diff options
Diffstat (limited to 'core/fxcrt')
21 files changed, 518 insertions, 471 deletions
diff --git a/core/fxcrt/xml/cfx_xmlchardata.cpp b/core/fxcrt/xml/cfx_xmlchardata.cpp index e62a43ac53..307d319537 100644 --- a/core/fxcrt/xml/cfx_xmlchardata.cpp +++ b/core/fxcrt/xml/cfx_xmlchardata.cpp @@ -6,6 +6,7 @@ #include "core/fxcrt/xml/cfx_xmlchardata.h" +#include "core/fxcrt/xml/cfx_xmldocument.h" #include "third_party/base/ptr_util.h" CFX_XMLCharData::CFX_XMLCharData(const WideString& wsCData) @@ -17,8 +18,8 @@ FX_XMLNODETYPE CFX_XMLCharData::GetType() const { return FX_XMLNODE_CharData; } -std::unique_ptr<CFX_XMLNode> CFX_XMLCharData::Clone() { - return pdfium::MakeUnique<CFX_XMLCharData>(GetText()); +CFX_XMLNode* CFX_XMLCharData::Clone(CFX_XMLDocument* doc) { + return doc->CreateNode<CFX_XMLCharData>(GetText()); } void CFX_XMLCharData::Save( diff --git a/core/fxcrt/xml/cfx_xmlchardata.h b/core/fxcrt/xml/cfx_xmlchardata.h index 0cdc348f26..013414bc82 100644 --- a/core/fxcrt/xml/cfx_xmlchardata.h +++ b/core/fxcrt/xml/cfx_xmlchardata.h @@ -12,6 +12,8 @@ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/xml/cfx_xmltext.h" +class CFX_XMLDocument; + class CFX_XMLCharData : public CFX_XMLText { public: explicit CFX_XMLCharData(const WideString& wsCData); @@ -19,7 +21,7 @@ class CFX_XMLCharData : public CFX_XMLText { // CFX_XMLNode FX_XMLNODETYPE GetType() const override; - std::unique_ptr<CFX_XMLNode> Clone() override; + CFX_XMLNode* Clone(CFX_XMLDocument* doc) override; void Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) override; }; diff --git a/core/fxcrt/xml/cfx_xmlchardata_unittest.cpp b/core/fxcrt/xml/cfx_xmlchardata_unittest.cpp index 0fa48e520f..4f0c49eaac 100644 --- a/core/fxcrt/xml/cfx_xmlchardata_unittest.cpp +++ b/core/fxcrt/xml/cfx_xmlchardata_unittest.cpp @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "core/fxcrt/xml/cfx_xmlchardata.h" +#include "core/fxcrt/xml/cfx_xmldocument.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/string_write_stream.h" #include "testing/test_support.h" @@ -18,12 +19,14 @@ TEST(CFX_XMLCharDataTest, GetText) { } TEST(CFX_XMLCharDataTest, Clone) { + CFX_XMLDocument doc; + CFX_XMLCharData data(L"My Data"); - auto clone = data.Clone(); + CFX_XMLNode* clone = data.Clone(&doc); EXPECT_TRUE(clone != nullptr); - EXPECT_NE(&data, clone.get()); + EXPECT_NE(&data, clone); ASSERT_EQ(FX_XMLNODE_CharData, clone->GetType()); - EXPECT_EQ(L"My Data", static_cast<CFX_XMLCharData*>(clone.get())->GetText()); + EXPECT_EQ(L"My Data", static_cast<CFX_XMLCharData*>(clone)->GetText()); } TEST(CFX_XMLCharDataTest, Save) { diff --git a/core/fxcrt/xml/cfx_xmldocument.cpp b/core/fxcrt/xml/cfx_xmldocument.cpp new file mode 100644 index 0000000000..f6e55551ed --- /dev/null +++ b/core/fxcrt/xml/cfx_xmldocument.cpp @@ -0,0 +1,14 @@ +// Copyright 2018 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 "core/fxcrt/xml/cfx_xmldocument.h" +#include "core/fxcrt/fx_system.h" +#include "core/fxcrt/xml/cfx_xmlinstruction.h" +#include "third_party/base/ptr_util.h" + +CFX_XMLDocument::CFX_XMLDocument() { + root_ = CreateNode<CFX_XMLElement>(L"root"); +} + +CFX_XMLDocument::~CFX_XMLDocument() = default; diff --git a/core/fxcrt/xml/cfx_xmldocument.h b/core/fxcrt/xml/cfx_xmldocument.h new file mode 100644 index 0000000000..a568f8390f --- /dev/null +++ b/core/fxcrt/xml/cfx_xmldocument.h @@ -0,0 +1,37 @@ +// Copyright 2018 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. + +#ifndef CORE_FXCRT_XML_CFX_XMLDOCUMENT_H_ +#define CORE_FXCRT_XML_CFX_XMLDOCUMENT_H_ + +#include <memory> +#include <utility> +#include <vector> + +#include "core/fxcrt/unowned_ptr.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "third_party/base/ptr_util.h" + +class CFX_XMLInstruction; +class CFX_XMLNode; + +class CFX_XMLDocument { + public: + CFX_XMLDocument(); + ~CFX_XMLDocument(); + + CFX_XMLElement* GetRoot() const { return root_.Get(); } + + template <typename T, typename... Args> + T* CreateNode(Args&&... args) { + nodes_.push_back(pdfium::MakeUnique<T>(std::forward<Args>(args)...)); + return static_cast<T*>(nodes_.back().get()); + } + + private: + std::vector<std::unique_ptr<CFX_XMLNode>> nodes_; + UnownedPtr<CFX_XMLElement> root_; +}; + +#endif // CORE_FXCRT_XML_CFX_XMLDOCUMENT_H_ diff --git a/core/fxcrt/xml/cfx_xmldocument_unittest.cpp b/core/fxcrt/xml/cfx_xmldocument_unittest.cpp new file mode 100644 index 0000000000..486b040db5 --- /dev/null +++ b/core/fxcrt/xml/cfx_xmldocument_unittest.cpp @@ -0,0 +1,22 @@ +// Copyright 2018 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 "core/fxcrt/xml/cfx_xmldocument.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlinstruction.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +TEST(CFX_XMLDocumentTest, Root) { + CFX_XMLDocument doc; + EXPECT_TRUE(doc.GetRoot() != nullptr); +} + +TEST(CFX_XMLDocumentTest, CreateNode) { + CFX_XMLDocument doc; + auto* node = doc.CreateNode<CFX_XMLElement>(L"elem"); + + ASSERT_EQ(FX_XMLNODE_Element, node->GetType()); + EXPECT_EQ(L"elem", node->GetName()); +} diff --git a/core/fxcrt/xml/cfx_xmlelement.cpp b/core/fxcrt/xml/cfx_xmlelement.cpp index 3befb242c9..74351b8c58 100644 --- a/core/fxcrt/xml/cfx_xmlelement.cpp +++ b/core/fxcrt/xml/cfx_xmlelement.cpp @@ -11,6 +11,7 @@ #include "core/fxcrt/cfx_widetextbuf.h" #include "core/fxcrt/fx_extension.h" #include "core/fxcrt/xml/cfx_xmlchardata.h" +#include "core/fxcrt/xml/cfx_xmldocument.h" #include "core/fxcrt/xml/cfx_xmltext.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" @@ -26,20 +27,18 @@ FX_XMLNODETYPE CFX_XMLElement::GetType() const { return FX_XMLNODE_Element; } -std::unique_ptr<CFX_XMLNode> CFX_XMLElement::Clone() { - auto pClone = pdfium::MakeUnique<CFX_XMLElement>(name_); - pClone->attrs_ = attrs_; +CFX_XMLNode* CFX_XMLElement::Clone(CFX_XMLDocument* doc) { + auto* node = doc->CreateNode<CFX_XMLElement>(name_); + node->attrs_ = attrs_; - // TODO(dsinclair): This clone is wrong. It doesn't clone child nodes just - // copies text nodes? - WideString wsText; + // TODO(dsinclair): This clone is wrong. It doesn't clone all child nodes just + // text nodes? for (CFX_XMLNode* pChild = GetFirstChild(); pChild; pChild = pChild->GetNextSibling()) { if (pChild->GetType() == FX_XMLNODE_Text) - wsText += static_cast<CFX_XMLText*>(pChild)->GetText(); + node->AppendChild(pChild->Clone(doc)); } - pClone->SetTextData(wsText); - return std::move(pClone); + return node; } WideString CFX_XMLElement::GetLocalTagName() const { @@ -60,7 +59,6 @@ WideString CFX_XMLElement::GetNamespaceURI() const { attr += L":"; attr += wsPrefix; } - const CFX_XMLNode* pNode = this; while (pNode) { if (pNode->GetType() != FX_XMLNODE_Element) @@ -89,13 +87,6 @@ WideString CFX_XMLElement::GetTextData() const { return buffer.MakeString(); } -void CFX_XMLElement::SetTextData(const WideString& wsText) { - // TODO(dsinclair): Shouldn't this remove the children if you set blank text? - if (wsText.IsEmpty()) - return; - AppendChild(pdfium::MakeUnique<CFX_XMLText>(wsText)); -} - void CFX_XMLElement::Save( const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) { ByteString bsNameEncoded = name_.UTF8Encode(); diff --git a/core/fxcrt/xml/cfx_xmlelement.h b/core/fxcrt/xml/cfx_xmlelement.h index 678ba6d996..ca5fd5e797 100644 --- a/core/fxcrt/xml/cfx_xmlelement.h +++ b/core/fxcrt/xml/cfx_xmlelement.h @@ -14,6 +14,8 @@ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/xml/cfx_xmlnode.h" +class CFX_XMLDocument; + class CFX_XMLElement : public CFX_XMLNode { public: explicit CFX_XMLElement(const WideString& wsTag); @@ -21,7 +23,7 @@ class CFX_XMLElement : public CFX_XMLNode { // CFX_XMLNode FX_XMLNODETYPE GetType() const override; - std::unique_ptr<CFX_XMLNode> Clone() override; + CFX_XMLNode* Clone(CFX_XMLDocument* doc) override; void Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) override; WideString GetName() const { return name_; } @@ -44,7 +46,6 @@ class CFX_XMLElement : public CFX_XMLNode { WideString GetNamespaceURI() const; WideString GetTextData() const; - void SetTextData(const WideString& wsText); private: WideString AttributeToString(const WideString& name, const WideString& value); diff --git a/core/fxcrt/xml/cfx_xmlelement_unittest.cpp b/core/fxcrt/xml/cfx_xmlelement_unittest.cpp index 79e067f511..1e53ef3dd7 100644 --- a/core/fxcrt/xml/cfx_xmlelement_unittest.cpp +++ b/core/fxcrt/xml/cfx_xmlelement_unittest.cpp @@ -2,15 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <utility> - -#include "core/fxcrt/xml/cfx_xmlchardata.h" #include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlchardata.h" +#include "core/fxcrt/xml/cfx_xmldocument.h" #include "core/fxcrt/xml/cfx_xmltext.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/string_write_stream.h" #include "testing/test_support.h" -#include "third_party/base/ptr_util.h" TEST(CFX_XMLElementTest, GetType) { CFX_XMLElement node(L"node"); @@ -74,19 +72,24 @@ TEST(CFX_XMLElementTest, Attributes) { } TEST(CFX_XMLElementTest, Clone) { + CFX_XMLDocument doc; + CFX_XMLElement node(L"test:node"); node.SetAttribute(L"first", L"one"); node.SetAttribute(L"second", L"two"); node.SetAttribute(L"xmlns:test", L"https://example.org/test"); - node.AppendChild(pdfium::MakeUnique<CFX_XMLText>(L"Text Child")); - node.AppendChild(pdfium::MakeUnique<CFX_XMLElement>(L"Node child")); + CFX_XMLText text_child1(L"Text Child"); + node.AppendChild(&text_child1); - auto clone = node.Clone(); + CFX_XMLElement node_child1(L"Node child"); + node.AppendChild(&node_child1); + + CFX_XMLNode* clone = node.Clone(&doc); EXPECT_TRUE(clone != nullptr); ASSERT_EQ(FX_XMLNODE_Element, clone->GetType()); - CFX_XMLElement* inst = static_cast<CFX_XMLElement*>(clone.get()); + CFX_XMLElement* inst = static_cast<CFX_XMLElement*>(clone); EXPECT_EQ(L"test:node", inst->GetName()); EXPECT_EQ(L"node", inst->GetLocalTagName()); @@ -129,14 +132,17 @@ TEST(CFX_XMLElementTest, SaveWithChildren) { auto stream = pdfium::MakeRetain<StringWriteStream>(); CFX_XMLElement node(L"node"); - node.AppendChild(pdfium::MakeUnique<CFX_XMLText>(L"Text Child 1")); + CFX_XMLText text_child1(L"Text Child 1"); + node.AppendChild(&text_child1); + + CFX_XMLElement node_child1(L"node-child"); + node.AppendChild(&node_child1); - auto child = pdfium::MakeUnique<CFX_XMLElement>(L"node-child"); - CFX_XMLElement* node_child1 = child.get(); - node.AppendChild(std::move(child)); + CFX_XMLText text_child2(L"Text Child 2"); + node_child1.AppendChild(&text_child2); - node_child1->AppendChild(pdfium::MakeUnique<CFX_XMLText>(L"Text Child 2")); - node.AppendChild(pdfium::MakeUnique<CFX_XMLCharData>(L"Char Data")); + CFX_XMLCharData char_data1(L"Char Data"); + node.AppendChild(&char_data1); node.Save(stream); EXPECT_EQ( @@ -160,18 +166,18 @@ TEST(CFX_XMLElementTest, SaveWithNamespace) { TEST(CFX_XMLElementTest, GetFirstChildNamed) { CFX_XMLElement node(L"node"); - auto child = pdfium::MakeUnique<CFX_XMLElement>(L"node-child"); - CFX_XMLElement* node_child1 = child.get(); - node.AppendChild(std::move(child)); + CFX_XMLElement node_child1(L"node-child"); + node.AppendChild(&node_child1); auto* found = node.GetFirstChildNamed(L"node-child"); EXPECT_TRUE(found != nullptr); - EXPECT_EQ(node_child1, found); + EXPECT_EQ(&node_child1, found); } TEST(CFX_XMLElementTest, GetFirstChildNamedMissing) { CFX_XMLElement node(L"node"); - node.AppendChild(pdfium::MakeUnique<CFX_XMLElement>(L"node-child")); + CFX_XMLElement node_child1(L"node-child"); + node.AppendChild(&node_child1); auto* found = node.GetFirstChildNamed(L"node-sibling"); EXPECT_TRUE(found == nullptr); @@ -179,23 +185,26 @@ TEST(CFX_XMLElementTest, GetFirstChildNamedMissing) { TEST(CFX_XMLElementTest, GetNthChildNamed) { CFX_XMLElement node(L"node"); - node.AppendChild(pdfium::MakeUnique<CFX_XMLElement>(L"node-child")); - node.AppendChild(pdfium::MakeUnique<CFX_XMLElement>(L"node-child")); - - auto child = pdfium::MakeUnique<CFX_XMLElement>(L"node-child"); - CFX_XMLElement* node_child3 = child.get(); - node.AppendChild(std::move(child)); + CFX_XMLElement node_child1(L"node-child"); + CFX_XMLElement node_child2(L"node-child"); + CFX_XMLElement node_child3(L"node-child"); + node.AppendChild(&node_child1); + node.AppendChild(&node_child2); + node.AppendChild(&node_child3); auto* found = node.GetNthChildNamed(L"node-child", 2); EXPECT_TRUE(found != nullptr); - EXPECT_EQ(node_child3, found); + EXPECT_EQ(&node_child3, found); } TEST(CFX_XMLElementTest, GetNthChildNamedMissingChild) { CFX_XMLElement node(L"node"); - node.AppendChild(pdfium::MakeUnique<CFX_XMLElement>(L"node-child")); - node.AppendChild(pdfium::MakeUnique<CFX_XMLElement>(L"node-child")); - node.AppendChild(pdfium::MakeUnique<CFX_XMLElement>(L"node-child")); + CFX_XMLElement node_child1(L"node-child"); + CFX_XMLElement node_child2(L"node-child"); + CFX_XMLElement node_child3(L"node-child"); + node.AppendChild(&node_child1); + node.AppendChild(&node_child2); + node.AppendChild(&node_child3); auto* found = node.GetNthChildNamed(L"node-child", 5); EXPECT_TRUE(found == nullptr); @@ -203,15 +212,18 @@ TEST(CFX_XMLElementTest, GetNthChildNamedMissingChild) { TEST(CFX_XMLElementTest, GetTextData) { CFX_XMLElement node(L"node"); - node.AppendChild(pdfium::MakeUnique<CFX_XMLText>(L"Text Child 1")); - auto child = pdfium::MakeUnique<CFX_XMLElement>(L"Node child"); - CFX_XMLElement* node_child1 = child.get(); - node.AppendChild(std::move(child)); + CFX_XMLText text_child1(L"Text Child 1"); + node.AppendChild(&text_child1); + + CFX_XMLElement node_child1(L"Node child"); + node.AppendChild(&node_child1); - node_child1->AppendChild(pdfium::MakeUnique<CFX_XMLText>(L"Text Child 2")); + CFX_XMLText text_child2(L"Text Child 2"); + node_child1.AppendChild(&text_child2); - node.AppendChild(pdfium::MakeUnique<CFX_XMLCharData>(L"Char Data")); + CFX_XMLCharData char_data1(L"Char Data"); + node.AppendChild(&char_data1); EXPECT_EQ(L"Text Child 1Char Data", node.GetTextData()); } diff --git a/core/fxcrt/xml/cfx_xmlinstruction.cpp b/core/fxcrt/xml/cfx_xmlinstruction.cpp index b7a87b588a..32841fb68e 100644 --- a/core/fxcrt/xml/cfx_xmlinstruction.cpp +++ b/core/fxcrt/xml/cfx_xmlinstruction.cpp @@ -10,6 +10,7 @@ #include "core/fxcrt/fx_codepage.h" #include "core/fxcrt/fx_extension.h" +#include "core/fxcrt/xml/cfx_xmldocument.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" @@ -22,10 +23,10 @@ FX_XMLNODETYPE CFX_XMLInstruction::GetType() const { return FX_XMLNODE_Instruction; } -std::unique_ptr<CFX_XMLNode> CFX_XMLInstruction::Clone() { - auto pClone = pdfium::MakeUnique<CFX_XMLInstruction>(name_); - pClone->m_TargetData = m_TargetData; - return std::move(pClone); +CFX_XMLNode* CFX_XMLInstruction::Clone(CFX_XMLDocument* doc) { + auto* node = doc->CreateNode<CFX_XMLInstruction>(name_); + node->m_TargetData = m_TargetData; + return node; } void CFX_XMLInstruction::AppendData(const WideString& wsData) { diff --git a/core/fxcrt/xml/cfx_xmlinstruction.h b/core/fxcrt/xml/cfx_xmlinstruction.h index 3be9d48573..153ef2b625 100644 --- a/core/fxcrt/xml/cfx_xmlinstruction.h +++ b/core/fxcrt/xml/cfx_xmlinstruction.h @@ -13,6 +13,8 @@ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/xml/cfx_xmlnode.h" +class CFX_XMLDocument; + class CFX_XMLInstruction : public CFX_XMLNode { public: explicit CFX_XMLInstruction(const WideString& wsTarget); @@ -20,7 +22,7 @@ class CFX_XMLInstruction : public CFX_XMLNode { // CFX_XMLNode FX_XMLNODETYPE GetType() const override; - std::unique_ptr<CFX_XMLNode> Clone() override; + CFX_XMLNode* Clone(CFX_XMLDocument* doc) override; void Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) override; bool IsOriginalXFAVersion() const; diff --git a/core/fxcrt/xml/cfx_xmlinstruction_unittest.cpp b/core/fxcrt/xml/cfx_xmlinstruction_unittest.cpp index c60d401303..0c43c59ccd 100644 --- a/core/fxcrt/xml/cfx_xmlinstruction_unittest.cpp +++ b/core/fxcrt/xml/cfx_xmlinstruction_unittest.cpp @@ -4,6 +4,7 @@ #include "core/fxcrt/xml/cfx_xmlinstruction.h" #include "core/fxcrt/cfx_memorystream.h" +#include "core/fxcrt/xml/cfx_xmldocument.h" #include "core/fxcrt/xml/cfx_xmlelement.h" #include "core/fxcrt/xml/cfx_xmlparser.h" #include "testing/gtest/include/gtest/gtest.h" @@ -41,15 +42,17 @@ TEST(CFX_XMLInstructionTest, TargetData) { } TEST(CFX_XMLInstructionTest, Clone) { + CFX_XMLDocument doc; + CFX_XMLInstruction node(L"acrobat"); node.AppendData(L"firstString"); node.AppendData(L"secondString"); - auto clone = node.Clone(); + CFX_XMLNode* clone = node.Clone(&doc); EXPECT_TRUE(clone != nullptr); ASSERT_EQ(FX_XMLNODE_Instruction, clone->GetType()); - CFX_XMLInstruction* inst = static_cast<CFX_XMLInstruction*>(clone.get()); + CFX_XMLInstruction* inst = static_cast<CFX_XMLInstruction*>(clone); EXPECT_TRUE(inst->IsAcrobat()); @@ -87,14 +90,16 @@ TEST(CFX_XMLInstructionTest, ParseAndReSave) { reinterpret_cast<uint8_t*>(const_cast<char*>(input)), strlen(input), false); - CFX_XMLElement root(L"root"); - CFX_XMLParser parser(&root, in_stream); - ASSERT_TRUE(parser.Parse()); - ASSERT_TRUE(root.GetFirstChild() != nullptr); - ASSERT_EQ(FX_XMLNODE_Instruction, root.GetFirstChild()->GetType()); + CFX_XMLParser parser(in_stream); + std::unique_ptr<CFX_XMLDocument> doc = parser.Parse(); + ASSERT_TRUE(doc != nullptr); + + CFX_XMLElement* root = doc->GetRoot(); + ASSERT_TRUE(root->GetFirstChild() != nullptr); + ASSERT_EQ(FX_XMLNODE_Instruction, root->GetFirstChild()->GetType()); CFX_XMLInstruction* node = - static_cast<CFX_XMLInstruction*>(root.GetFirstChild()); + static_cast<CFX_XMLInstruction*>(root->GetFirstChild()); ASSERT_TRUE(node != nullptr); EXPECT_TRUE(node->IsAcrobat()); @@ -109,3 +114,49 @@ TEST(CFX_XMLInstructionTest, ParseAndReSave) { "<?acrobat http://www.xfa.org/schema/xfa-template/3.3/ Display:1 ?>\n", out_stream->ToString()); } + +TEST(CFX_XMLInstructionTest, ParseAndReSaveInnerInstruction) { + const char* input = + "<node>\n" + "<?acrobat http://www.xfa.org/schema/xfa-template/3.3/ Display:1 ?>\n" + "</node>"; + + auto in_stream = pdfium::MakeRetain<CFX_MemoryStream>( + reinterpret_cast<uint8_t*>(const_cast<char*>(input)), strlen(input), + false); + + CFX_XMLParser parser(in_stream); + std::unique_ptr<CFX_XMLDocument> doc = parser.Parse(); + ASSERT_TRUE(doc != nullptr); + + CFX_XMLElement* root = doc->GetRoot(); + ASSERT_TRUE(root->GetFirstChild() != nullptr); + ASSERT_TRUE(root->GetFirstChild()->GetType() == FX_XMLNODE_Element); + + CFX_XMLElement* node = static_cast<CFX_XMLElement*>(root->GetFirstChild()); + EXPECT_EQ(L"node", node->GetName()); + + CFX_XMLInstruction* instruction = nullptr; + for (auto* elem = node->GetFirstChild(); elem; + elem = elem->GetNextSibling()) { + if (elem->GetType() == FX_XMLNODE_Instruction) { + instruction = static_cast<CFX_XMLInstruction*>(elem); + break; + } + } + ASSERT_TRUE(instruction != nullptr); + EXPECT_TRUE(instruction->IsAcrobat()); + + auto& data = instruction->GetTargetData(); + ASSERT_EQ(2U, data.size()); + EXPECT_EQ(L"http://www.xfa.org/schema/xfa-template/3.3/", data[0]); + EXPECT_EQ(L"Display:1", data[1]); + + auto out_stream = pdfium::MakeRetain<StringWriteStream>(); + node->Save(out_stream); + EXPECT_EQ( + "<node>\n\n" + "<?acrobat http://www.xfa.org/schema/xfa-template/3.3/ Display:1 ?>\n\n" + "</node>\n", + out_stream->ToString()); +} diff --git a/core/fxcrt/xml/cfx_xmlnode.cpp b/core/fxcrt/xml/cfx_xmlnode.cpp index 088cbf367c..c8fea23bda 100644 --- a/core/fxcrt/xml/cfx_xmlnode.cpp +++ b/core/fxcrt/xml/cfx_xmlnode.cpp @@ -17,38 +17,26 @@ CFX_XMLNode::CFX_XMLNode() = default; -CFX_XMLNode::~CFX_XMLNode() { - DeleteChildren(); -} +CFX_XMLNode::~CFX_XMLNode() = default; void CFX_XMLNode::DeleteChildren() { - CFX_XMLNode* child = last_child_.Get(); - // Clear last child early as it will have been deleted already. - last_child_ = nullptr; - while (child) { - child = child->prev_sibling_.Get(); - if (child) { - if (child->next_sibling_) { - child->next_sibling_->prev_sibling_ = nullptr; - child->next_sibling_->parent_ = nullptr; - } - - child->next_sibling_ = nullptr; - } - } - if (first_child_) { - first_child_->next_sibling_ = nullptr; + while (first_child_) { first_child_->parent_ = nullptr; + first_child_->prev_sibling_ = nullptr; + + CFX_XMLNode* child = first_child_; + first_child_ = child->next_sibling_; + + child->next_sibling_ = nullptr; } - first_child_ = nullptr; + last_child_ = nullptr; } -void CFX_XMLNode::AppendChild(std::unique_ptr<CFX_XMLNode> pNode) { - InsertChildNode(std::move(pNode), -1); +void CFX_XMLNode::AppendChild(CFX_XMLNode* pNode) { + InsertChildNode(pNode, -1); } -void CFX_XMLNode::InsertChildNode(std::unique_ptr<CFX_XMLNode> pNode, - int32_t index) { +void CFX_XMLNode::InsertChildNode(CFX_XMLNode* pNode, int32_t index) { ASSERT(!pNode->parent_); pNode->parent_ = this; @@ -56,36 +44,36 @@ void CFX_XMLNode::InsertChildNode(std::unique_ptr<CFX_XMLNode> pNode, if (!first_child_) { ASSERT(!last_child_); - first_child_ = std::move(pNode); - last_child_ = first_child_.get(); + first_child_ = pNode; + last_child_ = first_child_; first_child_->prev_sibling_ = nullptr; first_child_->next_sibling_ = nullptr; return; } if (index == 0) { - first_child_->prev_sibling_ = pNode.get(); - pNode->next_sibling_ = std::move(first_child_); + first_child_->prev_sibling_ = pNode; + pNode->next_sibling_ = first_child_; pNode->prev_sibling_ = nullptr; - first_child_ = std::move(pNode); + first_child_ = pNode; return; } int32_t iCount = 0; - CFX_XMLNode* pFind = first_child_.get(); + CFX_XMLNode* pFind = first_child_; // Note, negative indexes, and indexes after the end of the list will result // in appending to the list. while (++iCount != index && pFind->next_sibling_) - pFind = pFind->next_sibling_.get(); + pFind = pFind->next_sibling_; pNode->prev_sibling_ = pFind; if (pFind->next_sibling_) - pFind->next_sibling_->prev_sibling_ = pNode.get(); - pNode->next_sibling_ = std::move(pFind->next_sibling_); + pFind->next_sibling_->prev_sibling_ = pNode; + pNode->next_sibling_ = pFind->next_sibling_; - pFind->next_sibling_ = std::move(pNode); - if (pFind == last_child_.Get()) - last_child_ = pFind->next_sibling_.get(); + pFind->next_sibling_ = pNode; + if (pFind == last_child_) + last_child_ = pFind->next_sibling_; } void CFX_XMLNode::RemoveChildNode(CFX_XMLNode* pNode) { @@ -95,35 +83,25 @@ void CFX_XMLNode::RemoveChildNode(CFX_XMLNode* pNode) { if (pNode->GetParent() != this) return; - if (first_child_.get() == pNode) { - first_child_.release(); - first_child_ = std::move(pNode->next_sibling_); - if (first_child_) { - first_child_->prev_sibling_ = nullptr; - - if (first_child_->next_sibling_) - first_child_->next_sibling_->prev_sibling_ = first_child_.get(); - } - } else { - CFX_XMLNode* prev = pNode->prev_sibling_.Get(); - prev->next_sibling_.release(); // Release pNode - prev->next_sibling_ = std::move(pNode->next_sibling_); - - if (prev->next_sibling_) - prev->next_sibling_->prev_sibling_ = prev; - } + if (first_child_ == pNode) + first_child_ = pNode->next_sibling_; + if (last_child_ == pNode) + last_child_ = pNode->prev_sibling_; - if (last_child_.Get() == pNode) - last_child_ = pNode->prev_sibling_.Get(); + if (pNode->prev_sibling_) + pNode->prev_sibling_->next_sibling_ = pNode->next_sibling_; + if (pNode->next_sibling_) + pNode->next_sibling_->prev_sibling_ = pNode->prev_sibling_; pNode->parent_ = nullptr; pNode->prev_sibling_ = nullptr; + pNode->next_sibling_ = nullptr; } CFX_XMLNode* CFX_XMLNode::GetRoot() { CFX_XMLNode* pParent = this; while (pParent->parent_) - pParent = pParent->parent_.Get(); + pParent = pParent->parent_; return pParent; } diff --git a/core/fxcrt/xml/cfx_xmlnode.h b/core/fxcrt/xml/cfx_xmlnode.h index 4c98a3b51a..95dc0acce9 100644 --- a/core/fxcrt/xml/cfx_xmlnode.h +++ b/core/fxcrt/xml/cfx_xmlnode.h @@ -19,39 +19,41 @@ enum FX_XMLNODETYPE { FX_XMLNODE_CharData, }; +class CFX_XMLDocument; + class CFX_XMLNode { public: CFX_XMLNode(); virtual ~CFX_XMLNode(); virtual FX_XMLNODETYPE GetType() const = 0; - virtual std::unique_ptr<CFX_XMLNode> Clone() = 0; + virtual CFX_XMLNode* Clone(CFX_XMLDocument* doc) = 0; virtual void Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) = 0; CFX_XMLNode* GetRoot(); - CFX_XMLNode* GetParent() const { return parent_.Get(); } - CFX_XMLNode* GetFirstChild() const { return first_child_.get(); } - CFX_XMLNode* GetNextSibling() const { return next_sibling_.get(); } + CFX_XMLNode* GetParent() const { return parent_; } + CFX_XMLNode* GetFirstChild() const { return first_child_; } + CFX_XMLNode* GetNextSibling() const { return next_sibling_; } - void AppendChild(std::unique_ptr<CFX_XMLNode> pNode); - void InsertChildNode(std::unique_ptr<CFX_XMLNode> pNode, int32_t index); + void AppendChild(CFX_XMLNode* pNode); + void InsertChildNode(CFX_XMLNode* pNode, int32_t index); void RemoveChildNode(CFX_XMLNode* pNode); void DeleteChildren(); - CFX_XMLNode* GetLastChildForTesting() const { return last_child_.Get(); } - CFX_XMLNode* GetPrevSiblingForTesting() const { return prev_sibling_.Get(); } + CFX_XMLNode* GetLastChildForTesting() const { return last_child_; } + CFX_XMLNode* GetPrevSiblingForTesting() const { return prev_sibling_; } protected: WideString EncodeEntities(const WideString& value); private: - // A node owns its first child and it owns its next sibling. The rest - // are unowned pointers. - UnownedPtr<CFX_XMLNode> parent_; - UnownedPtr<CFX_XMLNode> last_child_; - UnownedPtr<CFX_XMLNode> prev_sibling_; - std::unique_ptr<CFX_XMLNode> first_child_; - std::unique_ptr<CFX_XMLNode> next_sibling_; + // The nodes are owned by the XML document. We do not know what order the + // nodes will be destroyed in so they can not be UnownedPtrs. + CFX_XMLNode* parent_ = nullptr; + CFX_XMLNode* first_child_ = nullptr; + CFX_XMLNode* last_child_ = nullptr; + CFX_XMLNode* next_sibling_ = nullptr; + CFX_XMLNode* prev_sibling_ = nullptr; }; #endif // CORE_FXCRT_XML_CFX_XMLNODE_H_ diff --git a/core/fxcrt/xml/cfx_xmlnode_unittest.cpp b/core/fxcrt/xml/cfx_xmlnode_unittest.cpp index 1c69069942..ec56603a58 100644 --- a/core/fxcrt/xml/cfx_xmlnode_unittest.cpp +++ b/core/fxcrt/xml/cfx_xmlnode_unittest.cpp @@ -2,274 +2,227 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <utility> - #include "core/fxcrt/xml/cfx_xmlelement.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/test_support.h" -#include "third_party/base/ptr_util.h" TEST(CFX_XMLNodeTest, GetParent) { - auto node1 = pdfium::MakeUnique<CFX_XMLElement>(L"node"); - auto child2 = pdfium::MakeUnique<CFX_XMLElement>(L"node2"); - auto child3 = pdfium::MakeUnique<CFX_XMLElement>(L"node3"); - - CFX_XMLElement* node2 = child2.get(); - CFX_XMLElement* node3 = child3.get(); + CFX_XMLElement node1(L"node"); + CFX_XMLElement node2(L"node2"); + CFX_XMLElement node3(L"node3"); - node1->AppendChild(std::move(child2)); - node2->AppendChild(std::move(child3)); + node1.AppendChild(&node2); + node2.AppendChild(&node3); - EXPECT_EQ(nullptr, node1->GetParent()); - EXPECT_EQ(node1.get(), node2->GetParent()); - EXPECT_EQ(node2, node3->GetParent()); + EXPECT_EQ(nullptr, node1.GetParent()); + EXPECT_EQ(&node1, node2.GetParent()); + EXPECT_EQ(&node2, node3.GetParent()); } TEST(CFX_XMLNodeTest, GetRoot) { - auto node1 = pdfium::MakeUnique<CFX_XMLElement>(L"node"); - auto child2 = pdfium::MakeUnique<CFX_XMLElement>(L"node2"); - auto child3 = pdfium::MakeUnique<CFX_XMLElement>(L"node3"); + CFX_XMLElement node1(L"node"); + CFX_XMLElement node2(L"node2"); + CFX_XMLElement node3(L"node3"); - CFX_XMLElement* node2 = child2.get(); - CFX_XMLElement* node3 = child3.get(); + node1.AppendChild(&node2); + node2.AppendChild(&node3); - node1->AppendChild(std::move(child2)); - node2->AppendChild(std::move(child3)); - - EXPECT_EQ(node1.get(), node1->GetRoot()); - EXPECT_EQ(node1.get(), node2->GetRoot()); - EXPECT_EQ(node1.get(), node3->GetRoot()); + EXPECT_EQ(&node1, node1.GetRoot()); + EXPECT_EQ(&node1, node2.GetRoot()); + EXPECT_EQ(&node1, node3.GetRoot()); } TEST(CFX_XMLNodeTest, GetChildren) { - auto node1 = pdfium::MakeUnique<CFX_XMLElement>(L"node"); - auto child2 = pdfium::MakeUnique<CFX_XMLElement>(L"node2"); - auto child3 = pdfium::MakeUnique<CFX_XMLElement>(L"node3"); - auto child4 = pdfium::MakeUnique<CFX_XMLElement>(L"node4"); - - CFX_XMLElement* node2 = child2.get(); - CFX_XMLElement* node3 = child3.get(); - CFX_XMLElement* node4 = child4.get(); + CFX_XMLElement node1(L"node"); + CFX_XMLElement node2(L"node2"); + CFX_XMLElement node3(L"node3"); + CFX_XMLElement node4(L"node4"); - node1->AppendChild(std::move(child2)); - node1->AppendChild(std::move(child4)); - node2->AppendChild(std::move(child3)); + node1.AppendChild(&node2); + node1.AppendChild(&node4); + node2.AppendChild(&node3); - EXPECT_EQ(node2, node1->GetFirstChild()); + EXPECT_EQ(&node2, node1.GetFirstChild()); - EXPECT_EQ(node4, node2->GetNextSibling()); - EXPECT_EQ(node3, node2->GetFirstChild()); + EXPECT_EQ(&node4, node2.GetNextSibling()); + EXPECT_EQ(&node3, node2.GetFirstChild()); - EXPECT_TRUE(node3->GetNextSibling() == nullptr); - EXPECT_TRUE(node3->GetFirstChild() == nullptr); + EXPECT_TRUE(node3.GetNextSibling() == nullptr); + EXPECT_TRUE(node3.GetFirstChild() == nullptr); - EXPECT_TRUE(node4->GetNextSibling() == nullptr); - EXPECT_TRUE(node4->GetFirstChild() == nullptr); + EXPECT_TRUE(node4.GetNextSibling() == nullptr); + EXPECT_TRUE(node4.GetFirstChild() == nullptr); } TEST(CFX_XMLNodeTest, DeleteChildren) { - auto node1 = pdfium::MakeUnique<CFX_XMLElement>(L"node"); - auto child2 = pdfium::MakeUnique<CFX_XMLElement>(L"node2"); - auto child3 = pdfium::MakeUnique<CFX_XMLElement>(L"node3"); - auto child4 = pdfium::MakeUnique<CFX_XMLElement>(L"node4"); - - CFX_XMLElement* node2 = child2.get(); - // CFX_XMLElement* node3 = child3.get(); - // CFX_XMLElement* node4 = child4.get(); - - node1->AppendChild(std::move(child2)); - node1->AppendChild(std::move(child4)); - node2->AppendChild(std::move(child3)); - - node1->DeleteChildren(); - EXPECT_TRUE(node1->GetFirstChild() == nullptr); - EXPECT_TRUE(node1->GetLastChildForTesting() == nullptr); + CFX_XMLElement node1(L"node"); + CFX_XMLElement node2(L"node2"); + CFX_XMLElement node3(L"node3"); + CFX_XMLElement node4(L"node4"); - // TODO(dsinclair): This isn't true currently but will be true when - // we own the nodes in an XML document. (Currently nodes are unique_ptrs - // so the objects have been deleted by this point.) + node1.AppendChild(&node2); + node1.AppendChild(&node4); + node2.AppendChild(&node3); - // EXPECT_TRUE(node2->GetParent() == nullptr); - // EXPECT_TRUE(node4->GetParent() == nullptr); + node1.DeleteChildren(); + EXPECT_TRUE(node1.GetFirstChild() == nullptr); + EXPECT_TRUE(node2.GetParent() == nullptr); + EXPECT_TRUE(node4.GetParent() == nullptr); - // // node2 and node4 should no longer be siblings. - // EXPECT_TRUE(node2->GetNextSibling() == nullptr); - // EXPECT_TRUE(node4->GetPrevSiblingForTesting() == nullptr); + // node2 and node4 should no longer be siblings. + EXPECT_TRUE(node2.GetNextSibling() == nullptr); + EXPECT_TRUE(node4.GetPrevSiblingForTesting() == nullptr); // Deleting children doesn't change deleted substructure - // EXPECT_EQ(node3, node2->GetFirstChild()); - // EXPECT_TRUE(node3->GetParent() == node2); + EXPECT_EQ(&node3, node2.GetFirstChild()); + EXPECT_TRUE(node3.GetParent() == &node2); } TEST(CFX_XMLNodeTest, AddingChildren) { - auto node1 = pdfium::MakeUnique<CFX_XMLElement>(L"node"); - auto child2 = pdfium::MakeUnique<CFX_XMLElement>(L"node2"); - auto child3 = pdfium::MakeUnique<CFX_XMLElement>(L"node3"); - auto child4 = pdfium::MakeUnique<CFX_XMLElement>(L"node4"); - auto child5 = pdfium::MakeUnique<CFX_XMLElement>(L"node5"); + CFX_XMLElement node1(L"node"); + CFX_XMLElement node2(L"node2"); + CFX_XMLElement node3(L"node3"); - CFX_XMLElement* node2 = child2.get(); - CFX_XMLElement* node3 = child3.get(); - CFX_XMLElement* node4 = child4.get(); - CFX_XMLElement* node5 = child5.get(); + node1.AppendChild(&node2); + node1.AppendChild(&node3); - node1->AppendChild(std::move(child2)); - node1->AppendChild(std::move(child3)); + EXPECT_EQ(&node1, node2.GetParent()); + EXPECT_EQ(&node1, node3.GetParent()); - EXPECT_EQ(node1.get(), node2->GetParent()); - EXPECT_EQ(node1.get(), node3->GetParent()); - - EXPECT_EQ(node2, node1->GetFirstChild()); - EXPECT_EQ(node3, node2->GetNextSibling()); - EXPECT_TRUE(node3->GetNextSibling() == nullptr); + EXPECT_EQ(&node2, node1.GetFirstChild()); + EXPECT_EQ(&node3, node2.GetNextSibling()); + EXPECT_TRUE(node3.GetNextSibling() == nullptr); // Insert to negative appends. - node1->InsertChildNode(std::move(child4), -1); - EXPECT_EQ(node1.get(), node4->GetParent()); - EXPECT_EQ(node4, node3->GetNextSibling()); - EXPECT_TRUE(node4->GetNextSibling() == nullptr); - - node1->InsertChildNode(std::move(child5), 1); - EXPECT_EQ(node1.get(), node5->GetParent()); - EXPECT_EQ(node2, node1->GetFirstChild()); - EXPECT_EQ(node5, node2->GetNextSibling()); - EXPECT_EQ(node3, node5->GetNextSibling()); - EXPECT_EQ(node4, node3->GetNextSibling()); - EXPECT_TRUE(node4->GetNextSibling() == nullptr); + CFX_XMLElement node4(L"node4"); + node1.InsertChildNode(&node4, -1); + EXPECT_EQ(&node1, node4.GetParent()); + EXPECT_EQ(&node4, node3.GetNextSibling()); + EXPECT_TRUE(node4.GetNextSibling() == nullptr); + + CFX_XMLElement node5(L"node5"); + node1.InsertChildNode(&node5, 1); + EXPECT_EQ(&node1, node5.GetParent()); + EXPECT_EQ(&node2, node1.GetFirstChild()); + EXPECT_EQ(&node5, node2.GetNextSibling()); + EXPECT_EQ(&node3, node5.GetNextSibling()); + EXPECT_EQ(&node4, node3.GetNextSibling()); + EXPECT_TRUE(node4.GetNextSibling() == nullptr); +} + +#ifndef NDEBUG +TEST(CFX_XMLNodeTest, DuplicateInsertOfNode) { + CFX_XMLElement node1(L"node"); + CFX_XMLElement node2(L"node2"); + + node1.AppendChild(&node2); + EXPECT_DEATH(node1.AppendChild(&node2), ""); } +#endif // NDEBUG TEST(CFX_XMLNodeTest, RemovingMiddleChild) { - auto node1 = pdfium::MakeUnique<CFX_XMLElement>(L"node"); - auto child2 = pdfium::MakeUnique<CFX_XMLElement>(L"node2"); - auto child3 = pdfium::MakeUnique<CFX_XMLElement>(L"node3"); - auto child4 = pdfium::MakeUnique<CFX_XMLElement>(L"node4"); - - CFX_XMLElement* node2 = child2.get(); - CFX_XMLElement* node3 = child3.get(); - CFX_XMLElement* node4 = child4.get(); - - node1->AppendChild(std::move(child2)); - node1->AppendChild(std::move(child3)); - node1->AppendChild(std::move(child4)); - - EXPECT_EQ(node2, node1->GetFirstChild()); - EXPECT_EQ(node3, node2->GetNextSibling()); - EXPECT_EQ(node4, node3->GetNextSibling()); - EXPECT_TRUE(node4->GetNextSibling() == nullptr); - - node1->RemoveChildNode(node3); - // Node is released by parent, so need to take ownership - child3 = pdfium::WrapUnique(node3); - - EXPECT_TRUE(node3->GetParent() == nullptr); - EXPECT_TRUE(node3->GetNextSibling() == nullptr); - EXPECT_TRUE(node3->GetPrevSiblingForTesting() == nullptr); - - EXPECT_EQ(node2, node1->GetFirstChild()); - EXPECT_EQ(node4, node2->GetNextSibling()); - EXPECT_EQ(node2, node4->GetPrevSiblingForTesting()); - EXPECT_TRUE(node4->GetNextSibling() == nullptr); + CFX_XMLElement node1(L"node1"); + CFX_XMLElement node2(L"node2"); + CFX_XMLElement node3(L"node3"); + CFX_XMLElement node4(L"node4"); + + node1.AppendChild(&node2); + node1.AppendChild(&node3); + node1.AppendChild(&node4); + + EXPECT_EQ(&node2, node1.GetFirstChild()); + EXPECT_EQ(&node3, node2.GetNextSibling()); + EXPECT_EQ(&node4, node3.GetNextSibling()); + EXPECT_TRUE(node4.GetNextSibling() == nullptr); + + node1.RemoveChildNode(&node3); + EXPECT_TRUE(node3.GetParent() == nullptr); + EXPECT_TRUE(node3.GetNextSibling() == nullptr); + EXPECT_TRUE(node3.GetPrevSiblingForTesting() == nullptr); + + EXPECT_EQ(&node2, node1.GetFirstChild()); + EXPECT_EQ(&node4, node2.GetNextSibling()); + EXPECT_EQ(&node2, node4.GetPrevSiblingForTesting()); + EXPECT_TRUE(node4.GetNextSibling() == nullptr); } TEST(CFX_XMLNodeTest, RemovingFirstChild) { - auto node1 = pdfium::MakeUnique<CFX_XMLElement>(L"node"); - auto child2 = pdfium::MakeUnique<CFX_XMLElement>(L"node2"); - auto child3 = pdfium::MakeUnique<CFX_XMLElement>(L"node3"); - auto child4 = pdfium::MakeUnique<CFX_XMLElement>(L"node4"); - - CFX_XMLElement* node2 = child2.get(); - CFX_XMLElement* node3 = child3.get(); - CFX_XMLElement* node4 = child4.get(); - - node1->AppendChild(std::move(child2)); - node1->AppendChild(std::move(child3)); - node1->AppendChild(std::move(child4)); - - EXPECT_EQ(node2, node1->GetFirstChild()); - EXPECT_EQ(node3, node2->GetNextSibling()); - EXPECT_EQ(node4, node3->GetNextSibling()); - EXPECT_TRUE(node4->GetNextSibling() == nullptr); - - node1->RemoveChildNode(node2); - // Node is released by parent, so need to take ownership - child2 = pdfium::WrapUnique(node2); - - EXPECT_TRUE(node2->GetParent() == nullptr); - EXPECT_TRUE(node2->GetNextSibling() == nullptr); - EXPECT_TRUE(node2->GetPrevSiblingForTesting() == nullptr); - - EXPECT_EQ(node3, node1->GetFirstChild()); - EXPECT_TRUE(node3->GetPrevSiblingForTesting() == nullptr); - EXPECT_EQ(node4, node3->GetNextSibling()); - EXPECT_TRUE(node4->GetNextSibling() == nullptr); + CFX_XMLElement node1(L"node1"); + CFX_XMLElement node2(L"node2"); + CFX_XMLElement node3(L"node3"); + CFX_XMLElement node4(L"node4"); + + node1.AppendChild(&node2); + node1.AppendChild(&node3); + node1.AppendChild(&node4); + + EXPECT_EQ(&node2, node1.GetFirstChild()); + EXPECT_EQ(&node3, node2.GetNextSibling()); + EXPECT_EQ(&node4, node3.GetNextSibling()); + EXPECT_TRUE(node4.GetNextSibling() == nullptr); + + node1.RemoveChildNode(&node2); + EXPECT_TRUE(node2.GetParent() == nullptr); + EXPECT_TRUE(node2.GetNextSibling() == nullptr); + EXPECT_TRUE(node2.GetPrevSiblingForTesting() == nullptr); + + EXPECT_EQ(&node3, node1.GetFirstChild()); + EXPECT_TRUE(node3.GetPrevSiblingForTesting() == nullptr); + EXPECT_EQ(&node4, node3.GetNextSibling()); + EXPECT_TRUE(node4.GetNextSibling() == nullptr); } TEST(CFX_XMLNodeTest, RemovingLastChild) { - auto node1 = pdfium::MakeUnique<CFX_XMLElement>(L"node"); - auto child2 = pdfium::MakeUnique<CFX_XMLElement>(L"node2"); - auto child3 = pdfium::MakeUnique<CFX_XMLElement>(L"node3"); - auto child4 = pdfium::MakeUnique<CFX_XMLElement>(L"node4"); - - CFX_XMLElement* node2 = child2.get(); - CFX_XMLElement* node3 = child3.get(); - CFX_XMLElement* node4 = child4.get(); - - node1->AppendChild(std::move(child2)); - node1->AppendChild(std::move(child3)); - node1->AppendChild(std::move(child4)); - - EXPECT_EQ(node2, node1->GetFirstChild()); - EXPECT_EQ(node3, node2->GetNextSibling()); - EXPECT_EQ(node4, node3->GetNextSibling()); - EXPECT_TRUE(node4->GetNextSibling() == nullptr); - - node1->RemoveChildNode(node4); - // Node is released by parent, so need to take ownership - child4 = pdfium::WrapUnique(node4); - - EXPECT_TRUE(node4->GetParent() == nullptr); - EXPECT_TRUE(node4->GetNextSibling() == nullptr); - EXPECT_TRUE(node4->GetPrevSiblingForTesting() == nullptr); - - EXPECT_EQ(node2, node1->GetFirstChild()); - EXPECT_EQ(node3, node2->GetNextSibling()); - EXPECT_TRUE(node3->GetNextSibling() == nullptr); + CFX_XMLElement node1(L"node1"); + CFX_XMLElement node2(L"node2"); + CFX_XMLElement node3(L"node3"); + CFX_XMLElement node4(L"node4"); + + node1.AppendChild(&node2); + node1.AppendChild(&node3); + node1.AppendChild(&node4); + + EXPECT_EQ(&node2, node1.GetFirstChild()); + EXPECT_EQ(&node3, node2.GetNextSibling()); + EXPECT_EQ(&node4, node3.GetNextSibling()); + EXPECT_TRUE(node4.GetNextSibling() == nullptr); + + node1.RemoveChildNode(&node4); + EXPECT_TRUE(node4.GetParent() == nullptr); + EXPECT_TRUE(node4.GetNextSibling() == nullptr); + EXPECT_TRUE(node4.GetPrevSiblingForTesting() == nullptr); + + EXPECT_EQ(&node2, node1.GetFirstChild()); + EXPECT_EQ(&node3, node2.GetNextSibling()); + EXPECT_TRUE(node3.GetNextSibling() == nullptr); } TEST(CFX_XMLNodeTest, RemovingOnlyChild) { - auto node1 = pdfium::MakeUnique<CFX_XMLElement>(L"node"); - auto child2 = pdfium::MakeUnique<CFX_XMLElement>(L"node2"); + CFX_XMLElement node1(L"node1"); + CFX_XMLElement node2(L"node2"); - CFX_XMLElement* node2 = child2.get(); + node1.AppendChild(&node2); - node1->AppendChild(std::move(child2)); + EXPECT_EQ(&node2, node1.GetFirstChild()); + EXPECT_TRUE(node2.GetNextSibling() == nullptr); - EXPECT_EQ(node2, node1->GetFirstChild()); - EXPECT_TRUE(node2->GetNextSibling() == nullptr); + node1.RemoveChildNode(&node2); + EXPECT_TRUE(node2.GetParent() == nullptr); - node1->RemoveChildNode(node2); - // Node is released by parent, so need to take ownership - child2 = pdfium::WrapUnique(node2); - - EXPECT_TRUE(node2->GetParent() == nullptr); - - EXPECT_TRUE(node1->GetFirstChild() == nullptr); - EXPECT_TRUE(node2->GetNextSibling() == nullptr); - EXPECT_TRUE(node2->GetPrevSiblingForTesting() == nullptr); + EXPECT_TRUE(node1.GetFirstChild() == nullptr); + EXPECT_TRUE(node2.GetNextSibling() == nullptr); + EXPECT_TRUE(node2.GetPrevSiblingForTesting() == nullptr); } TEST(CFX_XMLNodeTest, RemoveMissingChild) { - auto node1 = pdfium::MakeUnique<CFX_XMLElement>(L"node"); - auto child2 = pdfium::MakeUnique<CFX_XMLElement>(L"node2"); - auto child3 = pdfium::MakeUnique<CFX_XMLElement>(L"node3"); - - CFX_XMLElement* node2 = child2.get(); - CFX_XMLElement* node3 = child3.get(); + CFX_XMLElement node1(L"node1"); + CFX_XMLElement node2(L"node2"); + CFX_XMLElement node3(L"node3"); - node1->AppendChild(std::move(child2)); - node1->RemoveChildNode(node3); + node1.AppendChild(&node2); + node1.RemoveChildNode(&node3); - EXPECT_TRUE(node3->GetParent() == nullptr); - EXPECT_EQ(node2, node1->GetFirstChild()); - EXPECT_TRUE(node2->GetNextSibling() == nullptr); + EXPECT_TRUE(node3.GetParent() == nullptr); + EXPECT_EQ(&node2, node1.GetFirstChild()); + EXPECT_TRUE(node2.GetNextSibling() == nullptr); } diff --git a/core/fxcrt/xml/cfx_xmlparser.cpp b/core/fxcrt/xml/cfx_xmlparser.cpp index c7a81afc16..b7dbd19eab 100644 --- a/core/fxcrt/xml/cfx_xmlparser.cpp +++ b/core/fxcrt/xml/cfx_xmlparser.cpp @@ -16,6 +16,7 @@ #include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_safe_types.h" #include "core/fxcrt/xml/cfx_xmlchardata.h" +#include "core/fxcrt/xml/cfx_xmldocument.h" #include "core/fxcrt/xml/cfx_xmlelement.h" #include "core/fxcrt/xml/cfx_xmlinstruction.h" #include "core/fxcrt/xml/cfx_xmlnode.h" @@ -58,10 +59,7 @@ bool CFX_XMLParser::IsXMLNameChar(wchar_t ch, bool bFirstChar) { (!bFirstChar || it->bStartChar); } -CFX_XMLParser::CFX_XMLParser(CFX_XMLNode* pParent, - const RetainPtr<IFX_SeekableReadStream>& pStream) - : m_pParent(pParent) { - ASSERT(m_pParent); +CFX_XMLParser::CFX_XMLParser(const RetainPtr<IFX_SeekableReadStream>& pStream) { ASSERT(pStream); auto proxy = pdfium::MakeRetain<CFX_SeekableStreamProxy>(pStream); @@ -89,56 +87,51 @@ CFX_XMLParser::CFX_XMLParser(CFX_XMLNode* pParent, CFX_XMLParser::~CFX_XMLParser() = default; -bool CFX_XMLParser::Parse() { +std::unique_ptr<CFX_XMLDocument> CFX_XMLParser::Parse() { + auto doc = pdfium::MakeUnique<CFX_XMLDocument>(); + current_node_ = doc->GetRoot(); + int32_t iCount = 0; while (true) { FX_XmlSyntaxResult result = DoSyntaxParse(); if (result == FX_XmlSyntaxResult::Error) - return false; + return nullptr; if (result == FX_XmlSyntaxResult::EndOfString) break; switch (result) { case FX_XmlSyntaxResult::InstructionClose: - if (m_pChild && m_pChild->GetType() != FX_XMLNODE_Instruction) - return false; - - m_pChild = m_pParent; + if (current_node_ && current_node_->GetType() == FX_XMLNODE_Instruction) + current_node_ = current_node_->GetParent(); break; case FX_XmlSyntaxResult::ElementClose: { - if (m_pChild->GetType() != FX_XMLNODE_Element) - return false; + if (current_node_->GetType() != FX_XMLNODE_Element) + return nullptr; WideString element_name = GetTextData(); if (element_name.GetLength() > 0 && - element_name != static_cast<CFX_XMLElement*>(m_pChild)->GetName()) { - return false; + element_name != + static_cast<CFX_XMLElement*>(current_node_)->GetName()) { + return nullptr; } - if (!m_pChild || !m_pChild->GetParent()) - return false; - - m_pParent = m_pChild->GetParent(); - m_pChild = m_pParent; + current_node_ = current_node_->GetParent(); iCount++; break; } case FX_XmlSyntaxResult::TargetName: { WideString target_name = GetTextData(); if (target_name == L"originalXFAVersion" || target_name == L"acrobat") { - auto child = pdfium::MakeUnique<CFX_XMLInstruction>(target_name); - m_pChild = child.get(); - m_pParent->AppendChild(std::move(child)); - } else { - m_pChild = nullptr; + auto* node = doc->CreateNode<CFX_XMLInstruction>(target_name); + current_node_->AppendChild(node); + current_node_ = node; } break; } case FX_XmlSyntaxResult::TagName: { - auto child = pdfium::MakeUnique<CFX_XMLElement>(GetTextData()); - m_pChild = child.get(); - m_pParent->AppendChild(std::move(child)); - m_pParent = m_pChild; + auto* child = doc->CreateNode<CFX_XMLElement>(GetTextData()); + current_node_->AppendChild(child); + current_node_ = child; break; } case FX_XmlSyntaxResult::AttriName: { @@ -146,35 +139,29 @@ bool CFX_XMLParser::Parse() { break; } case FX_XmlSyntaxResult::AttriValue: - if (m_pChild && m_pChild->GetType() == FX_XMLNODE_Element) { - static_cast<CFX_XMLElement*>(m_pChild)->SetAttribute( - current_attribute_name_, GetTextData()); + if (current_node_ && current_node_->GetType() == FX_XMLNODE_Element) { + static_cast<CFX_XMLElement*>(current_node_) + ->SetAttribute(current_attribute_name_, GetTextData()); } current_attribute_name_.clear(); break; case FX_XmlSyntaxResult::Text: { - auto child = pdfium::MakeUnique<CFX_XMLText>(GetTextData()); - m_pChild = child.get(); - m_pParent->AppendChild(std::move(child)); - m_pChild = m_pParent; + current_node_->AppendChild(doc->CreateNode<CFX_XMLText>(GetTextData())); break; } case FX_XmlSyntaxResult::CData: { - auto child = pdfium::MakeUnique<CFX_XMLCharData>(GetTextData()); - m_pChild = child.get(); - m_pParent->AppendChild(std::move(child)); - m_pChild = m_pParent; + current_node_->AppendChild( + doc->CreateNode<CFX_XMLCharData>(GetTextData())); break; } case FX_XmlSyntaxResult::TargetData: { WideString target_data = GetTextData(); - if (m_pChild) { - if (m_pChild->GetType() != FX_XMLNODE_Instruction) - return false; - - auto* instruction = static_cast<CFX_XMLInstruction*>(m_pChild); - if (!target_data.IsEmpty()) - instruction->AppendData(target_data); + if (current_node_ && + current_node_->GetType() == FX_XMLNODE_Instruction) { + if (target_data.IsEmpty()) + break; + static_cast<CFX_XMLInstruction*>(current_node_) + ->AppendData(target_data); } break; } @@ -185,7 +172,7 @@ bool CFX_XMLParser::Parse() { break; } } - return !m_pParent || m_pParent->GetParent() ? false : GetStatus(); + return doc; } FX_XmlSyntaxResult CFX_XMLParser::DoSyntaxParse() { diff --git a/core/fxcrt/xml/cfx_xmlparser.h b/core/fxcrt/xml/cfx_xmlparser.h index e2a2d5b30f..6bf1946402 100644 --- a/core/fxcrt/xml/cfx_xmlparser.h +++ b/core/fxcrt/xml/cfx_xmlparser.h @@ -15,6 +15,7 @@ #include "core/fxcrt/retain_ptr.h" #include "core/fxcrt/xml/cfx_xmlnode.h" +class CFX_XMLDocument; class CFX_XMLElement; class CFX_XMLNode; class IFX_SeekableReadStream; @@ -41,11 +42,10 @@ class CFX_XMLParser { public: static bool IsXMLNameChar(wchar_t ch, bool bFirstChar); - CFX_XMLParser(CFX_XMLNode* pParent, - const RetainPtr<IFX_SeekableReadStream>& pStream); + explicit CFX_XMLParser(const RetainPtr<IFX_SeekableReadStream>& pStream); virtual ~CFX_XMLParser(); - bool Parse(); + std::unique_ptr<CFX_XMLDocument> Parse(); protected: FX_XmlSyntaxResult DoSyntaxParse(); @@ -74,8 +74,7 @@ class CFX_XMLParser { void ParseTextChar(wchar_t ch); bool GetStatus() const; - CFX_XMLNode* m_pParent; - CFX_XMLNode* m_pChild = nullptr; + CFX_XMLNode* current_node_ = nullptr; WideString current_attribute_name_; RetainPtr<IFX_SeekableReadStream> m_pStream; FX_FILESIZE m_Start = 0; // Start position in m_Buffer diff --git a/core/fxcrt/xml/cfx_xmlparser_unittest.cpp b/core/fxcrt/xml/cfx_xmlparser_unittest.cpp index 73d6685dad..7ca242211d 100644 --- a/core/fxcrt/xml/cfx_xmlparser_unittest.cpp +++ b/core/fxcrt/xml/cfx_xmlparser_unittest.cpp @@ -8,7 +8,9 @@ #include "core/fxcrt/cfx_memorystream.h" #include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/xml/cfx_xmldocument.h" #include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlinstruction.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/test_support.h" #include "third_party/base/ptr_util.h" @@ -17,9 +19,8 @@ namespace { class CFX_XMLTestParser : public CFX_XMLParser { public: - CFX_XMLTestParser(CFX_XMLNode* pParent, - const RetainPtr<IFX_SeekableStream>& pStream) - : CFX_XMLParser(pParent, pStream) {} + explicit CFX_XMLTestParser(const RetainPtr<IFX_SeekableStream>& pStream) + : CFX_XMLParser(pStream) {} ~CFX_XMLTestParser() override = default; @@ -52,9 +53,7 @@ TEST(CFX_XMLParserTest, CData) { L" "; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -98,9 +97,7 @@ TEST(CFX_XMLParserTest, CDataWithInnerScript) { L" "; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -133,9 +130,7 @@ TEST(CFX_XMLParserTest, ArrowBangArrow) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); @@ -166,9 +161,7 @@ TEST(CFX_XMLParserTest, ArrowBangBracketArrow) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -194,9 +187,7 @@ TEST(CFX_XMLParserTest, IncompleteCData) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -222,9 +213,7 @@ TEST(CFX_XMLParserTest, UnClosedCData) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -250,9 +239,7 @@ TEST(CFX_XMLParserTest, EmptyCData) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -285,9 +272,7 @@ TEST(CFX_XMLParserTest, Comment) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -317,9 +302,7 @@ TEST(CFX_XMLParserTest, IncorrectCommentStart) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -349,9 +332,7 @@ TEST(CFX_XMLParserTest, CommentEmpty) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -381,9 +362,7 @@ TEST(CFX_XMLParserTest, CommentThreeDash) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -407,9 +386,7 @@ TEST(CFX_XMLParserTest, CommentTwoDash) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -444,9 +421,7 @@ TEST(CFX_XMLParserTest, Entities) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -474,9 +449,7 @@ TEST(CFX_XMLParserTest, EntityOverflowHex) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -504,9 +477,7 @@ TEST(CFX_XMLParserTest, EntityOverflowDecimal) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); @@ -547,9 +518,7 @@ TEST(CFX_XMLParserTest, BadElementClose) { const char* input = "</endtag>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::Error, parser.DoSyntaxParse()); } @@ -557,9 +526,7 @@ TEST(CFX_XMLParserTest, DoubleElementClose) { const char* input = "<p></p></p>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"p", parser.GetTextData()); @@ -570,6 +537,26 @@ TEST(CFX_XMLParserTest, DoubleElementClose) { ASSERT_EQ(FX_XmlSyntaxResult::Error, parser.DoSyntaxParse()); } +TEST(CFX_XMLParserTest, ParseInstruction) { + const char* input = + "<?originalXFAVersion http://www.xfa.org/schema/xfa-template/3.3/ ?>" + "<form></form>"; + + auto stream = MakeProxy(input); + CFX_XMLTestParser parser(stream); + + auto doc = parser.Parse(); + ASSERT_TRUE(doc.get() != nullptr); + + CFX_XMLElement* root = doc->GetRoot(); + ASSERT_TRUE(root->GetFirstChild() != nullptr); + ASSERT_EQ(FX_XMLNODE_Instruction, root->GetFirstChild()->GetType()); + + CFX_XMLInstruction* instruction = + static_cast<CFX_XMLInstruction*>(root->GetFirstChild()); + EXPECT_TRUE(instruction->IsOriginalXFAVersion()); +} + TEST(CFX_XMLParserTest, BadEntity) { const char* input = "<script>" @@ -577,9 +564,7 @@ TEST(CFX_XMLParserTest, BadEntity) { "</script>"; auto stream = MakeProxy(input); - auto root = pdfium::MakeUnique<CFX_XMLElement>(L"ROOT"); - - CFX_XMLTestParser parser(root.get(), stream); + CFX_XMLTestParser parser(stream); ASSERT_EQ(FX_XmlSyntaxResult::ElementOpen, parser.DoSyntaxParse()); ASSERT_EQ(FX_XmlSyntaxResult::TagName, parser.DoSyntaxParse()); ASSERT_EQ(L"script", parser.GetTextData()); diff --git a/core/fxcrt/xml/cfx_xmltext.cpp b/core/fxcrt/xml/cfx_xmltext.cpp index 2c324be1c9..73f0477482 100644 --- a/core/fxcrt/xml/cfx_xmltext.cpp +++ b/core/fxcrt/xml/cfx_xmltext.cpp @@ -6,6 +6,7 @@ #include "core/fxcrt/xml/cfx_xmltext.h" +#include "core/fxcrt/xml/cfx_xmldocument.h" #include "third_party/base/ptr_util.h" CFX_XMLText::CFX_XMLText(const WideString& wsText) @@ -17,8 +18,8 @@ FX_XMLNODETYPE CFX_XMLText::GetType() const { return FX_XMLNODE_Text; } -std::unique_ptr<CFX_XMLNode> CFX_XMLText::Clone() { - return pdfium::MakeUnique<CFX_XMLText>(m_wsText); +CFX_XMLNode* CFX_XMLText::Clone(CFX_XMLDocument* doc) { + return doc->CreateNode<CFX_XMLText>(m_wsText); } void CFX_XMLText::Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) { diff --git a/core/fxcrt/xml/cfx_xmltext.h b/core/fxcrt/xml/cfx_xmltext.h index cc9c71d01c..c5c168059d 100644 --- a/core/fxcrt/xml/cfx_xmltext.h +++ b/core/fxcrt/xml/cfx_xmltext.h @@ -12,6 +12,8 @@ #include "core/fxcrt/fx_string.h" #include "core/fxcrt/xml/cfx_xmlnode.h" +class CFX_XMLDocument; + class CFX_XMLText : public CFX_XMLNode { public: explicit CFX_XMLText(const WideString& wsText); @@ -19,7 +21,7 @@ class CFX_XMLText : public CFX_XMLNode { // CFX_XMLNode FX_XMLNODETYPE GetType() const override; - std::unique_ptr<CFX_XMLNode> Clone() override; + CFX_XMLNode* Clone(CFX_XMLDocument* doc) override; void Save(const RetainPtr<IFX_SeekableWriteStream>& pXMLStream) override; WideString GetText() const { return m_wsText; } diff --git a/core/fxcrt/xml/cfx_xmltext_unittest.cpp b/core/fxcrt/xml/cfx_xmltext_unittest.cpp index ab977e9546..6e53f66612 100644 --- a/core/fxcrt/xml/cfx_xmltext_unittest.cpp +++ b/core/fxcrt/xml/cfx_xmltext_unittest.cpp @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "core/fxcrt/xml/cfx_xmltext.h" +#include "core/fxcrt/xml/cfx_xmldocument.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/string_write_stream.h" #include "testing/test_support.h" @@ -18,11 +19,13 @@ TEST(CFX_XMLTextTest, GetText) { } TEST(CFX_XMLTextTest, Clone) { + CFX_XMLDocument doc; + CFX_XMLText data(L"My Data"); - auto clone = data.Clone(); + CFX_XMLNode* clone = data.Clone(&doc); EXPECT_TRUE(clone != nullptr); ASSERT_EQ(FX_XMLNODE_Text, clone->GetType()); - EXPECT_EQ(L"My Data", static_cast<CFX_XMLText*>(clone.get())->GetText()); + EXPECT_EQ(L"My Data", static_cast<CFX_XMLText*>(clone)->GetText()); } TEST(CFX_XMLTextTest, Save) { |