Avoid some hash comparisons in CXFA_NodeHelper.

There is a perfectly good enum that we can use instead in some cases.
Split (with slight duplication) Name vs. Class searches since the
arguments are now of different types. This is easier to understand
in the end.

Change-Id: I79aed63d8f519bd4d899cf5c88589c2a46faa126
Reviewed-on: https://pdfium-review.googlesource.com/c/47334
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/xfa/cfxjse_resolveprocessor.cpp b/fxjs/xfa/cfxjse_resolveprocessor.cpp
index 9f165f5..c2a21a6 100644
--- a/fxjs/xfa/cfxjse_resolveprocessor.cpp
+++ b/fxjs/xfa/cfxjse_resolveprocessor.cpp
@@ -90,22 +90,23 @@
 }
 
 bool CFXJSE_ResolveProcessor::ResolveAnyChild(CFXJSE_ResolveNodeData& rnd) {
-  WideString wsName = rnd.m_wsName;
+  WideStringView wsName = rnd.m_wsName.AsStringView();
   WideString wsCondition = rnd.m_wsCondition;
   CXFA_Node* findNode = nullptr;
   bool bClassName = false;
   if (wsName.GetLength() && wsName[0] == '#') {
     bClassName = true;
-    wsName = wsName.Right(wsName.GetLength() - 1);
+    findNode = m_pNodeHelper->GetOneChildOfClass(
+        ToNode(rnd.m_CurObject), wsName.Right(wsName.GetLength() - 1));
+  } else {
+    findNode = m_pNodeHelper->GetOneChildNamed(ToNode(rnd.m_CurObject), wsName);
   }
-  findNode = m_pNodeHelper->GetOneChild(ToNode(rnd.m_CurObject), wsName.c_str(),
-                                        bClassName);
   if (!findNode)
     return false;
 
   if (wsCondition.IsEmpty()) {
     rnd.m_Objects.push_back(findNode);
-    return !rnd.m_Objects.empty();
+    return true;
   }
 
   std::vector<CXFA_Node*> tempNodes;
diff --git a/xfa/fxfa/parser/cxfa_nodehelper.cpp b/xfa/fxfa/parser/cxfa_nodehelper.cpp
index 0d4d09d..dc9b0ca 100644
--- a/xfa/fxfa/parser/cxfa_nodehelper.cpp
+++ b/xfa/fxfa/parser/cxfa_nodehelper.cpp
@@ -22,16 +22,74 @@
 
 CXFA_NodeHelper::~CXFA_NodeHelper() = default;
 
-CXFA_Node* CXFA_NodeHelper::GetOneChild(CXFA_Node* parent,
-                                        const wchar_t* pwsName,
-                                        bool bIsClassName) {
+CXFA_Node* CXFA_NodeHelper::GetOneChildNamed(CXFA_Node* parent,
+                                             WideStringView wsName) {
   if (!parent)
     return nullptr;
 
-  std::vector<CXFA_Node*> siblings;
-  uint32_t uNameHash = FX_HashCode_GetW(WideStringView(pwsName), false);
-  TraverseAnySiblings(parent, uNameHash, &siblings, bIsClassName);
-  return !siblings.empty() ? siblings[0] : nullptr;
+  return FindFirstSiblingNamed(parent, FX_HashCode_GetW(wsName, false));
+}
+
+CXFA_Node* CXFA_NodeHelper::GetOneChildOfClass(CXFA_Node* parent,
+                                               WideStringView wsClass) {
+  if (!parent)
+    return nullptr;
+
+  XFA_Element element = XFA_GetElementByName(wsClass);
+  if (element == XFA_Element::Unknown)
+    return nullptr;
+
+  return FindFirstSiblingOfClass(parent, element);
+}
+
+CXFA_Node* CXFA_NodeHelper::FindFirstSiblingNamed(CXFA_Node* parent,
+                                                  uint32_t dNameHash) {
+  CXFA_Node* result =
+      FindFirstSiblingNamedInList(parent, dNameHash, XFA_NODEFILTER_Properties);
+  if (result)
+    return result;
+
+  return FindFirstSiblingNamedInList(parent, dNameHash,
+                                     XFA_NODEFILTER_Children);
+}
+
+CXFA_Node* CXFA_NodeHelper::FindFirstSiblingNamedInList(CXFA_Node* parent,
+                                                        uint32_t dNameHash,
+                                                        uint32_t dwFilter) {
+  for (CXFA_Node* child : parent->GetNodeList(dwFilter, XFA_Element::Unknown)) {
+    if (child->GetNameHash() == dNameHash)
+      return child;
+
+    CXFA_Node* result = FindFirstSiblingNamed(child, dNameHash);
+    if (result)
+      return result;
+  }
+  return nullptr;
+}
+
+CXFA_Node* CXFA_NodeHelper::FindFirstSiblingOfClass(CXFA_Node* parent,
+                                                    XFA_Element element) {
+  CXFA_Node* result =
+      FindFirstSiblingOfClassInList(parent, element, XFA_NODEFILTER_Properties);
+  if (result)
+    return result;
+
+  return FindFirstSiblingOfClassInList(parent, element,
+                                       XFA_NODEFILTER_Children);
+}
+
+CXFA_Node* CXFA_NodeHelper::FindFirstSiblingOfClassInList(CXFA_Node* parent,
+                                                          XFA_Element element,
+                                                          uint32_t dwFilter) {
+  for (CXFA_Node* child : parent->GetNodeList(dwFilter, XFA_Element::Unknown)) {
+    if (child->GetElementType() == element)
+      return child;
+
+    CXFA_Node* result = FindFirstSiblingOfClass(child, element);
+    if (result)
+      return result;
+  }
+  return nullptr;
 }
 
 int32_t CXFA_NodeHelper::CountSiblings(CXFA_Node* pNode,
@@ -57,53 +115,6 @@
                           bIsClassName, true);
 }
 
-int32_t CXFA_NodeHelper::TraverseAnySiblings(CXFA_Node* parent,
-                                             uint32_t dNameHash,
-                                             std::vector<CXFA_Node*>* pSiblings,
-                                             bool bIsClassName) {
-  if (!parent || !pSiblings)
-    return 0;
-
-  int32_t nCount = 0;
-  for (CXFA_Node* child :
-       parent->GetNodeList(XFA_NODEFILTER_Properties, XFA_Element::Unknown)) {
-    if (bIsClassName) {
-      if (child->GetClassHashCode() == dNameHash) {
-        pSiblings->push_back(child);
-        nCount++;
-      }
-    } else {
-      if (child->GetNameHash() == dNameHash) {
-        pSiblings->push_back(child);
-        nCount++;
-      }
-    }
-    if (nCount > 0)
-      return nCount;
-
-    nCount += TraverseAnySiblings(child, dNameHash, pSiblings, bIsClassName);
-  }
-  for (CXFA_Node* child :
-       parent->GetNodeList(XFA_NODEFILTER_Children, XFA_Element::Unknown)) {
-    if (bIsClassName) {
-      if (child->GetClassHashCode() == dNameHash) {
-        pSiblings->push_back(child);
-        nCount++;
-      }
-    } else {
-      if (child->GetNameHash() == dNameHash) {
-        pSiblings->push_back(child);
-        nCount++;
-      }
-    }
-    if (nCount > 0)
-      return nCount;
-
-    nCount += TraverseAnySiblings(child, dNameHash, pSiblings, bIsClassName);
-  }
-  return nCount;
-}
-
 int32_t CXFA_NodeHelper::TraverseSiblings(CXFA_Node* parent,
                                           uint32_t dNameHash,
                                           std::vector<CXFA_Node*>* pSiblings,
diff --git a/xfa/fxfa/parser/cxfa_nodehelper.h b/xfa/fxfa/parser/cxfa_nodehelper.h
index ba9a6ba..2ebde22 100644
--- a/xfa/fxfa/parser/cxfa_nodehelper.h
+++ b/xfa/fxfa/parser/cxfa_nodehelper.h
@@ -26,20 +26,10 @@
   CXFA_NodeHelper();
   ~CXFA_NodeHelper();
 
-  CXFA_Node* GetOneChild(CXFA_Node* parent,
-                         const wchar_t* pwsName,
-                         bool bIsClassName);
+  CXFA_Node* GetOneChildNamed(CXFA_Node* parent, WideStringView wsName);
+  CXFA_Node* GetOneChildOfClass(CXFA_Node* parent, WideStringView wsClass);
+
   CXFA_Node* GetParent(CXFA_Node* pNode, XFA_LOGIC_TYPE eLogicType);
-  int32_t TraverseSiblings(CXFA_Node* parent,
-                           uint32_t dNameHash,
-                           std::vector<CXFA_Node*>* pSiblings,
-                           XFA_LOGIC_TYPE eLogicType,
-                           bool bIsClassName,
-                           bool bIsFindProperty);
-  int32_t TraverseAnySiblings(CXFA_Node* parent,
-                              uint32_t dNameHash,
-                              std::vector<CXFA_Node*>* pSiblings,
-                              bool bIsClassName);
   int32_t CountSiblings(CXFA_Node* pNode,
                         XFA_LOGIC_TYPE eLogicType,
                         std::vector<CXFA_Node*>* pSiblings,
@@ -64,6 +54,22 @@
   int32_t m_iCurAllStart = -1;
   UnownedPtr<CXFA_Node> m_pCreateParent;
   UnownedPtr<CXFA_Node> m_pAllStartParent;
+
+ private:
+  CXFA_Node* FindFirstSiblingNamed(CXFA_Node* parent, uint32_t dNameHash);
+  CXFA_Node* FindFirstSiblingNamedInList(CXFA_Node* parent,
+                                         uint32_t dwNameHash,
+                                         uint32_t dwFilter);
+  CXFA_Node* FindFirstSiblingOfClass(CXFA_Node* parent, XFA_Element element);
+  CXFA_Node* FindFirstSiblingOfClassInList(CXFA_Node* parent,
+                                           XFA_Element element,
+                                           uint32_t dwFilter);
+  int32_t TraverseSiblings(CXFA_Node* parent,
+                           uint32_t dNameHash,
+                           std::vector<CXFA_Node*>* pSiblings,
+                           XFA_LOGIC_TYPE eLogicType,
+                           bool bIsClassName,
+                           bool bIsFindProperty);
 };
 
 #endif  // XFA_FXFA_PARSER_CXFA_NODEHELPER_H_