Clean up CXML_Element.

- Set more members in the ctor
- Remove dead code
- Use more unique_ptrs

Change-Id: Idfe85d07c784a57862f9314bc85f407f817b8f2f
Reviewed-on: https://pdfium-review.googlesource.com/2844
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Nicolás Peña <npm@chromium.org>
Reviewed-by: dsinclair <dsinclair@chromium.org>
diff --git a/core/fpdfdoc/cpdf_metadata.cpp b/core/fpdfdoc/cpdf_metadata.cpp
index bdb70c0..5e3acbe 100644
--- a/core/fpdfdoc/cpdf_metadata.cpp
+++ b/core/fpdfdoc/cpdf_metadata.cpp
@@ -22,7 +22,7 @@
 
   CPDF_StreamAcc acc;
   acc.LoadAllData(pStream, false);
-  m_pXmlElement.reset(CXML_Element::Parse(acc.GetData(), acc.GetSize()));
+  m_pXmlElement = CXML_Element::Parse(acc.GetData(), acc.GetSize());
 }
 
 CPDF_Metadata::~CPDF_Metadata() {}
diff --git a/core/fxcrt/fx_xml.h b/core/fxcrt/fx_xml.h
index 38a1b60..87f1915 100644
--- a/core/fxcrt/fx_xml.h
+++ b/core/fxcrt/fx_xml.h
@@ -54,26 +54,18 @@
  public:
   enum ChildType { Invalid, Element, Content };
 
-  static CXML_Element* Parse(const void* pBuffer,
-                             size_t size,
-                             bool bSaveSpaceChars = false,
-                             FX_FILESIZE* pParsedSize = nullptr);
-  static CXML_Element* Parse(const CFX_RetainPtr<IFX_SeekableReadStream>& pFile,
-                             bool bSaveSpaceChars = false,
-                             FX_FILESIZE* pParsedSize = nullptr);
-  static CXML_Element* Parse(
-      const CFX_RetainPtr<IFX_BufferedReadStream>& pBuffer,
-      bool bSaveSpaceChars = false,
-      FX_FILESIZE* pParsedSize = nullptr);
+  static std::unique_ptr<CXML_Element> Parse(const void* pBuffer, size_t size);
 
-  CXML_Element();
+  CXML_Element(const CXML_Element* pParent,
+               const CFX_ByteStringC& qSpace,
+               const CFX_ByteStringC& tagname);
   ~CXML_Element();
 
   void Empty();
   CFX_ByteString GetTagName(bool bQualified = false) const;
   CFX_ByteString GetNamespace(bool bQualified = false) const;
   CFX_ByteString GetNamespaceURI(const CFX_ByteString& qName) const;
-  CXML_Element* GetParent() const { return m_pParent; }
+  const CXML_Element* GetParent() const { return m_pParent; }
   uint32_t CountAttrs() const { return m_AttrMap.GetSize(); }
   void GetAttrByIndex(int index,
                       CFX_ByteString& space,
@@ -148,7 +140,6 @@
                            int index) const;
 
   uint32_t FindElement(CXML_Element* pChild) const;
-  void SetTag(const CFX_ByteStringC& qSpace, const CFX_ByteStringC& tagname);
   void SetTag(const CFX_ByteStringC& qTagName);
   void RemoveChildren();
   void RemoveChild(uint32_t index);
@@ -159,7 +150,7 @@
     void* child;  // CXML_Element and CXML_Content lack a common ancestor.
   };
 
-  CXML_Element* m_pParent;
+  const CXML_Element* const m_pParent;
   CFX_ByteString m_QSpaceName;
   CFX_ByteString m_TagName;
   CXML_AttrMap m_AttrMap;
diff --git a/core/fxcrt/fx_xml_composer.cpp b/core/fxcrt/fx_xml_composer.cpp
index 91118a0..637d64c 100644
--- a/core/fxcrt/fx_xml_composer.cpp
+++ b/core/fxcrt/fx_xml_composer.cpp
@@ -23,14 +23,10 @@
   }
 }
 
-void CXML_Element::SetTag(const CFX_ByteStringC& qSpace,
-                          const CFX_ByteStringC& tagname) {
-  m_QSpaceName = qSpace;
-  m_TagName = tagname;
-}
 void CXML_Element::SetTag(const CFX_ByteStringC& qTagName) {
   ASSERT(!qTagName.IsEmpty());
-  CFX_ByteStringC bsSpace, bsName;
+  CFX_ByteStringC bsSpace;
+  CFX_ByteStringC bsName;
   FX_XML_SplitQualifiedName(qTagName, bsSpace, bsName);
   m_QSpaceName = bsSpace;
   m_TagName = bsName;
diff --git a/core/fxcrt/fx_xml_parser.cpp b/core/fxcrt/fx_xml_parser.cpp
index 2250087..761aae7 100644
--- a/core/fxcrt/fx_xml_parser.cpp
+++ b/core/fxcrt/fx_xml_parser.cpp
@@ -4,13 +4,13 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#include "core/fxcrt/xml_int.h"
-
 #include <algorithm>
+#include <memory>
 #include <vector>
 
 #include "core/fxcrt/fx_ext.h"
 #include "core/fxcrt/fx_xml.h"
+#include "core/fxcrt/xml_int.h"
 #include "third_party/base/ptr_util.h"
 #include "third_party/base/stl_util.h"
 
@@ -101,7 +101,7 @@
 }
 
 FX_FILESIZE CXML_DataBufAcc::GetPosition() {
-  return (FX_FILESIZE)m_dwCurPos;
+  return static_cast<FX_FILESIZE>(m_dwCurPos);
 }
 
 size_t CXML_DataBufAcc::ReadBlock(void* buffer, size_t size) {
@@ -167,11 +167,12 @@
 }
 
 bool CXML_DataStmAcc::IsEOF() {
-  return m_nStart + (FX_FILESIZE)m_dwSize >= m_pFileRead->GetSize();
+  return m_nStart + static_cast<FX_FILESIZE>(m_dwSize) >=
+         m_pFileRead->GetSize();
 }
 
 FX_FILESIZE CXML_DataStmAcc::GetPosition() {
-  return m_nStart + (FX_FILESIZE)m_dwSize;
+  return m_nStart + static_cast<FX_FILESIZE>(m_dwSize);
 }
 
 size_t CXML_DataStmAcc::ReadBlock(void* buffer, size_t size) {
@@ -183,7 +184,7 @@
     m_nStart = 0;
 
   FX_FILESIZE nLength = m_pFileRead->GetSize();
-  m_nStart += (FX_FILESIZE)m_dwSize;
+  m_nStart += static_cast<FX_FILESIZE>(m_dwSize);
   if (m_nStart >= nLength)
     return false;
 
@@ -212,7 +213,6 @@
 
 CXML_Parser::CXML_Parser()
     : m_nOffset(0),
-      m_bSaveSpaceChars(false),
       m_pBuffer(nullptr),
       m_dwBufferSize(0),
       m_nBufferOffset(0),
@@ -220,25 +220,8 @@
 
 CXML_Parser::~CXML_Parser() {}
 
-bool CXML_Parser::Init(uint8_t* pBuffer, size_t size) {
+bool CXML_Parser::Init(const uint8_t* pBuffer, size_t size) {
   m_pDataAcc = pdfium::MakeRetain<CXML_DataBufAcc>(pBuffer, size);
-  return Init();
-}
-
-bool CXML_Parser::Init(const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead) {
-  m_pDataAcc = pdfium::MakeRetain<CXML_DataStmAcc>(pFileRead);
-  return Init();
-}
-
-bool CXML_Parser::Init(const CFX_RetainPtr<IFX_BufferedReadStream>& pBuffer) {
-  if (!pBuffer)
-    return false;
-
-  m_pDataAcc = pBuffer;
-  return Init();
-}
-
-bool CXML_Parser::Init() {
   m_nOffset = 0;
   return ReadNextBlock();
 }
@@ -259,33 +242,33 @@
 }
 
 void CXML_Parser::SkipWhiteSpaces() {
-  m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-  if (IsEOF()) {
+  m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+  if (IsEOF())
     return;
-  }
+
   do {
     while (m_dwIndex < m_dwBufferSize &&
            g_FXCRT_XML_IsWhiteSpace(m_pBuffer[m_dwIndex])) {
       m_dwIndex++;
     }
-    m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-    if (m_dwIndex < m_dwBufferSize || IsEOF()) {
+    m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+    if (m_dwIndex < m_dwBufferSize || IsEOF())
       break;
-    }
   } while (ReadNextBlock());
 }
-void CXML_Parser::GetName(CFX_ByteString& space, CFX_ByteString& name) {
-  m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-  if (IsEOF()) {
+
+void CXML_Parser::GetName(CFX_ByteString* space, CFX_ByteString* name) {
+  m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+  if (IsEOF())
     return;
-  }
+
   CFX_ByteTextBuf buf;
   uint8_t ch;
   do {
     while (m_dwIndex < m_dwBufferSize) {
       ch = m_pBuffer[m_dwIndex];
       if (ch == ':') {
-        space = buf.AsStringC();
+        *space = buf.AsStringC();
         buf.Clear();
       } else if (g_FXCRT_XML_IsNameChar(ch)) {
         buf.AppendChar(ch);
@@ -294,15 +277,15 @@
       }
       m_dwIndex++;
     }
-    m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-    if (m_dwIndex < m_dwBufferSize || IsEOF()) {
+    m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+    if (m_dwIndex < m_dwBufferSize || IsEOF())
       break;
-    }
   } while (ReadNextBlock());
-  name = buf.AsStringC();
+  *name = buf.AsStringC();
 }
+
 void CXML_Parser::SkipLiterals(const CFX_ByteStringC& str) {
-  m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
+  m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
   if (IsEOF()) {
     return;
   }
@@ -311,32 +294,31 @@
     while (m_dwIndex < m_dwBufferSize) {
       if (str.GetAt(i) != m_pBuffer[m_dwIndex++]) {
         i = 0;
-      } else {
-        i++;
-        if (i == iLen) {
-          break;
-        }
+        continue;
       }
+      i++;
+      if (i == iLen)
+        break;
     }
-    m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-    if (i == iLen) {
+    m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+    if (i == iLen)
       return;
-    }
-    if (m_dwIndex < m_dwBufferSize || IsEOF()) {
+
+    if (m_dwIndex < m_dwBufferSize || IsEOF())
       break;
-    }
   } while (ReadNextBlock());
   while (!m_pDataAcc->IsEOF()) {
     ReadNextBlock();
-    m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwBufferSize;
+    m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwBufferSize);
   }
   m_dwIndex = m_dwBufferSize;
 }
+
 uint32_t CXML_Parser::GetCharRef() {
-  m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-  if (IsEOF()) {
+  m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+  if (IsEOF())
     return 0;
-  }
+
   uint8_t ch;
   int32_t iState = 0;
   CFX_ByteTextBuf buf;
@@ -356,17 +338,16 @@
           m_dwIndex++;
           if (ch == ';') {
             CFX_ByteStringC ref = buf.AsStringC();
-            if (ref == "gt") {
+            if (ref == "gt")
               code = '>';
-            } else if (ref == "lt") {
+            else if (ref == "lt")
               code = '<';
-            } else if (ref == "amp") {
+            else if (ref == "amp")
               code = '&';
-            } else if (ref == "apos") {
+            else if (ref == "apos")
               code = '\'';
-            } else if (ref == "quot") {
+            else if (ref == "quot")
               code = '"';
-            }
             iState = 10;
             break;
           }
@@ -408,40 +389,40 @@
           }
           break;
       }
-      if (iState == 10) {
+      if (iState == 10)
         break;
-      }
     }
-    m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
+    m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
     if (iState == 10 || m_dwIndex < m_dwBufferSize || IsEOF()) {
       break;
     }
   } while (ReadNextBlock());
   return code;
 }
+
 void CXML_Parser::GetAttrValue(CFX_WideString& value) {
-  m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-  if (IsEOF()) {
+  m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+  if (IsEOF())
     return;
-  }
+
   CFX_UTF8Decoder decoder;
   uint8_t mark = 0, ch = 0;
   do {
     while (m_dwIndex < m_dwBufferSize) {
       ch = m_pBuffer[m_dwIndex];
       if (mark == 0) {
-        if (ch != '\'' && ch != '"') {
+        if (ch != '\'' && ch != '"')
           return;
-        }
+
         mark = ch;
         m_dwIndex++;
         ch = 0;
         continue;
       }
       m_dwIndex++;
-      if (ch == mark) {
+      if (ch == mark)
         break;
-      }
+
       if (ch == '&') {
         decoder.AppendChar(GetCharRef());
         if (IsEOF()) {
@@ -452,22 +433,22 @@
         decoder.Input(ch);
       }
     }
-    m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-    if (ch == mark || m_dwIndex < m_dwBufferSize || IsEOF()) {
+    m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+    if (ch == mark || m_dwIndex < m_dwBufferSize || IsEOF())
       break;
-    }
   } while (ReadNextBlock());
   value = decoder.GetResult();
 }
-void CXML_Parser::GetTagName(CFX_ByteString& space,
-                             CFX_ByteString& name,
-                             bool& bEndTag,
-                             bool bStartTag) {
-  m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-  if (IsEOF()) {
+
+void CXML_Parser::GetTagName(bool bStartTag,
+                             bool* bEndTag,
+                             CFX_ByteString* space,
+                             CFX_ByteString* name) {
+  m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+  if (IsEOF())
     return;
-  }
-  bEndTag = false;
+
+  *bEndTag = false;
   uint8_t ch;
   int32_t iState = bStartTag ? 1 : 0;
   do {
@@ -476,9 +457,9 @@
       switch (iState) {
         case 0:
           m_dwIndex++;
-          if (ch != '<') {
+          if (ch != '<')
             break;
-          }
+
           iState = 1;
           break;
         case 1:
@@ -487,7 +468,8 @@
             SkipLiterals("?>");
             iState = 0;
             break;
-          } else if (ch == '!') {
+          }
+          if (ch == '!') {
             m_dwIndex++;
             SkipLiterals("-->");
             iState = 0;
@@ -496,85 +478,85 @@
           if (ch == '/') {
             m_dwIndex++;
             GetName(space, name);
-            bEndTag = true;
+            *bEndTag = true;
           } else {
             GetName(space, name);
-            bEndTag = false;
+            *bEndTag = false;
           }
           return;
       }
     }
-    m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-    if (m_dwIndex < m_dwBufferSize || IsEOF()) {
+    m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+    if (m_dwIndex < m_dwBufferSize || IsEOF())
       break;
-    }
   } while (ReadNextBlock());
 }
-CXML_Element* CXML_Parser::ParseElement(CXML_Element* pParent, bool bStartTag) {
-  m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-  if (IsEOF()) {
+
+std::unique_ptr<CXML_Element> CXML_Parser::ParseElement(CXML_Element* pParent,
+                                                        bool bStartTag) {
+  m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+  if (IsEOF())
     return nullptr;
-  }
-  CFX_ByteString tag_name, tag_space;
+
+  CFX_ByteString tag_name;
+  CFX_ByteString tag_space;
   bool bEndTag;
-  GetTagName(tag_space, tag_name, bEndTag, bStartTag);
-  if (tag_name.IsEmpty() || bEndTag) {
+  GetTagName(bStartTag, &bEndTag, &tag_space, &tag_name);
+  if (tag_name.IsEmpty() || bEndTag)
     return nullptr;
-  }
-  CXML_Element* pElement = new CXML_Element;
-  pElement->m_pParent = pParent;
-  pElement->SetTag(tag_space.AsStringC(), tag_name.AsStringC());
+
+  auto pElement = pdfium::MakeUnique<CXML_Element>(
+      pParent, tag_space.AsStringC(), tag_name.AsStringC());
   do {
-    CFX_ByteString attr_space, attr_name;
+    CFX_ByteString attr_space;
+    CFX_ByteString attr_name;
     while (m_dwIndex < m_dwBufferSize) {
       SkipWhiteSpaces();
-      if (IsEOF()) {
+      if (IsEOF())
         break;
-      }
-      if (!g_FXCRT_XML_IsNameIntro(m_pBuffer[m_dwIndex])) {
+
+      if (!g_FXCRT_XML_IsNameIntro(m_pBuffer[m_dwIndex]))
         break;
-      }
-      GetName(attr_space, attr_name);
+
+      GetName(&attr_space, &attr_name);
       SkipWhiteSpaces();
-      if (IsEOF()) {
+      if (IsEOF())
         break;
-      }
-      if (m_pBuffer[m_dwIndex] != '=') {
+
+      if (m_pBuffer[m_dwIndex] != '=')
         break;
-      }
+
       m_dwIndex++;
       SkipWhiteSpaces();
-      if (IsEOF()) {
+      if (IsEOF())
         break;
-      }
+
       CFX_WideString attr_value;
       GetAttrValue(attr_value);
       pElement->m_AttrMap.SetAt(attr_space, attr_name, attr_value);
     }
-    m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-    if (m_dwIndex < m_dwBufferSize || IsEOF()) {
+    m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+    if (m_dwIndex < m_dwBufferSize || IsEOF())
       break;
-    }
   } while (ReadNextBlock());
   SkipWhiteSpaces();
-  if (IsEOF()) {
+  if (IsEOF())
     return pElement;
-  }
+
   uint8_t ch = m_pBuffer[m_dwIndex++];
   if (ch == '/') {
     m_dwIndex++;
-    m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
+    m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
     return pElement;
   }
   if (ch != '>') {
-    m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-    delete pElement;
+    m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
     return nullptr;
   }
   SkipWhiteSpaces();
-  if (IsEOF()) {
+  if (IsEOF())
     return pElement;
-  }
+
   CFX_UTF8Decoder decoder;
   CFX_WideTextBuf content;
   bool bCDATA = false;
@@ -601,30 +583,31 @@
             SkipWhiteSpaces();
             iState = 0;
           } else if (ch == '/') {
-            CFX_ByteString space, name;
-            GetName(space, name);
+            CFX_ByteString space;
+            CFX_ByteString name;
+            GetName(&space, &name);
             SkipWhiteSpaces();
             m_dwIndex++;
             iState = 10;
           } else {
             content << decoder.GetResult();
             CFX_WideString dataStr = content.MakeString();
-            if (!bCDATA && !m_bSaveSpaceChars) {
+            if (!bCDATA)
               dataStr.TrimRight(L" \t\r\n");
-            }
-            InsertContentSegment(bCDATA, dataStr.AsStringC(), pElement);
+
+            InsertContentSegment(bCDATA, dataStr.AsStringC(), pElement.get());
             content.Clear();
             decoder.Clear();
             bCDATA = false;
             iState = 0;
             m_dwIndex--;
-            CXML_Element* pSubElement = ParseElement(pElement, true);
-            if (!pSubElement) {
+            std::unique_ptr<CXML_Element> pSubElement(
+                ParseElement(pElement.get(), true));
+            if (!pSubElement)
               break;
-            }
-            pSubElement->m_pParent = pElement;
+
             pElement->m_Children.push_back(
-                {CXML_Element::Element, pSubElement});
+                {CXML_Element::Element, pSubElement.release()});
             SkipWhiteSpaces();
           }
           break;
@@ -646,80 +629,49 @@
         break;
       }
     }
-    m_nOffset = m_nBufferOffset + (FX_FILESIZE)m_dwIndex;
-    if (iState == 10 || m_dwIndex < m_dwBufferSize || IsEOF()) {
+    m_nOffset = m_nBufferOffset + static_cast<FX_FILESIZE>(m_dwIndex);
+    if (iState == 10 || m_dwIndex < m_dwBufferSize || IsEOF())
       break;
-    }
   } while (ReadNextBlock());
   content << decoder.GetResult();
   CFX_WideString dataStr = content.MakeString();
-  if (!m_bSaveSpaceChars) {
-    dataStr.TrimRight(L" \t\r\n");
-  }
-  InsertContentSegment(bCDATA, dataStr.AsStringC(), pElement);
+  dataStr.TrimRight(L" \t\r\n");
+
+  InsertContentSegment(bCDATA, dataStr.AsStringC(), pElement.get());
   content.Clear();
   decoder.Clear();
   bCDATA = false;
   return pElement;
 }
+
 void CXML_Parser::InsertContentSegment(bool bCDATA,
                                        const CFX_WideStringC& content,
                                        CXML_Element* pElement) {
-  if (content.IsEmpty()) {
+  if (content.IsEmpty())
     return;
-  }
+
   CXML_Content* pContent = new CXML_Content;
   pContent->Set(bCDATA, content);
   pElement->m_Children.push_back({CXML_Element::Content, pContent});
 }
-static CXML_Element* XML_ContinueParse(CXML_Parser& parser,
-                                       bool bSaveSpaceChars,
-                                       FX_FILESIZE* pParsedSize) {
-  parser.m_bSaveSpaceChars = bSaveSpaceChars;
-  CXML_Element* pElement = parser.ParseElement(nullptr, false);
-  if (pParsedSize) {
-    *pParsedSize = parser.m_nOffset;
-  }
-  return pElement;
-}
-CXML_Element* CXML_Element::Parse(const void* pBuffer,
-                                  size_t size,
-                                  bool bSaveSpaceChars,
-                                  FX_FILESIZE* pParsedSize) {
+
+std::unique_ptr<CXML_Element> CXML_Element::Parse(const void* pBuffer,
+                                                  size_t size) {
   CXML_Parser parser;
-  if (!parser.Init((uint8_t*)pBuffer, size)) {
+  if (!parser.Init(static_cast<const uint8_t*>(pBuffer), size))
     return nullptr;
-  }
-  return XML_ContinueParse(parser, bSaveSpaceChars, pParsedSize);
+  return parser.ParseElement(nullptr, false);
 }
 
-CXML_Element* CXML_Element::Parse(
-    const CFX_RetainPtr<IFX_SeekableReadStream>& pFile,
-    bool bSaveSpaceChars,
-    FX_FILESIZE* pParsedSize) {
-  CXML_Parser parser;
-  if (!parser.Init(pFile))
-    return nullptr;
+CXML_Element::CXML_Element(const CXML_Element* pParent,
+                           const CFX_ByteStringC& qSpace,
+                           const CFX_ByteStringC& tagname)
+    : m_pParent(pParent), m_QSpaceName(qSpace), m_TagName(tagname) {}
 
-  return XML_ContinueParse(parser, bSaveSpaceChars, pParsedSize);
-}
-
-CXML_Element* CXML_Element::Parse(
-    const CFX_RetainPtr<IFX_BufferedReadStream>& pBuffer,
-    bool bSaveSpaceChars,
-    FX_FILESIZE* pParsedSize) {
-  CXML_Parser parser;
-  if (!parser.Init(pBuffer))
-    return nullptr;
-
-  return XML_ContinueParse(parser, bSaveSpaceChars, pParsedSize);
-}
-
-CXML_Element::CXML_Element()
-    : m_pParent(nullptr), m_QSpaceName(), m_TagName(), m_AttrMap() {}
 CXML_Element::~CXML_Element() {
   Empty();
 }
+
 void CXML_Element::Empty() {
   RemoveChildren();
 }
@@ -754,36 +706,38 @@
   const CFX_WideString* pwsSpace;
   const CXML_Element* pElement = this;
   do {
-    if (qName.IsEmpty()) {
+    if (qName.IsEmpty())
       pwsSpace = pElement->m_AttrMap.Lookup("", "xmlns");
-    } else {
+    else
       pwsSpace = pElement->m_AttrMap.Lookup("xmlns", qName);
-    }
-    if (pwsSpace) {
+    if (pwsSpace)
       break;
-    }
+
     pElement = pElement->GetParent();
   } while (pElement);
   return pwsSpace ? pwsSpace->UTF8Encode() : CFX_ByteString();
 }
+
 void CXML_Element::GetAttrByIndex(int index,
                                   CFX_ByteString& space,
                                   CFX_ByteString& name,
                                   CFX_WideString& value) const {
-  if (index < 0 || index >= m_AttrMap.GetSize()) {
+  if (index < 0 || index >= m_AttrMap.GetSize())
     return;
-  }
+
   CXML_AttrItem& item = m_AttrMap.GetAt(index);
   space = item.m_QSpaceName;
   name = item.m_AttrName;
   value = item.m_Value;
 }
+
 bool CXML_Element::HasAttr(const CFX_ByteStringC& name) const {
   CFX_ByteStringC bsSpace;
   CFX_ByteStringC bsName;
   FX_XML_SplitQualifiedName(name, bsSpace, bsName);
   return !!m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName));
 }
+
 bool CXML_Element::GetAttrValue(const CFX_ByteStringC& name,
                                 CFX_WideString& attribute) const {
   CFX_ByteStringC bsSpace;
@@ -791,17 +745,19 @@
   FX_XML_SplitQualifiedName(name, bsSpace, bsName);
   return GetAttrValue(bsSpace, bsName, attribute);
 }
+
 bool CXML_Element::GetAttrValue(const CFX_ByteStringC& space,
                                 const CFX_ByteStringC& name,
                                 CFX_WideString& attribute) const {
   const CFX_WideString* pValue =
       m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
-  if (pValue) {
-    attribute = *pValue;
-    return true;
-  }
-  return false;
+  if (!pValue)
+    return false;
+
+  attribute = *pValue;
+  return true;
 }
+
 bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& name,
                                   int& attribute) const {
   CFX_ByteStringC bsSpace;
@@ -809,43 +765,49 @@
   FX_XML_SplitQualifiedName(name, bsSpace, bsName);
   const CFX_WideString* pwsValue =
       m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName));
-  if (pwsValue) {
-    attribute = pwsValue->GetInteger();
-    return true;
-  }
-  return false;
+  if (!pwsValue)
+    return false;
+
+  attribute = pwsValue->GetInteger();
+  return true;
 }
+
 bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& space,
                                   const CFX_ByteStringC& name,
                                   int& attribute) const {
   const CFX_WideString* pwsValue =
       m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
-  if (pwsValue) {
-    attribute = pwsValue->GetInteger();
-    return true;
-  }
-  return false;
+  if (!pwsValue)
+    return false;
+
+  attribute = pwsValue->GetInteger();
+  return true;
 }
+
 bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& name,
                                 FX_FLOAT& attribute) const {
-  CFX_ByteStringC bsSpace, bsName;
+  CFX_ByteStringC bsSpace;
+  CFX_ByteStringC bsName;
   FX_XML_SplitQualifiedName(name, bsSpace, bsName);
   return GetAttrFloat(bsSpace, bsName, attribute);
 }
+
 bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& space,
                                 const CFX_ByteStringC& name,
                                 FX_FLOAT& attribute) const {
   const CFX_WideString* pValue =
       m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
-  if (pValue) {
-    attribute = pValue->GetFloat();
-    return true;
-  }
-  return false;
+  if (!pValue)
+    return false;
+
+  attribute = pValue->GetFloat();
+  return true;
 }
+
 CXML_Element::ChildType CXML_Element::GetChildType(uint32_t index) const {
   return index < m_Children.size() ? m_Children[index].type : Invalid;
 }
+
 CFX_WideString CXML_Element::GetContent(uint32_t index) const {
   if (index < m_Children.size() && m_Children[index].type == Content) {
     CXML_Content* pContent =
@@ -855,12 +817,13 @@
   }
   return CFX_WideString();
 }
+
 CXML_Element* CXML_Element::GetElement(uint32_t index) const {
-  if (index < m_Children.size() && m_Children[index].type == Element) {
+  if (index < m_Children.size() && m_Children[index].type == Element)
     return static_cast<CXML_Element*>(m_Children[index].child);
-  }
   return nullptr;
 }
+
 uint32_t CXML_Element::CountElements(const CFX_ByteStringC& space,
                                      const CFX_ByteStringC& tag) const {
   int count = 0;
@@ -876,6 +839,7 @@
   }
   return count;
 }
+
 CXML_Element* CXML_Element::GetElement(const CFX_ByteStringC& space,
                                        const CFX_ByteStringC& tag,
                                        int index) const {
@@ -895,6 +859,7 @@
   }
   return nullptr;
 }
+
 uint32_t CXML_Element::FindElement(CXML_Element* pChild) const {
   int index = 0;
   for (const ChildRecord& record : m_Children) {
diff --git a/core/fxcrt/xml_int.h b/core/fxcrt/xml_int.h
index e617a77..96a7da9 100644
--- a/core/fxcrt/xml_int.h
+++ b/core/fxcrt/xml_int.h
@@ -8,6 +8,7 @@
 #define CORE_FXCRT_XML_INT_H_
 
 #include <algorithm>
+#include <memory>
 
 #include "core/fxcrt/fx_stream.h"
 
@@ -19,23 +20,21 @@
   CXML_Parser();
   ~CXML_Parser();
 
-  bool Init(uint8_t* pBuffer, size_t size);
-  bool Init(const CFX_RetainPtr<IFX_SeekableReadStream>& pFileRead);
-  bool Init(const CFX_RetainPtr<IFX_BufferedReadStream>& pBuffer);
-  bool Init();
+  bool Init(const uint8_t* pBuffer, size_t size);
   bool ReadNextBlock();
   bool IsEOF();
   bool HaveAvailData();
   void SkipWhiteSpaces();
-  void GetName(CFX_ByteString& space, CFX_ByteString& name);
+  void GetName(CFX_ByteString* space, CFX_ByteString* name);
   void GetAttrValue(CFX_WideString& value);
   uint32_t GetCharRef();
-  void GetTagName(CFX_ByteString& space,
-                  CFX_ByteString& name,
-                  bool& bEndTag,
-                  bool bStartTag = false);
+  void GetTagName(bool bStartTag,
+                  bool* bEndTag,
+                  CFX_ByteString* space,
+                  CFX_ByteString* name);
   void SkipLiterals(const CFX_ByteStringC& str);
-  CXML_Element* ParseElement(CXML_Element* pParent, bool bStartTag = false);
+  std::unique_ptr<CXML_Element> ParseElement(CXML_Element* pParent,
+                                             bool bStartTag);
   void InsertContentSegment(bool bCDATA,
                             const CFX_WideStringC& content,
                             CXML_Element* pElement);
@@ -43,7 +42,6 @@
 
   CFX_RetainPtr<IFX_BufferedReadStream> m_pDataAcc;
   FX_FILESIZE m_nOffset;
-  bool m_bSaveSpaceChars;
   const uint8_t* m_pBuffer;
   size_t m_dwBufferSize;
   FX_FILESIZE m_nBufferOffset;
diff --git a/fpdfsdk/pdfwindow/PWL_Edit.cpp b/fpdfsdk/pdfwindow/PWL_Edit.cpp
index 1ba8e7d..b77aad9 100644
--- a/fpdfsdk/pdfwindow/PWL_Edit.cpp
+++ b/fpdfsdk/pdfwindow/PWL_Edit.cpp
@@ -6,6 +6,7 @@
 
 #include "fpdfsdk/pdfwindow/PWL_Edit.h"
 
+#include <memory>
 #include <vector>
 
 #include "core/fpdfapi/font/cpdf_font.h"
@@ -41,35 +42,41 @@
 
 void CPWL_Edit::SetText(const CFX_WideString& csText) {
   CFX_WideString swText = csText;
-  if (HasFlag(PES_RICH)) {
-    CFX_ByteString sValue = CFX_ByteString::FromUnicode(swText);
-    if (CXML_Element* pXML =
-            CXML_Element::Parse(sValue.c_str(), sValue.GetLength())) {
-      int32_t nCount = pXML->CountChildren();
-      bool bFirst = true;
+  if (!HasFlag(PES_RICH)) {
+    m_pEdit->SetText(swText);
+    return;
+  }
 
-      swText.clear();
+  CFX_ByteString sValue = CFX_ByteString::FromUnicode(swText);
+  std::unique_ptr<CXML_Element> pXML(
+      CXML_Element::Parse(sValue.c_str(), sValue.GetLength()));
+  if (!pXML) {
+    m_pEdit->SetText(swText);
+    return;
+  }
 
-      for (int32_t i = 0; i < nCount; i++) {
-        if (CXML_Element* pSubElement = pXML->GetElement(i)) {
-          CFX_ByteString tag = pSubElement->GetTagName();
-          if (tag.EqualNoCase("p")) {
-            int nChild = pSubElement->CountChildren();
-            CFX_WideString swSection;
-            for (int32_t j = 0; j < nChild; j++) {
-              swSection += pSubElement->GetContent(j);
-            }
+  int32_t nCount = pXML->CountChildren();
+  bool bFirst = true;
 
-            if (bFirst)
-              bFirst = false;
-            else
-              swText += FWL_VKEY_Return;
-            swText += swSection;
-          }
-        }
-      }
+  swText.clear();
 
-      delete pXML;
+  for (int32_t i = 0; i < nCount; i++) {
+    CXML_Element* pSubElement = pXML->GetElement(i);
+    if (!pSubElement)
+      continue;
+
+    CFX_ByteString tag = pSubElement->GetTagName();
+    if (tag.EqualNoCase("p")) {
+      int nChild = pSubElement->CountChildren();
+      CFX_WideString swSection;
+      for (int32_t j = 0; j < nChild; j++)
+        swSection += pSubElement->GetContent(j);
+
+      if (bFirst)
+        bFirst = false;
+      else
+        swText += FWL_VKEY_Return;
+      swText += swSection;
     }
   }
 
diff --git a/xfa/fxfa/parser/xfa_localemgr.cpp b/xfa/fxfa/parser/xfa_localemgr.cpp
index cfa5801..0cd64ea 100644
--- a/xfa/fxfa/parser/xfa_localemgr.cpp
+++ b/xfa/fxfa/parser/xfa_localemgr.cpp
@@ -1053,7 +1053,7 @@
   pCodecMgr->GetFlateModule()->FlateOrLZWDecode(false, pBuf, nBufLen, true, 0,
                                                 0, 0, 0, 0, pOut, dwSize);
   if (pOut) {
-    pLocale.reset(CXML_Element::Parse(pOut, dwSize));
+    pLocale = CXML_Element::Parse(pOut, dwSize);
     FX_Free(pOut);
   }
   return pLocale ? std::unique_ptr<IFX_Locale>(