diff options
-rw-r--r-- | BUILD.gn | 2 | ||||
-rw-r--r-- | fxjs/cfxjse_formcalc_context.cpp | 92 | ||||
-rw-r--r-- | fxjs/cjx_layoutpseudomodel.cpp | 2 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_ffdatetimeedit.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_ffnumericedit.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_ffpageview.h | 2 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_textprovider.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/parser/cxfa_layoutpagemgr.cpp | 2 | ||||
-rw-r--r-- | xfa/fxfa/parser/cxfa_node.cpp | 2 | ||||
-rw-r--r-- | xfa/fxfa/parser/cxfa_nodeiteratortemplate.h | 129 | ||||
-rw-r--r-- | xfa/fxfa/parser/cxfa_nodeiteratortemplate_unittest.cpp | 257 | ||||
-rw-r--r-- | xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h | 2 | ||||
-rw-r--r-- | xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h | 2 | ||||
-rw-r--r-- | xfa/fxfa/parser/xfa_document_datamerger_imp.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/parser/xfa_utils.cpp | 84 | ||||
-rw-r--r-- | xfa/fxfa/parser/xfa_utils.h | 120 | ||||
-rw-r--r-- | xfa/fxfa/parser/xfa_utils_unittest.cpp | 249 |
18 files changed, 489 insertions, 461 deletions
@@ -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")); |