summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BUILD.gn2
-rw-r--r--fxjs/cfxjse_formcalc_context.cpp92
-rw-r--r--fxjs/cjx_layoutpseudomodel.cpp2
-rw-r--r--xfa/fxfa/cxfa_ffdatetimeedit.cpp1
-rw-r--r--xfa/fxfa/cxfa_ffnumericedit.cpp1
-rw-r--r--xfa/fxfa/cxfa_ffpageview.h2
-rw-r--r--xfa/fxfa/cxfa_textprovider.cpp1
-rw-r--r--xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp1
-rw-r--r--xfa/fxfa/parser/cxfa_layoutpagemgr.cpp2
-rw-r--r--xfa/fxfa/parser/cxfa_node.cpp2
-rw-r--r--xfa/fxfa/parser/cxfa_nodeiteratortemplate.h129
-rw-r--r--xfa/fxfa/parser/cxfa_nodeiteratortemplate_unittest.cpp257
-rw-r--r--xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h2
-rw-r--r--xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h2
-rw-r--r--xfa/fxfa/parser/xfa_document_datamerger_imp.cpp1
-rw-r--r--xfa/fxfa/parser/xfa_utils.cpp84
-rw-r--r--xfa/fxfa/parser/xfa_utils.h120
-rw-r--r--xfa/fxfa/parser/xfa_utils_unittest.cpp249
18 files changed, 489 insertions, 461 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 3a62b707b8..3b7cabb307 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1850,6 +1850,7 @@ if (pdf_enable_xfa) {
"xfa/fxfa/parser/cxfa_node.h",
"xfa/fxfa/parser/cxfa_nodehelper.cpp",
"xfa/fxfa/parser/cxfa_nodehelper.h",
+ "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h",
"xfa/fxfa/parser/cxfa_nodelist.cpp",
"xfa/fxfa/parser/cxfa_nodelist.h",
"xfa/fxfa/parser/cxfa_nodelocale.cpp",
@@ -2016,6 +2017,7 @@ test("pdfium_unittests") {
"xfa/fxfa/fm2js/cxfa_fmlexer_unittest.cpp",
"xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp",
"xfa/fxfa/fm2js/cxfa_fmsimpleexpression_unittest.cpp",
+ "xfa/fxfa/parser/cxfa_nodeiteratortemplate_unittest.cpp",
"xfa/fxfa/parser/xfa_utils_unittest.cpp",
]
}
diff --git a/fxjs/cfxjse_formcalc_context.cpp b/fxjs/cfxjse_formcalc_context.cpp
index 55fab55722..30fa18737b 100644
--- a/fxjs/cfxjse_formcalc_context.cpp
+++ b/fxjs/cfxjse_formcalc_context.cpp
@@ -532,6 +532,90 @@ ByteString GUIDString(bool bSeparator) {
return bsStr;
}
+double ByteStringToDouble(const ByteStringView& szStringVal) {
+ WideString wsValue = WideString::FromUTF8(szStringVal);
+ wsValue.TrimLeft();
+ wsValue.TrimRight();
+
+ int32_t cc = 0;
+ bool bNegative = false;
+
+ const wchar_t* str = wsValue.c_str();
+ int32_t len = wsValue.GetLength();
+ if (str[0] == '+') {
+ cc++;
+ } else if (str[0] == '-') {
+ bNegative = true;
+ cc++;
+ }
+
+ int32_t nIntegralLen = 0;
+ int64_t nIntegral = 0;
+ while (cc < len) {
+ if (str[cc] == '.' || str[cc] == 'E' || str[cc] == 'e' ||
+ nIntegralLen > 17) {
+ break;
+ }
+ if (!FXSYS_isDecimalDigit(str[cc])) {
+ return 0;
+ }
+ nIntegral = nIntegral * 10 + str[cc] - '0';
+ cc++;
+ nIntegralLen++;
+ }
+ nIntegral = bNegative ? -nIntegral : nIntegral;
+
+ int32_t scale = 0;
+ double fraction = 0.0;
+ uint32_t dwFractional = 0;
+ if (cc < len && str[cc] == '.') {
+ cc++;
+ while (cc < len) {
+ fraction += XFA_GetFractionalScale(scale) * (str[cc] - '0');
+ scale++;
+ cc++;
+ if (cc == len)
+ break;
+ if (scale == XFA_GetMaxFractionalScale() || str[cc] == 'E' ||
+ str[cc] == 'e') {
+ break;
+ }
+ if (!FXSYS_isDecimalDigit(str[cc]))
+ return 0;
+ }
+ dwFractional = static_cast<uint32_t>(fraction * 4294967296.0);
+ }
+
+ int32_t nExponent = 0;
+ bool bExpSign = false;
+ if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) {
+ cc++;
+ if (cc < len) {
+ if (str[cc] == '+') {
+ cc++;
+ } else if (str[cc] == '-') {
+ bExpSign = true;
+ cc++;
+ }
+ }
+ while (cc < len) {
+ if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc]))
+ return 0;
+
+ nExponent = nExponent * 10 + str[cc] - '0';
+ cc++;
+ }
+ nExponent = bExpSign ? -nExponent : nExponent;
+ }
+
+ double dValue = dwFractional / 4294967296.0;
+ dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue);
+ if (nExponent != 0)
+ dValue *= FXSYS_pow(10, static_cast<float>(nExponent));
+
+ return dValue;
+}
+
} // namespace
// static
@@ -6005,8 +6089,10 @@ float CFXJSE_FormCalcContext::ValueToFloat(CFXJSE_Value* pThis,
GetObjectDefaultValue(arg, newPropertyValue.get());
return ValueToFloat(pThis, newPropertyValue.get());
}
- if (arg->IsString())
- return (float)XFA_ByteStringToDouble(arg->ToString().AsStringView());
+ if (arg->IsString()) {
+ return static_cast<float>(
+ ByteStringToDouble(arg->ToString().AsStringView()));
+ }
if (arg->IsUndefined())
return 0;
@@ -6040,7 +6126,7 @@ double CFXJSE_FormCalcContext::ValueToDouble(CFXJSE_Value* pThis,
return ValueToDouble(pThis, newPropertyValue.get());
}
if (arg->IsString())
- return XFA_ByteStringToDouble(arg->ToString().AsStringView());
+ return ByteStringToDouble(arg->ToString().AsStringView());
if (arg->IsUndefined())
return 0;
return arg->ToDouble();
diff --git a/fxjs/cjx_layoutpseudomodel.cpp b/fxjs/cjx_layoutpseudomodel.cpp
index 79e7fc8cf1..9767c15d3a 100644
--- a/fxjs/cjx_layoutpseudomodel.cpp
+++ b/fxjs/cjx_layoutpseudomodel.cpp
@@ -21,8 +21,8 @@
#include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
#include "xfa/fxfa/parser/cxfa_measurement.h"
#include "xfa/fxfa/parser/cxfa_node.h"
+#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
#include "xfa/fxfa/parser/cxfa_traversestrategy_contentlayoutitem.h"
-#include "xfa/fxfa/parser/xfa_utils.h"
CJX_LayoutPseudoModel::CJX_LayoutPseudoModel(CScript_LayoutPseudoModel* model)
: CJX_Object(model) {}
diff --git a/xfa/fxfa/cxfa_ffdatetimeedit.cpp b/xfa/fxfa/cxfa_ffdatetimeedit.cpp
index 65c32d517b..54878ae211 100644
--- a/xfa/fxfa/cxfa_ffdatetimeedit.cpp
+++ b/xfa/fxfa/cxfa_ffdatetimeedit.cpp
@@ -15,6 +15,7 @@
#include "xfa/fxfa/cxfa_eventparam.h"
#include "xfa/fxfa/cxfa_ffdoc.h"
#include "xfa/fxfa/parser/cxfa_localevalue.h"
+#include "xfa/fxfa/parser/xfa_utils.h"
CXFA_FFDateTimeEdit::CXFA_FFDateTimeEdit(CXFA_WidgetAcc* pDataAcc)
: CXFA_FFTextEdit(pDataAcc) {}
diff --git a/xfa/fxfa/cxfa_ffnumericedit.cpp b/xfa/fxfa/cxfa_ffnumericedit.cpp
index d6e1defca4..b8e9a1c4ea 100644
--- a/xfa/fxfa/cxfa_ffnumericedit.cpp
+++ b/xfa/fxfa/cxfa_ffnumericedit.cpp
@@ -13,6 +13,7 @@
#include "xfa/fwl/cfwl_notedriver.h"
#include "xfa/fxfa/cxfa_ffdoc.h"
#include "xfa/fxfa/parser/cxfa_localevalue.h"
+#include "xfa/fxfa/parser/xfa_utils.h"
CXFA_FFNumericEdit::CXFA_FFNumericEdit(CXFA_WidgetAcc* pDataAcc)
: CXFA_FFTextEdit(pDataAcc) {}
diff --git a/xfa/fxfa/cxfa_ffpageview.h b/xfa/fxfa/cxfa_ffpageview.h
index f99788505f..b33e25f79d 100644
--- a/xfa/fxfa/cxfa_ffpageview.h
+++ b/xfa/fxfa/cxfa_ffpageview.h
@@ -12,8 +12,8 @@
#include "xfa/fxfa/parser/cxfa_containerlayoutitem.h"
#include "xfa/fxfa/parser/cxfa_contentlayoutitem.h"
+#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
#include "xfa/fxfa/parser/cxfa_traversestrategy_layoutitem.h"
-#include "xfa/fxfa/parser/xfa_utils.h"
class CXFA_FFWidget;
class CXFA_FFDocView;
diff --git a/xfa/fxfa/cxfa_textprovider.cpp b/xfa/fxfa/cxfa_textprovider.cpp
index 165bc09f7e..d4ef35397e 100644
--- a/xfa/fxfa/cxfa_textprovider.cpp
+++ b/xfa/fxfa/cxfa_textprovider.cpp
@@ -31,6 +31,7 @@
#include "xfa/fxfa/parser/cxfa_localevalue.h"
#include "xfa/fxfa/parser/cxfa_node.h"
#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
+#include "xfa/fxfa/parser/xfa_utils.h"
CXFA_Node* CXFA_TextProvider::GetTextNode(bool& bRichText) {
bRichText = false;
diff --git a/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp
index 189a466e4f..c30c8dd575 100644
--- a/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp
+++ b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp
@@ -23,6 +23,7 @@
#include "xfa/fxfa/parser/cxfa_localemgr.h"
#include "xfa/fxfa/parser/cxfa_measurement.h"
#include "xfa/fxfa/parser/cxfa_node.h"
+#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
#include "xfa/fxfa/parser/cxfa_occurdata.h"
#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
#include "xfa/fxfa/parser/xfa_utils.h"
diff --git a/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp b/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp
index 57d71ffd89..4ecbd048ed 100644
--- a/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp
+++ b/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp
@@ -17,6 +17,7 @@
#include "xfa/fxfa/parser/cxfa_localemgr.h"
#include "xfa/fxfa/parser/cxfa_measurement.h"
#include "xfa/fxfa/parser/cxfa_node.h"
+#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
#include "xfa/fxfa/parser/cxfa_object.h"
#include "xfa/fxfa/parser/cxfa_traversestrategy_contentareacontainerlayoutitem.h"
#include "xfa/fxfa/parser/cxfa_traversestrategy_layoutitem.h"
@@ -24,7 +25,6 @@
#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
#include "xfa/fxfa/parser/xfa_document_datamerger_imp.h"
#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
-#include "xfa/fxfa/parser/xfa_utils.h"
namespace {
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp
index c906d26bda..07d9f84916 100644
--- a/xfa/fxfa/parser/cxfa_node.cpp
+++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -32,10 +32,12 @@
#include "xfa/fxfa/parser/cxfa_document.h"
#include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
#include "xfa/fxfa/parser/cxfa_measurement.h"
+#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
#include "xfa/fxfa/parser/cxfa_occurdata.h"
#include "xfa/fxfa/parser/cxfa_simple_parser.h"
#include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h"
#include "xfa/fxfa/parser/xfa_basic_data.h"
+#include "xfa/fxfa/parser/xfa_utils.h"
namespace {
diff --git a/xfa/fxfa/parser/cxfa_nodeiteratortemplate.h b/xfa/fxfa/parser/cxfa_nodeiteratortemplate.h
new file mode 100644
index 0000000000..214f38e501
--- /dev/null
+++ b/xfa/fxfa/parser/cxfa_nodeiteratortemplate.h
@@ -0,0 +1,129 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_FXFA_PARSER_CXFA_NODEITERATORTEMPLATE_H_
+#define XFA_FXFA_PARSER_CXFA_NODEITERATORTEMPLATE_H_
+
+template <class NodeType, class TraverseStrategy>
+class CXFA_NodeIteratorTemplate {
+ public:
+ explicit CXFA_NodeIteratorTemplate(NodeType* pRoot)
+ : m_pRoot(pRoot), m_pCurrent(pRoot) {}
+
+ NodeType* GetRoot() const { return m_pRoot; }
+ NodeType* GetCurrent() const { return m_pCurrent; }
+
+ void Reset() { m_pCurrent = m_pRoot; }
+ bool SetCurrent(NodeType* pNode) {
+ if (!RootReachableFromNode(pNode)) {
+ m_pCurrent = nullptr;
+ return false;
+ }
+ m_pCurrent = pNode;
+ return true;
+ }
+
+ NodeType* MoveToPrev() {
+ if (!m_pRoot)
+ return nullptr;
+ if (!m_pCurrent) {
+ m_pCurrent = LastDescendant(m_pRoot);
+ return m_pCurrent;
+ }
+ NodeType* pSibling = PreviousSiblingWithinSubtree(m_pCurrent);
+ if (pSibling) {
+ m_pCurrent = LastDescendant(pSibling);
+ return m_pCurrent;
+ }
+ NodeType* pParent = ParentWithinSubtree(m_pCurrent);
+ if (pParent) {
+ m_pCurrent = pParent;
+ return m_pCurrent;
+ }
+ return nullptr;
+ }
+
+ NodeType* MoveToNext() {
+ if (!m_pRoot || !m_pCurrent)
+ return nullptr;
+ NodeType* pChild = TraverseStrategy::GetFirstChild(m_pCurrent);
+ if (pChild) {
+ m_pCurrent = pChild;
+ return m_pCurrent;
+ }
+ return SkipChildrenAndMoveToNext();
+ }
+
+ NodeType* SkipChildrenAndMoveToNext() {
+ if (!m_pRoot)
+ return nullptr;
+ NodeType* pNode = m_pCurrent;
+ while (pNode) {
+ NodeType* pSibling = NextSiblingWithinSubtree(pNode);
+ if (pSibling) {
+ m_pCurrent = pSibling;
+ return m_pCurrent;
+ }
+ pNode = ParentWithinSubtree(pNode);
+ }
+ m_pCurrent = nullptr;
+ return m_pCurrent;
+ }
+
+ private:
+ bool RootReachableFromNode(NodeType* pNode) {
+ if (!pNode)
+ return false;
+ if (pNode == m_pRoot)
+ return true;
+ return RootReachableFromNode(TraverseStrategy::GetParent(pNode));
+ }
+
+ NodeType* ParentWithinSubtree(NodeType* pNode) {
+ if (!pNode || pNode == m_pRoot)
+ return nullptr;
+ return TraverseStrategy::GetParent(pNode);
+ }
+
+ NodeType* NextSiblingWithinSubtree(NodeType* pNode) {
+ if (pNode == m_pRoot)
+ return nullptr;
+ return TraverseStrategy::GetNextSibling(pNode);
+ }
+
+ NodeType* PreviousSiblingWithinSubtree(NodeType* pNode) {
+ NodeType* pParent = ParentWithinSubtree(pNode);
+ if (!pParent)
+ return nullptr;
+ NodeType* pCurrent = TraverseStrategy::GetFirstChild(pParent);
+ NodeType* pPrevious = nullptr;
+ while (pCurrent != pNode) {
+ pPrevious = pCurrent;
+ pCurrent = TraverseStrategy::GetNextSibling(pCurrent);
+ }
+ return pPrevious;
+ }
+
+ NodeType* LastChild(NodeType* pNode) {
+ NodeType* pPrevious = nullptr;
+ NodeType* pChild = TraverseStrategy::GetFirstChild(pNode);
+ while (pChild) {
+ pPrevious = pChild;
+ pChild = NextSiblingWithinSubtree(pChild);
+ }
+ return pPrevious;
+ }
+
+ NodeType* LastDescendant(NodeType* pNode) {
+ NodeType* pChild = LastChild(pNode);
+ return pChild ? LastDescendant(pChild) : pNode;
+ }
+
+ NodeType* m_pRoot;
+ NodeType* m_pCurrent;
+};
+
+#endif // XFA_FXFA_PARSER_CXFA_NODEITERATORTEMPLATE_H_
diff --git a/xfa/fxfa/parser/cxfa_nodeiteratortemplate_unittest.cpp b/xfa/fxfa/parser/cxfa_nodeiteratortemplate_unittest.cpp
new file mode 100644
index 0000000000..114bed0f78
--- /dev/null
+++ b/xfa/fxfa/parser/cxfa_nodeiteratortemplate_unittest.cpp
@@ -0,0 +1,257 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
+
+#include <memory>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/test_support.h"
+#include "third_party/base/ptr_util.h"
+
+class CXFA_NodeIteratorTemplateTest : public testing::Test {
+ public:
+ class Node {
+ public:
+ class Strategy {
+ public:
+ static Node* GetFirstChild(Node* pNode) {
+ return pNode && !pNode->children_.empty() ? pNode->children_.front()
+ : nullptr;
+ }
+ static Node* GetNextSibling(Node* pNode) {
+ return pNode ? pNode->next_sibling_ : nullptr;
+ }
+ static Node* GetParent(Node* pNode) {
+ return pNode ? pNode->parent_ : nullptr;
+ }
+ };
+
+ explicit Node(Node* parent) : parent_(parent), next_sibling_(nullptr) {
+ if (parent) {
+ if (!parent->children_.empty())
+ parent->children_.back()->next_sibling_ = this;
+ parent->children_.push_back(this);
+ }
+ }
+
+ private:
+ Node* parent_;
+ Node* next_sibling_;
+ std::vector<Node*> children_;
+ };
+
+ using Iterator = CXFA_NodeIteratorTemplate<Node, Node::Strategy>;
+
+ // Builds a tree along the lines of:
+ //
+ // root
+ // |
+ // child1--child2
+ // |
+ // child3------------child7--child9
+ // | |
+ // child4--child6 child8
+ // |
+ // child5
+ //
+ void SetUp() override {
+ root_ = pdfium::MakeUnique<Node>(nullptr);
+ child1_ = pdfium::MakeUnique<Node>(root_.get());
+ child2_ = pdfium::MakeUnique<Node>(root_.get());
+ child3_ = pdfium::MakeUnique<Node>(child2_.get());
+ child4_ = pdfium::MakeUnique<Node>(child3_.get());
+ child5_ = pdfium::MakeUnique<Node>(child4_.get());
+ child6_ = pdfium::MakeUnique<Node>(child3_.get());
+ child7_ = pdfium::MakeUnique<Node>(child2_.get());
+ child8_ = pdfium::MakeUnique<Node>(child7_.get());
+ child9_ = pdfium::MakeUnique<Node>(child2_.get());
+ }
+
+ Node* root() const { return root_.get(); }
+ Node* child1() const { return child1_.get(); }
+ Node* child2() const { return child2_.get(); }
+ Node* child3() const { return child3_.get(); }
+ Node* child4() const { return child4_.get(); }
+ Node* child5() const { return child5_.get(); }
+ Node* child6() const { return child6_.get(); }
+ Node* child7() const { return child7_.get(); }
+ Node* child8() const { return child8_.get(); }
+ Node* child9() const { return child9_.get(); }
+
+ protected:
+ std::unique_ptr<Node> root_;
+ std::unique_ptr<Node> child1_;
+ std::unique_ptr<Node> child2_;
+ std::unique_ptr<Node> child3_;
+ std::unique_ptr<Node> child4_;
+ std::unique_ptr<Node> child5_;
+ std::unique_ptr<Node> child6_;
+ std::unique_ptr<Node> child7_;
+ std::unique_ptr<Node> child8_;
+ std::unique_ptr<Node> child9_;
+};
+
+TEST_F(CXFA_NodeIteratorTemplateTest, Empty) {
+ Iterator iter(nullptr);
+ EXPECT_EQ(nullptr, iter.GetRoot());
+ EXPECT_EQ(nullptr, iter.GetCurrent());
+ EXPECT_EQ(nullptr, iter.MoveToNext());
+ EXPECT_EQ(nullptr, iter.MoveToPrev());
+ EXPECT_EQ(nullptr, iter.SkipChildrenAndMoveToNext());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, Root) {
+ Iterator iter(root());
+ EXPECT_EQ(root(), iter.GetRoot());
+ EXPECT_EQ(root(), iter.GetCurrent());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, Current) {
+ Iterator iter(root());
+ iter.SetCurrent(child1());
+ EXPECT_EQ(root(), iter.GetRoot());
+ EXPECT_EQ(child1(), iter.GetCurrent());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, CurrentOutsideRootDisallowed) {
+ Iterator iter(child1());
+ iter.SetCurrent(root());
+ EXPECT_EQ(child1(), iter.GetRoot());
+ EXPECT_EQ(nullptr, iter.GetCurrent());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, CurrentNull) {
+ Iterator iter(root());
+ EXPECT_EQ(child1(), iter.MoveToNext());
+
+ iter.SetCurrent(nullptr);
+ EXPECT_EQ(nullptr, iter.GetCurrent());
+
+ EXPECT_EQ(nullptr, iter.MoveToNext());
+ EXPECT_EQ(nullptr, iter.GetCurrent());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, MoveToPrev) {
+ Iterator iter(root());
+ iter.SetCurrent(child9());
+
+ EXPECT_EQ(child8(), iter.MoveToPrev());
+ EXPECT_EQ(child8(), iter.GetCurrent());
+
+ EXPECT_EQ(child7(), iter.MoveToPrev());
+ EXPECT_EQ(child7(), iter.GetCurrent());
+
+ EXPECT_EQ(child6(), iter.MoveToPrev());
+ EXPECT_EQ(child6(), iter.GetCurrent());
+
+ EXPECT_EQ(child5(), iter.MoveToPrev());
+ EXPECT_EQ(child5(), iter.GetCurrent());
+
+ EXPECT_EQ(child4(), iter.MoveToPrev());
+ EXPECT_EQ(child4(), iter.GetCurrent());
+
+ EXPECT_EQ(child3(), iter.MoveToPrev());
+ EXPECT_EQ(child3(), iter.GetCurrent());
+
+ EXPECT_EQ(child2(), iter.MoveToPrev());
+ EXPECT_EQ(child2(), iter.GetCurrent());
+
+ EXPECT_EQ(child1(), iter.MoveToPrev());
+ EXPECT_EQ(child1(), iter.GetCurrent());
+
+ EXPECT_EQ(root(), iter.MoveToPrev());
+ EXPECT_EQ(root(), iter.GetCurrent());
+
+ EXPECT_EQ(nullptr, iter.MoveToPrev());
+ EXPECT_EQ(root(), iter.GetCurrent());
+
+ EXPECT_EQ(nullptr, iter.MoveToPrev());
+ EXPECT_EQ(root(), iter.GetCurrent());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, MoveToNext) {
+ Iterator iter(root());
+ iter.SetCurrent(child2());
+
+ EXPECT_EQ(child3(), iter.MoveToNext());
+ EXPECT_EQ(child3(), iter.GetCurrent());
+
+ EXPECT_EQ(child4(), iter.MoveToNext());
+ EXPECT_EQ(child4(), iter.GetCurrent());
+
+ EXPECT_EQ(child5(), iter.MoveToNext());
+ EXPECT_EQ(child5(), iter.GetCurrent());
+
+ EXPECT_EQ(child6(), iter.MoveToNext());
+ EXPECT_EQ(child6(), iter.GetCurrent());
+
+ EXPECT_EQ(child7(), iter.MoveToNext());
+ EXPECT_EQ(child7(), iter.GetCurrent());
+
+ EXPECT_EQ(child8(), iter.MoveToNext());
+ EXPECT_EQ(child8(), iter.GetCurrent());
+
+ EXPECT_EQ(child9(), iter.MoveToNext());
+ EXPECT_EQ(child9(), iter.GetCurrent());
+
+ EXPECT_EQ(nullptr, iter.MoveToNext());
+ EXPECT_EQ(nullptr, iter.GetCurrent());
+
+ EXPECT_EQ(nullptr, iter.MoveToNext());
+ EXPECT_EQ(nullptr, iter.GetCurrent());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, SkipChildrenAndMoveToNext) {
+ Iterator iter(root());
+ iter.SetCurrent(child3());
+ EXPECT_EQ(child7(), iter.SkipChildrenAndMoveToNext());
+ EXPECT_EQ(child9(), iter.SkipChildrenAndMoveToNext());
+ EXPECT_EQ(nullptr, iter.SkipChildrenAndMoveToNext());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, BackAndForth) {
+ Iterator iter(root());
+ EXPECT_EQ(child1(), iter.MoveToNext());
+ EXPECT_EQ(child2(), iter.MoveToNext());
+ EXPECT_EQ(child3(), iter.MoveToNext());
+ EXPECT_EQ(child4(), iter.MoveToNext());
+ EXPECT_EQ(child5(), iter.MoveToNext());
+ EXPECT_EQ(child4(), iter.MoveToPrev());
+ EXPECT_EQ(child3(), iter.MoveToPrev());
+ EXPECT_EQ(child2(), iter.MoveToPrev());
+ EXPECT_EQ(child1(), iter.MoveToPrev());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, NextFromBeforeTheBeginning) {
+ Iterator iter(root());
+ EXPECT_EQ(nullptr, iter.MoveToPrev());
+ EXPECT_EQ(root(), iter.GetCurrent());
+ EXPECT_EQ(child1(), iter.MoveToNext());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, PrevFromAfterTheEnd) {
+ Iterator iter(root());
+ iter.SetCurrent(child9());
+ EXPECT_EQ(nullptr, iter.MoveToNext());
+ EXPECT_EQ(child9(), iter.MoveToPrev());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, ChildAsRootPrev) {
+ Iterator iter(child3());
+ EXPECT_EQ(nullptr, iter.MoveToPrev());
+
+ iter.SetCurrent(child4());
+ EXPECT_EQ(child3(), iter.MoveToPrev());
+ EXPECT_EQ(nullptr, iter.MoveToPrev());
+}
+
+TEST_F(CXFA_NodeIteratorTemplateTest, ChildAsRootNext) {
+ Iterator iter(child3());
+ iter.SetCurrent(child4());
+ EXPECT_EQ(child5(), iter.MoveToNext());
+ EXPECT_EQ(child6(), iter.MoveToNext());
+ EXPECT_EQ(nullptr, iter.MoveToNext());
+}
diff --git a/xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h b/xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h
index d507c262fe..ce6463c700 100644
--- a/xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h
+++ b/xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h
@@ -8,7 +8,7 @@
#define XFA_FXFA_PARSER_CXFA_TRAVERSESTRATEGY_XFACONTAINERNODE_H_
#include "xfa/fxfa/parser/cxfa_node.h"
-#include "xfa/fxfa/parser/xfa_utils.h"
+#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
class CXFA_TraverseStrategy_XFAContainerNode {
public:
diff --git a/xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h b/xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h
index b6fb156cb9..7fab43c9bc 100644
--- a/xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h
+++ b/xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h
@@ -7,7 +7,7 @@
#ifndef XFA_FXFA_PARSER_CXFA_TRAVERSESTRATEGY_XFANODE_H_
#define XFA_FXFA_PARSER_CXFA_TRAVERSESTRATEGY_XFANODE_H_
-#include "xfa/fxfa/parser/xfa_utils.h"
+#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
class CXFA_TraverseStrategy_XFANode {
public:
diff --git a/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp b/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp
index 128ad7b2ad..94c82f85e8 100644
--- a/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp
+++ b/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp
@@ -19,6 +19,7 @@
#include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
#include "xfa/fxfa/parser/cxfa_localemgr.h"
#include "xfa/fxfa/parser/cxfa_node.h"
+#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
#include "xfa/fxfa/parser/cxfa_occurdata.h"
#include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h"
#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
diff --git a/xfa/fxfa/parser/xfa_utils.cpp b/xfa/fxfa/parser/xfa_utils.cpp
index 5bdfe5853b..588246fc55 100644
--- a/xfa/fxfa/parser/xfa_utils.cpp
+++ b/xfa/fxfa/parser/xfa_utils.cpp
@@ -39,85 +39,6 @@ const double fraction_scales[] = {0.1,
0.000000000000001,
0.0000000000000001};
-double WideStringToDouble(const WideString& wsStringVal) {
- WideString wsValue = wsStringVal;
- wsValue.TrimLeft();
- wsValue.TrimRight();
- int64_t nIntegral = 0;
- uint32_t dwFractional = 0;
- int32_t nExponent = 0;
- int32_t cc = 0;
- bool bNegative = false;
- bool bExpSign = false;
- const wchar_t* str = wsValue.c_str();
- int32_t len = wsValue.GetLength();
- if (str[0] == '+') {
- cc++;
- } else if (str[0] == '-') {
- bNegative = true;
- cc++;
- }
- int32_t nIntegralLen = 0;
- while (cc < len) {
- if (str[cc] == '.' || str[cc] == 'E' || str[cc] == 'e' ||
- nIntegralLen > 17) {
- break;
- }
- if (!FXSYS_isDecimalDigit(str[cc])) {
- return 0;
- }
- nIntegral = nIntegral * 10 + str[cc] - '0';
- cc++;
- nIntegralLen++;
- }
- nIntegral = bNegative ? -nIntegral : nIntegral;
- int32_t scale = 0;
- double fraction = 0.0;
- if (cc < len && str[cc] == '.') {
- cc++;
- while (cc < len) {
- fraction += XFA_GetFractionalScale(scale) * (str[cc] - '0');
- scale++;
- cc++;
- if (cc == len)
- break;
- if (scale == XFA_GetMaxFractionalScale() || str[cc] == 'E' ||
- str[cc] == 'e') {
- break;
- }
- if (!FXSYS_isDecimalDigit(str[cc]))
- return 0;
- }
- dwFractional = static_cast<uint32_t>(fraction * 4294967296.0);
- }
- if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) {
- cc++;
- if (cc < len) {
- if (str[cc] == '+') {
- cc++;
- } else if (str[cc] == '-') {
- bExpSign = true;
- cc++;
- }
- }
- while (cc < len) {
- if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc]))
- return 0;
-
- nExponent = nExponent * 10 + str[cc] - '0';
- cc++;
- }
- nExponent = bExpSign ? -nExponent : nExponent;
- }
-
- double dValue = dwFractional / 4294967296.0;
- dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue);
- if (nExponent != 0)
- dValue *= FXSYS_pow(10, static_cast<float>(nExponent));
-
- return dValue;
-}
-
} // namespace
double XFA_GetFractionalScale(uint32_t idx) {
@@ -228,11 +149,6 @@ bool XFA_FieldIsMultiListBox(CXFA_Node* pFieldNode) {
return bRet;
}
-double XFA_ByteStringToDouble(const ByteStringView& szStringVal) {
- WideString wsValue = WideString::FromUTF8(szStringVal);
- return WideStringToDouble(wsValue);
-}
-
int32_t XFA_MapRotation(int32_t nRotation) {
nRotation = nRotation % 360;
nRotation = nRotation < 0 ? nRotation + 360 : nRotation;
diff --git a/xfa/fxfa/parser/xfa_utils.h b/xfa/fxfa/parser/xfa_utils.h
index cfa27bbccd..b00f7aace6 100644
--- a/xfa/fxfa/parser/xfa_utils.h
+++ b/xfa/fxfa/parser/xfa_utils.h
@@ -23,127 +23,7 @@ bool XFA_FDEExtension_ResolveNamespaceQualifier(CFX_XMLElement* pNode,
const WideString& wsQualifier,
WideString* wsNamespaceURI);
-template <class NodeType, class TraverseStrategy>
-class CXFA_NodeIteratorTemplate {
- public:
- explicit CXFA_NodeIteratorTemplate(NodeType* pRoot)
- : m_pRoot(pRoot), m_pCurrent(pRoot) {}
-
- NodeType* GetRoot() const { return m_pRoot; }
- NodeType* GetCurrent() const { return m_pCurrent; }
-
- void Reset() { m_pCurrent = m_pRoot; }
- bool SetCurrent(NodeType* pNode) {
- if (!RootReachableFromNode(pNode)) {
- m_pCurrent = nullptr;
- return false;
- }
- m_pCurrent = pNode;
- return true;
- }
-
- NodeType* MoveToPrev() {
- if (!m_pRoot)
- return nullptr;
- if (!m_pCurrent) {
- m_pCurrent = LastDescendant(m_pRoot);
- return m_pCurrent;
- }
- NodeType* pSibling = PreviousSiblingWithinSubtree(m_pCurrent);
- if (pSibling) {
- m_pCurrent = LastDescendant(pSibling);
- return m_pCurrent;
- }
- NodeType* pParent = ParentWithinSubtree(m_pCurrent);
- if (pParent) {
- m_pCurrent = pParent;
- return m_pCurrent;
- }
- return nullptr;
- }
-
- NodeType* MoveToNext() {
- if (!m_pRoot || !m_pCurrent)
- return nullptr;
- NodeType* pChild = TraverseStrategy::GetFirstChild(m_pCurrent);
- if (pChild) {
- m_pCurrent = pChild;
- return m_pCurrent;
- }
- return SkipChildrenAndMoveToNext();
- }
-
- NodeType* SkipChildrenAndMoveToNext() {
- if (!m_pRoot)
- return nullptr;
- NodeType* pNode = m_pCurrent;
- while (pNode) {
- NodeType* pSibling = NextSiblingWithinSubtree(pNode);
- if (pSibling) {
- m_pCurrent = pSibling;
- return m_pCurrent;
- }
- pNode = ParentWithinSubtree(pNode);
- }
- m_pCurrent = nullptr;
- return m_pCurrent;
- }
-
- private:
- bool RootReachableFromNode(NodeType* pNode) {
- if (!pNode)
- return false;
- if (pNode == m_pRoot)
- return true;
- return RootReachableFromNode(TraverseStrategy::GetParent(pNode));
- }
-
- NodeType* ParentWithinSubtree(NodeType* pNode) {
- if (!pNode || pNode == m_pRoot)
- return nullptr;
- return TraverseStrategy::GetParent(pNode);
- }
-
- NodeType* NextSiblingWithinSubtree(NodeType* pNode) {
- if (pNode == m_pRoot)
- return nullptr;
- return TraverseStrategy::GetNextSibling(pNode);
- }
-
- NodeType* PreviousSiblingWithinSubtree(NodeType* pNode) {
- NodeType* pParent = ParentWithinSubtree(pNode);
- if (!pParent)
- return nullptr;
- NodeType* pCurrent = TraverseStrategy::GetFirstChild(pParent);
- NodeType* pPrevious = nullptr;
- while (pCurrent != pNode) {
- pPrevious = pCurrent;
- pCurrent = TraverseStrategy::GetNextSibling(pCurrent);
- }
- return pPrevious;
- }
-
- NodeType* LastChild(NodeType* pNode) {
- NodeType* pPrevious = nullptr;
- NodeType* pChild = TraverseStrategy::GetFirstChild(pNode);
- while (pChild) {
- pPrevious = pChild;
- pChild = NextSiblingWithinSubtree(pChild);
- }
- return pPrevious;
- }
-
- NodeType* LastDescendant(NodeType* pNode) {
- NodeType* pChild = LastChild(pNode);
- return pChild ? LastDescendant(pChild) : pNode;
- }
-
- NodeType* m_pRoot;
- NodeType* m_pCurrent;
-};
-
CXFA_LocaleValue XFA_GetLocaleValue(CXFA_WidgetData* pWidgetData);
-double XFA_ByteStringToDouble(const ByteStringView& szStringVal);
int32_t XFA_MapRotation(int32_t nRotation);
bool XFA_RecognizeRichText(CFX_XMLElement* pRichTextXMLNode);
diff --git a/xfa/fxfa/parser/xfa_utils_unittest.cpp b/xfa/fxfa/parser/xfa_utils_unittest.cpp
index ab344c4f6c..bd2c89d554 100644
--- a/xfa/fxfa/parser/xfa_utils_unittest.cpp
+++ b/xfa/fxfa/parser/xfa_utils_unittest.cpp
@@ -4,12 +4,8 @@
#include "xfa/fxfa/parser/xfa_utils.h"
-#include <memory>
-#include <vector>
-
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/test_support.h"
-#include "third_party/base/ptr_util.h"
TEST(XfaUtilsImpTest, XFA_MapRotation) {
struct TestCase {
@@ -27,251 +23,6 @@ TEST(XfaUtilsImpTest, XFA_MapRotation) {
}
}
-class XFANodeIteratorTest : public testing::Test {
- public:
- class Node {
- public:
- class Strategy {
- public:
- static Node* GetFirstChild(Node* pNode) {
- return pNode && !pNode->children_.empty() ? pNode->children_.front()
- : nullptr;
- }
- static Node* GetNextSibling(Node* pNode) {
- return pNode ? pNode->next_sibling_ : nullptr;
- }
- static Node* GetParent(Node* pNode) {
- return pNode ? pNode->parent_ : nullptr;
- }
- };
-
- explicit Node(Node* parent) : parent_(parent), next_sibling_(nullptr) {
- if (parent) {
- if (!parent->children_.empty())
- parent->children_.back()->next_sibling_ = this;
- parent->children_.push_back(this);
- }
- }
-
- private:
- Node* parent_;
- Node* next_sibling_;
- std::vector<Node*> children_;
- };
-
- using Iterator = CXFA_NodeIteratorTemplate<Node, Node::Strategy>;
-
- // Builds a tree along the lines of:
- //
- // root
- // |
- // child1--child2
- // |
- // child3------------child7--child9
- // | |
- // child4--child6 child8
- // |
- // child5
- //
- void SetUp() override {
- root_ = pdfium::MakeUnique<Node>(nullptr);
- child1_ = pdfium::MakeUnique<Node>(root_.get());
- child2_ = pdfium::MakeUnique<Node>(root_.get());
- child3_ = pdfium::MakeUnique<Node>(child2_.get());
- child4_ = pdfium::MakeUnique<Node>(child3_.get());
- child5_ = pdfium::MakeUnique<Node>(child4_.get());
- child6_ = pdfium::MakeUnique<Node>(child3_.get());
- child7_ = pdfium::MakeUnique<Node>(child2_.get());
- child8_ = pdfium::MakeUnique<Node>(child7_.get());
- child9_ = pdfium::MakeUnique<Node>(child2_.get());
- }
-
- Node* root() const { return root_.get(); }
- Node* child1() const { return child1_.get(); }
- Node* child2() const { return child2_.get(); }
- Node* child3() const { return child3_.get(); }
- Node* child4() const { return child4_.get(); }
- Node* child5() const { return child5_.get(); }
- Node* child6() const { return child6_.get(); }
- Node* child7() const { return child7_.get(); }
- Node* child8() const { return child8_.get(); }
- Node* child9() const { return child9_.get(); }
-
- protected:
- std::unique_ptr<Node> root_;
- std::unique_ptr<Node> child1_;
- std::unique_ptr<Node> child2_;
- std::unique_ptr<Node> child3_;
- std::unique_ptr<Node> child4_;
- std::unique_ptr<Node> child5_;
- std::unique_ptr<Node> child6_;
- std::unique_ptr<Node> child7_;
- std::unique_ptr<Node> child8_;
- std::unique_ptr<Node> child9_;
-};
-
-TEST_F(XFANodeIteratorTest, Empty) {
- Iterator iter(nullptr);
- EXPECT_EQ(nullptr, iter.GetRoot());
- EXPECT_EQ(nullptr, iter.GetCurrent());
- EXPECT_EQ(nullptr, iter.MoveToNext());
- EXPECT_EQ(nullptr, iter.MoveToPrev());
- EXPECT_EQ(nullptr, iter.SkipChildrenAndMoveToNext());
-}
-
-TEST_F(XFANodeIteratorTest, Root) {
- Iterator iter(root());
- EXPECT_EQ(root(), iter.GetRoot());
- EXPECT_EQ(root(), iter.GetCurrent());
-}
-
-TEST_F(XFANodeIteratorTest, Current) {
- Iterator iter(root());
- iter.SetCurrent(child1());
- EXPECT_EQ(root(), iter.GetRoot());
- EXPECT_EQ(child1(), iter.GetCurrent());
-}
-
-TEST_F(XFANodeIteratorTest, CurrentOutsideRootDisallowed) {
- Iterator iter(child1());
- iter.SetCurrent(root());
- EXPECT_EQ(child1(), iter.GetRoot());
- EXPECT_EQ(nullptr, iter.GetCurrent());
-}
-
-TEST_F(XFANodeIteratorTest, CurrentNull) {
- Iterator iter(root());
- EXPECT_EQ(child1(), iter.MoveToNext());
-
- iter.SetCurrent(nullptr);
- EXPECT_EQ(nullptr, iter.GetCurrent());
-
- EXPECT_EQ(nullptr, iter.MoveToNext());
- EXPECT_EQ(nullptr, iter.GetCurrent());
-}
-
-TEST_F(XFANodeIteratorTest, MoveToPrev) {
- Iterator iter(root());
- iter.SetCurrent(child9());
-
- EXPECT_EQ(child8(), iter.MoveToPrev());
- EXPECT_EQ(child8(), iter.GetCurrent());
-
- EXPECT_EQ(child7(), iter.MoveToPrev());
- EXPECT_EQ(child7(), iter.GetCurrent());
-
- EXPECT_EQ(child6(), iter.MoveToPrev());
- EXPECT_EQ(child6(), iter.GetCurrent());
-
- EXPECT_EQ(child5(), iter.MoveToPrev());
- EXPECT_EQ(child5(), iter.GetCurrent());
-
- EXPECT_EQ(child4(), iter.MoveToPrev());
- EXPECT_EQ(child4(), iter.GetCurrent());
-
- EXPECT_EQ(child3(), iter.MoveToPrev());
- EXPECT_EQ(child3(), iter.GetCurrent());
-
- EXPECT_EQ(child2(), iter.MoveToPrev());
- EXPECT_EQ(child2(), iter.GetCurrent());
-
- EXPECT_EQ(child1(), iter.MoveToPrev());
- EXPECT_EQ(child1(), iter.GetCurrent());
-
- EXPECT_EQ(root(), iter.MoveToPrev());
- EXPECT_EQ(root(), iter.GetCurrent());
-
- EXPECT_EQ(nullptr, iter.MoveToPrev());
- EXPECT_EQ(root(), iter.GetCurrent());
-
- EXPECT_EQ(nullptr, iter.MoveToPrev());
- EXPECT_EQ(root(), iter.GetCurrent());
-}
-
-TEST_F(XFANodeIteratorTest, MoveToNext) {
- Iterator iter(root());
- iter.SetCurrent(child2());
-
- EXPECT_EQ(child3(), iter.MoveToNext());
- EXPECT_EQ(child3(), iter.GetCurrent());
-
- EXPECT_EQ(child4(), iter.MoveToNext());
- EXPECT_EQ(child4(), iter.GetCurrent());
-
- EXPECT_EQ(child5(), iter.MoveToNext());
- EXPECT_EQ(child5(), iter.GetCurrent());
-
- EXPECT_EQ(child6(), iter.MoveToNext());
- EXPECT_EQ(child6(), iter.GetCurrent());
-
- EXPECT_EQ(child7(), iter.MoveToNext());
- EXPECT_EQ(child7(), iter.GetCurrent());
-
- EXPECT_EQ(child8(), iter.MoveToNext());
- EXPECT_EQ(child8(), iter.GetCurrent());
-
- EXPECT_EQ(child9(), iter.MoveToNext());
- EXPECT_EQ(child9(), iter.GetCurrent());
-
- EXPECT_EQ(nullptr, iter.MoveToNext());
- EXPECT_EQ(nullptr, iter.GetCurrent());
-
- EXPECT_EQ(nullptr, iter.MoveToNext());
- EXPECT_EQ(nullptr, iter.GetCurrent());
-}
-
-TEST_F(XFANodeIteratorTest, SkipChildrenAndMoveToNext) {
- Iterator iter(root());
- iter.SetCurrent(child3());
- EXPECT_EQ(child7(), iter.SkipChildrenAndMoveToNext());
- EXPECT_EQ(child9(), iter.SkipChildrenAndMoveToNext());
- EXPECT_EQ(nullptr, iter.SkipChildrenAndMoveToNext());
-}
-
-TEST_F(XFANodeIteratorTest, BackAndForth) {
- Iterator iter(root());
- EXPECT_EQ(child1(), iter.MoveToNext());
- EXPECT_EQ(child2(), iter.MoveToNext());
- EXPECT_EQ(child3(), iter.MoveToNext());
- EXPECT_EQ(child4(), iter.MoveToNext());
- EXPECT_EQ(child5(), iter.MoveToNext());
- EXPECT_EQ(child4(), iter.MoveToPrev());
- EXPECT_EQ(child3(), iter.MoveToPrev());
- EXPECT_EQ(child2(), iter.MoveToPrev());
- EXPECT_EQ(child1(), iter.MoveToPrev());
-}
-
-TEST_F(XFANodeIteratorTest, NextFromBeforeTheBeginning) {
- Iterator iter(root());
- EXPECT_EQ(nullptr, iter.MoveToPrev());
- EXPECT_EQ(root(), iter.GetCurrent());
- EXPECT_EQ(child1(), iter.MoveToNext());
-}
-
-TEST_F(XFANodeIteratorTest, PrevFromAfterTheEnd) {
- Iterator iter(root());
- iter.SetCurrent(child9());
- EXPECT_EQ(nullptr, iter.MoveToNext());
- EXPECT_EQ(child9(), iter.MoveToPrev());
-}
-
-TEST_F(XFANodeIteratorTest, ChildAsRootPrev) {
- Iterator iter(child3());
- EXPECT_EQ(nullptr, iter.MoveToPrev());
-
- iter.SetCurrent(child4());
- EXPECT_EQ(child3(), iter.MoveToPrev());
- EXPECT_EQ(nullptr, iter.MoveToPrev());
-}
-
-TEST_F(XFANodeIteratorTest, ChildAsRootNext) {
- Iterator iter(child3());
- iter.SetCurrent(child4());
- EXPECT_EQ(child5(), iter.MoveToNext());
- EXPECT_EQ(child6(), iter.MoveToNext());
- EXPECT_EQ(nullptr, iter.MoveToNext());
-}
-
TEST(XFAUtilsTest, GetAttributeByName) {
EXPECT_EQ(nullptr, XFA_GetAttributeByName(L""));
EXPECT_EQ(nullptr, XFA_GetAttributeByName(L"nonesuch"));