From bdbfc08f96f89581bea277d5ddd9755e893067d7 Mon Sep 17 00:00:00 2001 From: dan sinclair Date: Mon, 16 Apr 2018 17:59:07 +0000 Subject: Convert CXFA_XMLLocale to CFX_XML This CL converts CXFA_XMLLocale to use CFX_XML instead of CXML. Change-Id: I1db617a658548ae5979f2f38d72c5b3000998663 Reviewed-on: https://pdfium-review.googlesource.com/30693 Reviewed-by: Henrique Nakashima Commit-Queue: dsinclair --- core/fxcrt/xml/cfx_xmlelement.cpp | 22 +++ core/fxcrt/xml/cfx_xmlelement.h | 4 + xfa/fxfa/parser/cxfa_xmllocale.cpp | 210 +++++++++++++++----------- xfa/fxfa/parser/cxfa_xmllocale.h | 16 +- xfa/fxfa/parser/cxfa_xmllocale_unittest.cpp | 224 +++++++++++++++------------- 5 files changed, 271 insertions(+), 205 deletions(-) diff --git a/core/fxcrt/xml/cfx_xmlelement.cpp b/core/fxcrt/xml/cfx_xmlelement.cpp index 530752e1dd..27d136305b 100644 --- a/core/fxcrt/xml/cfx_xmlelement.cpp +++ b/core/fxcrt/xml/cfx_xmlelement.cpp @@ -119,3 +119,25 @@ void CFX_XMLElement::Save( } pXMLStream->WriteString(ws.AsStringView()); } + +CFX_XMLElement* CFX_XMLElement::GetFirstChildNamed( + const WideStringView& name) const { + return GetNthChildNamed(name, 0); +} + +CFX_XMLElement* CFX_XMLElement::GetNthChildNamed(const WideStringView& name, + size_t idx) const { + for (auto* child = GetFirstChild(); child; child = child->GetNextSibling()) { + if (child->GetType() != FX_XMLNODE_Element) + continue; + + CFX_XMLElement* elem = static_cast(child); + if (elem->GetName() != name) + continue; + if (idx == 0) + return elem; + + --idx; + } + return nullptr; +} diff --git a/core/fxcrt/xml/cfx_xmlelement.h b/core/fxcrt/xml/cfx_xmlelement.h index e665e24a98..f713114eb7 100644 --- a/core/fxcrt/xml/cfx_xmlelement.h +++ b/core/fxcrt/xml/cfx_xmlelement.h @@ -23,6 +23,10 @@ class CFX_XMLElement : public CFX_XMLAttributeNode { std::unique_ptr Clone() override; void Save(const RetainPtr& pXMLStream) override; + CFX_XMLElement* GetFirstChildNamed(const WideStringView& name) const; + CFX_XMLElement* GetNthChildNamed(const WideStringView& name, + size_t idx) const; + WideString GetLocalTagName() const; WideString GetNamespacePrefix() const; WideString GetNamespaceURI() const; diff --git a/xfa/fxfa/parser/cxfa_xmllocale.cpp b/xfa/fxfa/parser/cxfa_xmllocale.cpp index ce68c71e19..93b84ca367 100644 --- a/xfa/fxfa/parser/cxfa_xmllocale.cpp +++ b/xfa/fxfa/parser/cxfa_xmllocale.cpp @@ -8,8 +8,9 @@ #include -#include "core/fxcrt/xml/cxml_content.h" -#include "core/fxcrt/xml/cxml_element.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxcrt/xml/cfx_xmlelement.h" +#include "core/fxcrt/xml/cfx_xmlparser.h" #include "xfa/fxfa/parser/cxfa_document.h" #include "xfa/fxfa/parser/cxfa_localemgr.h" #include "xfa/fxfa/parser/cxfa_nodelocale.h" @@ -19,92 +20,110 @@ // static std::unique_ptr CXFA_XMLLocale::Create( pdfium::span data) { - std::unique_ptr pLocale = - CXML_Element::Parse(data.data(), data.size()); - return pLocale ? pdfium::MakeUnique(std::move(pLocale)) - : nullptr; + auto root = pdfium::MakeUnique(L"root"); + auto proxy = + pdfium::MakeRetain(data.data(), data.size()); + proxy->SetCodePage(FX_CODEPAGE_UTF8); + + CFX_XMLParser parser(root.get(), proxy); + if (!parser.Parse()) + return nullptr; + + CFX_XMLElement* locale = nullptr; + for (auto* child = root->GetFirstChild(); child; + child = child->GetNextSibling()) { + if (child->GetType() != FX_XMLNODE_Element) + continue; + CFX_XMLElement* elem = static_cast(child); + if (elem->GetName() == L"locale") { + locale = elem; + break; + } + } + if (!locale) + return nullptr; + + return pdfium::MakeUnique(std::move(root), locale); } -CXFA_XMLLocale::CXFA_XMLLocale(std::unique_ptr pLocaleData) - : m_pLocaleData(std::move(pLocaleData)) {} +CXFA_XMLLocale::CXFA_XMLLocale(std::unique_ptr root, + CFX_XMLElement* locale) + : xml_root_(std::move(root)), locale_(locale) { + ASSERT(xml_root_); + ASSERT(locale_); +} CXFA_XMLLocale::~CXFA_XMLLocale() {} WideString CXFA_XMLLocale::GetName() const { - return m_pLocaleData ? m_pLocaleData->GetAttrValue("name") : WideString(); + return locale_->GetString(L"name"); } WideString CXFA_XMLLocale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType) const { - ByteString bsSymbols; - WideString wsName; + WideStringView bsSymbols; + WideStringView bsSymbol; + WideStringView wsName; switch (eType) { case FX_LOCALENUMSYMBOL_Decimal: - bsSymbols = "numberSymbols"; + bsSymbols = L"numberSymbols"; + bsSymbol = L"numberSymbol"; wsName = L"decimal"; break; case FX_LOCALENUMSYMBOL_Grouping: - bsSymbols = "numberSymbols"; + bsSymbols = L"numberSymbols"; + bsSymbol = L"numberSymbol"; wsName = L"grouping"; break; case FX_LOCALENUMSYMBOL_Percent: - bsSymbols = "numberSymbols"; + bsSymbols = L"numberSymbols"; + bsSymbol = L"numberSymbol"; wsName = L"percent"; break; case FX_LOCALENUMSYMBOL_Minus: - bsSymbols = "numberSymbols"; + bsSymbols = L"numberSymbols"; + bsSymbol = L"numberSymbol"; wsName = L"minus"; break; case FX_LOCALENUMSYMBOL_Zero: - bsSymbols = "numberSymbols"; + bsSymbols = L"numberSymbols"; + bsSymbol = L"numberSymbol"; wsName = L"zero"; break; case FX_LOCALENUMSYMBOL_CurrencySymbol: - bsSymbols = "currencySymbols"; + bsSymbols = L"currencySymbols"; + bsSymbol = L"currencySymbol"; wsName = L"symbol"; break; case FX_LOCALENUMSYMBOL_CurrencyName: - bsSymbols = "currencySymbols"; + bsSymbols = L"currencySymbols"; + bsSymbol = L"currencySymbol"; wsName = L"isoname"; break; default: - return WideString(); + return L""; } - CXML_Element* pElement = - m_pLocaleData->GetElement("", bsSymbols.AsStringView(), 0); - if (!pElement) - return WideString(); - - return GetPattern( - pElement, ByteStringView(bsSymbols.c_str(), bsSymbols.GetLength() - 1), - wsName.AsStringView()); + CFX_XMLElement* patterns = locale_->GetFirstChildNamed(bsSymbols); + if (!patterns) + return L""; + + return GetPattern(patterns, bsSymbol, wsName); } WideString CXFA_XMLLocale::GetDateTimeSymbols() const { - if (!m_pLocaleData) - return WideString(); - - CXML_Element* pNumberSymbols = - m_pLocaleData->GetElement("", "dateTimeSymbols", 0); - if (!pNumberSymbols) - return WideString(); - - CXML_Content* pContent = ToContent(pNumberSymbols->GetChild(0)); - if (!pContent) - return WideString(); - - return pContent->m_Content; + CFX_XMLElement* symbols = locale_->GetFirstChildNamed(L"dateTimeSymbols"); + return symbols ? symbols->GetTextData() : L""; } WideString CXFA_XMLLocale::GetMonthName(int32_t nMonth, bool bAbbr) const { - return GetCalendarSymbol("month", nMonth, bAbbr); + return GetCalendarSymbol(L"month", nMonth, bAbbr); } WideString CXFA_XMLLocale::GetDayName(int32_t nWeek, bool bAbbr) const { - return GetCalendarSymbol("day", nWeek, bAbbr); + return GetCalendarSymbol(L"day", nWeek, bAbbr); } WideString CXFA_XMLLocale::GetMeridiemName(bool bAM) const { - return GetCalendarSymbol("meridiem", bAM ? 0 : 1, false); + return GetCalendarSymbol(L"meridiem", bAM ? 0 : 1, false); } FX_TIMEZONE CXFA_XMLLocale::GetTimeZone() const { @@ -112,44 +131,49 @@ FX_TIMEZONE CXFA_XMLLocale::GetTimeZone() const { } WideString CXFA_XMLLocale::GetEraName(bool bAD) const { - return GetCalendarSymbol("era", bAD ? 1 : 0, false); + return GetCalendarSymbol(L"era", bAD ? 1 : 0, false); } -WideString CXFA_XMLLocale::GetCalendarSymbol(const ByteStringView& symbol, - int index, +WideString CXFA_XMLLocale::GetCalendarSymbol(const WideStringView& symbol, + size_t index, bool bAbbr) const { - if (index < 0 || !m_pLocaleData) - return WideString(); - - CXML_Element* pChild = m_pLocaleData->GetElement("", "calendarSymbols", 0); - if (!pChild) - return WideString(); - - ByteString pstrSymbolNames = symbol + "Names"; - CXML_Element* pSymbolNames = - pChild->GetElement("", pstrSymbolNames.AsStringView(), 0); - if (!pSymbolNames) - return WideString(); - - if ((!!pSymbolNames->GetAttrInteger("abbr")) != bAbbr) - pSymbolNames = pChild->GetElement("", pstrSymbolNames.AsStringView(), 1); - - if (!pSymbolNames || (!!pSymbolNames->GetAttrInteger("abbr")) != bAbbr) - return WideString(); - - CXML_Element* pSymbolName = pSymbolNames->GetElement("", symbol, index); - if (!pSymbolName) - return WideString(); + CFX_XMLElement* child = locale_->GetFirstChildNamed(L"calendarSymbols"); + if (!child) + return L""; + + WideString pstrSymbolNames = symbol + L"Names"; + CFX_XMLElement* name_child = nullptr; + for (auto* name = child->GetFirstChild(); name; + name = name->GetNextSibling()) { + if (name->GetType() != FX_XMLNODE_Element) + continue; + + auto* elem = static_cast(name); + if (elem->GetName() != pstrSymbolNames) + continue; + + WideString abbr = elem->GetString(L"abbr"); + bool abbr_value = false; + if (!abbr.IsEmpty()) + abbr_value = abbr == L"1"; + if (abbr_value != bAbbr) + continue; + + name_child = elem; + break; + } + if (!name_child) + return L""; - CXML_Content* pContent = ToContent(pSymbolName->GetChild(0)); - return pContent ? pContent->m_Content : WideString(); + CFX_XMLElement* sym_element = name_child->GetNthChildNamed(symbol, index); + return sym_element ? sym_element->GetTextData() : L""; } WideString CXFA_XMLLocale::GetDatePattern( FX_LOCALEDATETIMESUBCATEGORY eType) const { - CXML_Element* pElement = m_pLocaleData->GetElement("", "datePatterns", 0); - if (!pElement) - return WideString(); + CFX_XMLElement* patterns = locale_->GetFirstChildNamed(L"datePatterns"); + if (!patterns) + return L""; WideString wsName; switch (eType) { @@ -167,14 +191,14 @@ WideString CXFA_XMLLocale::GetDatePattern( wsName = L"long"; break; } - return GetPattern(pElement, "datePattern", wsName.AsStringView()); + return GetPattern(patterns, L"datePattern", wsName.AsStringView()); } WideString CXFA_XMLLocale::GetTimePattern( FX_LOCALEDATETIMESUBCATEGORY eType) const { - CXML_Element* pElement = m_pLocaleData->GetElement("", "timePatterns", 0); - if (!pElement) - return WideString(); + CFX_XMLElement* patterns = locale_->GetFirstChildNamed(L"timePatterns"); + if (!patterns) + return L""; WideString wsName; switch (eType) { @@ -192,25 +216,29 @@ WideString CXFA_XMLLocale::GetTimePattern( wsName = L"long"; break; } - return GetPattern(pElement, "timePattern", wsName.AsStringView()); + return GetPattern(patterns, L"timePattern", wsName.AsStringView()); } WideString CXFA_XMLLocale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const { - return m_pLocaleData->GetElement("", "numberPatterns", 0) - ? XFA_PatternToString(eType) - : WideString(); + CFX_XMLElement* patterns = locale_->GetFirstChildNamed(L"numberPatterns"); + return patterns ? XFA_PatternToString(eType) : L""; } -WideString CXFA_XMLLocale::GetPattern(CXML_Element* pElement, - const ByteStringView& bsTag, +WideString CXFA_XMLLocale::GetPattern(CFX_XMLElement* patterns, + const WideStringView& bsTag, const WideStringView& wsName) const { - size_t iCount = pElement->CountElements("", bsTag); - for (size_t i = 0; i < iCount; i++) { - CXML_Element* pChild = pElement->GetElement("", bsTag, i); - if (pChild->GetAttrValue("name") == wsName) { - CXML_Content* pContent = ToContent(pChild->GetChild(0)); - return pContent ? pContent->m_Content : WideString(); - } + for (auto* child = patterns->GetFirstChild(); child; + child = child->GetNextSibling()) { + if (child->GetType() != FX_XMLNODE_Element) + continue; + + CFX_XMLElement* pattern = static_cast(child); + if (pattern->GetName() != bsTag) + continue; + if (pattern->GetString(L"name") != wsName) + continue; + + return pattern->GetTextData(); } - return WideString(); + return L""; } diff --git a/xfa/fxfa/parser/cxfa_xmllocale.h b/xfa/fxfa/parser/cxfa_xmllocale.h index d1d21e83f1..92bd3607ec 100644 --- a/xfa/fxfa/parser/cxfa_xmllocale.h +++ b/xfa/fxfa/parser/cxfa_xmllocale.h @@ -13,13 +13,14 @@ #include "third_party/base/ptr_util.h" #include "third_party/base/span.h" -class CXML_Element; +class CFX_XMLElement; class CXFA_XMLLocale : public LocaleIface { public: static std::unique_ptr Create(pdfium::span data); - explicit CXFA_XMLLocale(std::unique_ptr pLocaleData); + explicit CXFA_XMLLocale(std::unique_ptr root, + CFX_XMLElement* locale); ~CXFA_XMLLocale() override; // LocaleIface @@ -38,14 +39,15 @@ class CXFA_XMLLocale : public LocaleIface { WideString GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const override; private: - WideString GetPattern(CXML_Element* pElement, - const ByteStringView& bsTag, + WideString GetPattern(CFX_XMLElement* pElement, + const WideStringView& bsTag, const WideStringView& wsName) const; - WideString GetCalendarSymbol(const ByteStringView& symbol, - int index, + WideString GetCalendarSymbol(const WideStringView& symbol, + size_t index, bool bAbbr) const; - std::unique_ptr m_pLocaleData; + std::unique_ptr xml_root_; + UnownedPtr locale_; }; #endif // XFA_FXFA_PARSER_CXFA_XMLLOCALE_H_ diff --git a/xfa/fxfa/parser/cxfa_xmllocale_unittest.cpp b/xfa/fxfa/parser/cxfa_xmllocale_unittest.cpp index a9bda60085..e2c5198eb8 100644 --- a/xfa/fxfa/parser/cxfa_xmllocale_unittest.cpp +++ b/xfa/fxfa/parser/cxfa_xmllocale_unittest.cpp @@ -7,109 +7,89 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/test_support.h" -namespace { - -const char* xml_data = +static const char* xml_data = "" - " " - " " - " January" - " February" - " March" - " April" - " May" - " June" - " July" - " August" - " September" - " October" - " November" - " December" - " " - " " - " Jan" - " Feb" - " Mar" - " Apr" - " May" - " Jun" - " Jul" - " Aug" - " Sep" - " Oct" - " Nov" - " Dec" - " " - " " - " Sunday" - " Monday" - " Tuesday" - " Wednesday" - " Thursday" - " Friday" - " Saturday" - " " - " " - " Sun" - " Mon" - " Tue" - " Wed" - " Thu" - " Fri" - " Sat" - " " - " " - " AM" - " PM" - " " - " " - " BC" - " AD" - " " - " " - " " - " EEEE, MMMM D, YYYY" - " MMMM D, YYYY" - " MMM D, YYYY" - " M/D/YY" - " " - " " - " h:MM:SS A Z" - " h:MM:SS A Z" - " h:MM:SS A" - " h:MM A" - " " - " GyMdkHmsSEDFwWahKzZ" - " " - " z,zz9.zzz" - " $z,zz9.99|($z,zz9.99)" - " z,zz9%" - " " - " " - " ." - " ," - " %" - " -" - " 0" - " " - " " - " $" - " USD" - " ." - " " + "January" + "February" + "March" + "April" + "May" + "June" + "July" + "August" + "September" + "October" + "November" + "December" + "" + "Jan" + "Feb" + "Mar" + "Apr" + "May" + "Jun" + "Jul" + "Aug" + "Sep" + "Oct" + "Nov" + "Dec" + "" + "Sunday" + "Monday" + "Tuesday" + "Wednesday" + "Thursday" + "Friday" + "Saturday" + "" + "Sun" + "Mon" + "Tue" + "Wed" + "Thu" + "Fri" + "Sat" + "" + "AM" + "PM" + "" + "BC" + "AD" + "" + "" + "EEEE, MMMM D, YYYY" + "MMMM D, YYYY" + "MMM D, YYYY" + "M/D/YY" + "" + "h:MM:SS A Z" + "h:MM:SS A Z" + "h:MM:SS A" + "h:MM A" + "" + "GyMdkHmsSEDFwWahKzZ" + "z,zz9.zzz" + "$z,zz9.99|($z,zz9.99)" + "z,zz9%" + "" + "." + "," + "%" + "-" + "0" + "" + "$" + "USD" + "." + "" ""; -std::unique_ptr LoadLocale() { +TEST(CXFA_XMLLocaleTest, Create) { auto span = pdfium::make_span(reinterpret_cast(const_cast(xml_data)), strlen(xml_data)); - return CXFA_XMLLocale::Create(span); -} - -} // namespace - -TEST(CXFA_XMLLocaleTest, Create) { - auto locale = LoadLocale(); + auto locale = CXFA_XMLLocale::Create(span); EXPECT_TRUE(locale != nullptr); } @@ -119,14 +99,20 @@ TEST(CXFA_XMLLocaleTest, CreateBadXML) { } TEST(CXFA_XMLLocaleTest, GetName) { - auto locale = LoadLocale(); + auto span = + pdfium::make_span(reinterpret_cast(const_cast(xml_data)), + strlen(xml_data)); + auto locale = CXFA_XMLLocale::Create(span); ASSERT_TRUE(locale != nullptr); EXPECT_EQ(L"en_US", locale->GetName()); } TEST(CXFA_XMLLocaleTest, GetNumbericSymbol) { - auto locale = LoadLocale(); + auto span = + pdfium::make_span(reinterpret_cast(const_cast(xml_data)), + strlen(xml_data)); + auto locale = CXFA_XMLLocale::Create(span); ASSERT_TRUE(locale != nullptr); EXPECT_EQ(L".", locale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal)); @@ -139,14 +125,20 @@ TEST(CXFA_XMLLocaleTest, GetNumbericSymbol) { } TEST(CXFA_XMLLocaleTest, GetDateTimeSymbols) { - auto locale = LoadLocale(); + auto span = + pdfium::make_span(reinterpret_cast(const_cast(xml_data)), + strlen(xml_data)); + auto locale = CXFA_XMLLocale::Create(span); ASSERT_TRUE(locale != nullptr); EXPECT_EQ(L"GyMdkHmsSEDFwWahKzZ", locale->GetDateTimeSymbols()); } TEST(CXFA_XMLLocaleTest, GetMonthName) { - auto locale = LoadLocale(); + auto span = + pdfium::make_span(reinterpret_cast(const_cast(xml_data)), + strlen(xml_data)); + auto locale = CXFA_XMLLocale::Create(span); ASSERT_TRUE(locale != nullptr); EXPECT_EQ(L"", locale->GetMonthName(24, false)); @@ -156,7 +148,10 @@ TEST(CXFA_XMLLocaleTest, GetMonthName) { } TEST(CXFA_XMLLocaleTest, GetDayName) { - auto locale = LoadLocale(); + auto span = + pdfium::make_span(reinterpret_cast(const_cast(xml_data)), + strlen(xml_data)); + auto locale = CXFA_XMLLocale::Create(span); ASSERT_TRUE(locale != nullptr); EXPECT_EQ(L"", locale->GetDayName(24, false)); @@ -166,7 +161,10 @@ TEST(CXFA_XMLLocaleTest, GetDayName) { } TEST(CXFA_XMLLocaleTest, GetMeridiemName) { - auto locale = LoadLocale(); + auto span = + pdfium::make_span(reinterpret_cast(const_cast(xml_data)), + strlen(xml_data)); + auto locale = CXFA_XMLLocale::Create(span); ASSERT_TRUE(locale != nullptr); EXPECT_EQ(L"AM", locale->GetMeridiemName(true)); @@ -174,7 +172,10 @@ TEST(CXFA_XMLLocaleTest, GetMeridiemName) { } TEST(CXFA_XMLLocaleTest, GetEraName) { - auto locale = LoadLocale(); + auto span = + pdfium::make_span(reinterpret_cast(const_cast(xml_data)), + strlen(xml_data)); + auto locale = CXFA_XMLLocale::Create(span); ASSERT_TRUE(locale != nullptr); EXPECT_EQ(L"AD", locale->GetEraName(true)); @@ -182,7 +183,10 @@ TEST(CXFA_XMLLocaleTest, GetEraName) { } TEST(CXFA_XMLLocaleTest, GetDatePattern) { - auto locale = LoadLocale(); + auto span = + pdfium::make_span(reinterpret_cast(const_cast(xml_data)), + strlen(xml_data)); + auto locale = CXFA_XMLLocale::Create(span); ASSERT_TRUE(locale != nullptr); EXPECT_EQ(L"M/D/YY", @@ -198,7 +202,10 @@ TEST(CXFA_XMLLocaleTest, GetDatePattern) { } TEST(CXFA_XMLLocaleTest, GetTimePattern) { - auto locale = LoadLocale(); + auto span = + pdfium::make_span(reinterpret_cast(const_cast(xml_data)), + strlen(xml_data)); + auto locale = CXFA_XMLLocale::Create(span); ASSERT_TRUE(locale != nullptr); EXPECT_EQ(L"h:MM A", @@ -214,7 +221,10 @@ TEST(CXFA_XMLLocaleTest, GetTimePattern) { } TEST(CXFA_XMLLocaleTest, GetNumPattern) { - auto locale = LoadLocale(); + auto span = + pdfium::make_span(reinterpret_cast(const_cast(xml_data)), + strlen(xml_data)); + auto locale = CXFA_XMLLocale::Create(span); ASSERT_TRUE(locale != nullptr); EXPECT_EQ(L"z,zzz,zzz,zzz,zzz,zzz%", -- cgit v1.2.3