xref: /aosp_15_r20/external/pdfium/xfa/fxfa/parser/cxfa_xmllocale.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2017 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker 
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker 
7*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_xmllocale.h"
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
10*3ac0a46fSAndroid Build Coastguard Worker 
11*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/cfx_read_only_span_stream.h"
12*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_codepage.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmldocument.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmlelement.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/xml/cfx_xmlparser.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/check.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_document.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_localemgr.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_nodelocale.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_timezoneprovider.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_utils.h"
22*3ac0a46fSAndroid Build Coastguard Worker 
23*3ac0a46fSAndroid Build Coastguard Worker namespace {
24*3ac0a46fSAndroid Build Coastguard Worker 
25*3ac0a46fSAndroid Build Coastguard Worker constexpr wchar_t kNumberSymbols[] = L"numberSymbols";
26*3ac0a46fSAndroid Build Coastguard Worker constexpr wchar_t kNumberSymbol[] = L"numberSymbol";
27*3ac0a46fSAndroid Build Coastguard Worker constexpr wchar_t kCurrencySymbols[] = L"currencySymbols";
28*3ac0a46fSAndroid Build Coastguard Worker constexpr wchar_t kCurrencySymbol[] = L"currencySymbol";
29*3ac0a46fSAndroid Build Coastguard Worker 
30*3ac0a46fSAndroid Build Coastguard Worker }  // namespace
31*3ac0a46fSAndroid Build Coastguard Worker 
32*3ac0a46fSAndroid Build Coastguard Worker // static
Create(cppgc::Heap * heap,pdfium::span<uint8_t> data)33*3ac0a46fSAndroid Build Coastguard Worker CXFA_XMLLocale* CXFA_XMLLocale::Create(cppgc::Heap* heap,
34*3ac0a46fSAndroid Build Coastguard Worker                                        pdfium::span<uint8_t> data) {
35*3ac0a46fSAndroid Build Coastguard Worker   auto stream = pdfium::MakeRetain<CFX_ReadOnlySpanStream>(data);
36*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLParser parser(stream);
37*3ac0a46fSAndroid Build Coastguard Worker   auto doc = parser.Parse();
38*3ac0a46fSAndroid Build Coastguard Worker   if (!doc)
39*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
40*3ac0a46fSAndroid Build Coastguard Worker 
41*3ac0a46fSAndroid Build Coastguard Worker   for (auto* child = doc->GetRoot()->GetFirstChild(); child;
42*3ac0a46fSAndroid Build Coastguard Worker        child = child->GetNextSibling()) {
43*3ac0a46fSAndroid Build Coastguard Worker     CFX_XMLElement* elem = ToXMLElement(child);
44*3ac0a46fSAndroid Build Coastguard Worker     if (elem && elem->GetName().EqualsASCII("locale")) {
45*3ac0a46fSAndroid Build Coastguard Worker       return cppgc::MakeGarbageCollected<CXFA_XMLLocale>(
46*3ac0a46fSAndroid Build Coastguard Worker           heap->GetAllocationHandle(), std::move(doc), elem);
47*3ac0a46fSAndroid Build Coastguard Worker     }
48*3ac0a46fSAndroid Build Coastguard Worker   }
49*3ac0a46fSAndroid Build Coastguard Worker   return nullptr;
50*3ac0a46fSAndroid Build Coastguard Worker }
51*3ac0a46fSAndroid Build Coastguard Worker 
CXFA_XMLLocale(std::unique_ptr<CFX_XMLDocument> doc,const CFX_XMLElement * locale)52*3ac0a46fSAndroid Build Coastguard Worker CXFA_XMLLocale::CXFA_XMLLocale(std::unique_ptr<CFX_XMLDocument> doc,
53*3ac0a46fSAndroid Build Coastguard Worker                                const CFX_XMLElement* locale)
54*3ac0a46fSAndroid Build Coastguard Worker     : xml_doc_(std::move(doc)), locale_(locale) {
55*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(xml_doc_);
56*3ac0a46fSAndroid Build Coastguard Worker   DCHECK(locale_);
57*3ac0a46fSAndroid Build Coastguard Worker }
58*3ac0a46fSAndroid Build Coastguard Worker 
59*3ac0a46fSAndroid Build Coastguard Worker CXFA_XMLLocale::~CXFA_XMLLocale() = default;
60*3ac0a46fSAndroid Build Coastguard Worker 
Trace(cppgc::Visitor * visitor) const61*3ac0a46fSAndroid Build Coastguard Worker void CXFA_XMLLocale::Trace(cppgc::Visitor* visitor) const {
62*3ac0a46fSAndroid Build Coastguard Worker   GCedLocaleIface::Trace(visitor);
63*3ac0a46fSAndroid Build Coastguard Worker }
64*3ac0a46fSAndroid Build Coastguard Worker 
GetName() const65*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetName() const {
66*3ac0a46fSAndroid Build Coastguard Worker   return locale_->GetAttribute(L"name");
67*3ac0a46fSAndroid Build Coastguard Worker }
68*3ac0a46fSAndroid Build Coastguard Worker 
GetDecimalSymbol() const69*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetDecimalSymbol() const {
70*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* patterns = locale_->GetFirstChildNamed(kNumberSymbols);
71*3ac0a46fSAndroid Build Coastguard Worker   return patterns ? GetPattern(patterns, kNumberSymbol, L"decimal")
72*3ac0a46fSAndroid Build Coastguard Worker                   : WideString();
73*3ac0a46fSAndroid Build Coastguard Worker }
74*3ac0a46fSAndroid Build Coastguard Worker 
GetGroupingSymbol() const75*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetGroupingSymbol() const {
76*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* patterns = locale_->GetFirstChildNamed(kNumberSymbols);
77*3ac0a46fSAndroid Build Coastguard Worker   return patterns ? GetPattern(patterns, kNumberSymbol, L"grouping")
78*3ac0a46fSAndroid Build Coastguard Worker                   : WideString();
79*3ac0a46fSAndroid Build Coastguard Worker }
80*3ac0a46fSAndroid Build Coastguard Worker 
GetPercentSymbol() const81*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetPercentSymbol() const {
82*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* patterns = locale_->GetFirstChildNamed(kNumberSymbols);
83*3ac0a46fSAndroid Build Coastguard Worker   return patterns ? GetPattern(patterns, kNumberSymbol, L"percent")
84*3ac0a46fSAndroid Build Coastguard Worker                   : WideString();
85*3ac0a46fSAndroid Build Coastguard Worker }
86*3ac0a46fSAndroid Build Coastguard Worker 
GetMinusSymbol() const87*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetMinusSymbol() const {
88*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* patterns = locale_->GetFirstChildNamed(kNumberSymbols);
89*3ac0a46fSAndroid Build Coastguard Worker   return patterns ? GetPattern(patterns, kNumberSymbol, L"minus")
90*3ac0a46fSAndroid Build Coastguard Worker                   : WideString();
91*3ac0a46fSAndroid Build Coastguard Worker }
92*3ac0a46fSAndroid Build Coastguard Worker 
GetCurrencySymbol() const93*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetCurrencySymbol() const {
94*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* patterns = locale_->GetFirstChildNamed(kCurrencySymbols);
95*3ac0a46fSAndroid Build Coastguard Worker   return patterns ? GetPattern(patterns, kCurrencySymbol, L"symbol")
96*3ac0a46fSAndroid Build Coastguard Worker                   : WideString();
97*3ac0a46fSAndroid Build Coastguard Worker }
98*3ac0a46fSAndroid Build Coastguard Worker 
GetDateTimeSymbols() const99*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetDateTimeSymbols() const {
100*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* symbols = locale_->GetFirstChildNamed(L"dateTimeSymbols");
101*3ac0a46fSAndroid Build Coastguard Worker   return symbols ? symbols->GetTextData() : WideString();
102*3ac0a46fSAndroid Build Coastguard Worker }
103*3ac0a46fSAndroid Build Coastguard Worker 
GetMonthName(int32_t nMonth,bool bAbbr) const104*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetMonthName(int32_t nMonth, bool bAbbr) const {
105*3ac0a46fSAndroid Build Coastguard Worker   return GetCalendarSymbol(L"month", nMonth, bAbbr);
106*3ac0a46fSAndroid Build Coastguard Worker }
107*3ac0a46fSAndroid Build Coastguard Worker 
GetDayName(int32_t nWeek,bool bAbbr) const108*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetDayName(int32_t nWeek, bool bAbbr) const {
109*3ac0a46fSAndroid Build Coastguard Worker   return GetCalendarSymbol(L"day", nWeek, bAbbr);
110*3ac0a46fSAndroid Build Coastguard Worker }
111*3ac0a46fSAndroid Build Coastguard Worker 
GetMeridiemName(bool bAM) const112*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetMeridiemName(bool bAM) const {
113*3ac0a46fSAndroid Build Coastguard Worker   return GetCalendarSymbol(L"meridiem", bAM ? 0 : 1, false);
114*3ac0a46fSAndroid Build Coastguard Worker }
115*3ac0a46fSAndroid Build Coastguard Worker 
GetTimeZoneInMinutes() const116*3ac0a46fSAndroid Build Coastguard Worker int CXFA_XMLLocale::GetTimeZoneInMinutes() const {
117*3ac0a46fSAndroid Build Coastguard Worker   return CXFA_TimeZoneProvider().GetTimeZoneInMinutes();
118*3ac0a46fSAndroid Build Coastguard Worker }
119*3ac0a46fSAndroid Build Coastguard Worker 
GetEraName(bool bAD) const120*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetEraName(bool bAD) const {
121*3ac0a46fSAndroid Build Coastguard Worker   return GetCalendarSymbol(L"era", bAD ? 1 : 0, false);
122*3ac0a46fSAndroid Build Coastguard Worker }
123*3ac0a46fSAndroid Build Coastguard Worker 
GetCalendarSymbol(WideStringView symbol,size_t index,bool bAbbr) const124*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetCalendarSymbol(WideStringView symbol,
125*3ac0a46fSAndroid Build Coastguard Worker                                              size_t index,
126*3ac0a46fSAndroid Build Coastguard Worker                                              bool bAbbr) const {
127*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* child = locale_->GetFirstChildNamed(L"calendarSymbols");
128*3ac0a46fSAndroid Build Coastguard Worker   if (!child)
129*3ac0a46fSAndroid Build Coastguard Worker     return WideString();
130*3ac0a46fSAndroid Build Coastguard Worker 
131*3ac0a46fSAndroid Build Coastguard Worker   WideString pstrSymbolNames = symbol + L"Names";
132*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* name_child = nullptr;
133*3ac0a46fSAndroid Build Coastguard Worker   for (auto* name = child->GetFirstChild(); name;
134*3ac0a46fSAndroid Build Coastguard Worker        name = name->GetNextSibling()) {
135*3ac0a46fSAndroid Build Coastguard Worker     CFX_XMLElement* elem = ToXMLElement(name);
136*3ac0a46fSAndroid Build Coastguard Worker     if (!elem || elem->GetName() != pstrSymbolNames)
137*3ac0a46fSAndroid Build Coastguard Worker       continue;
138*3ac0a46fSAndroid Build Coastguard Worker 
139*3ac0a46fSAndroid Build Coastguard Worker     WideString abbr = elem->GetAttribute(L"abbr");
140*3ac0a46fSAndroid Build Coastguard Worker     bool abbr_value = false;
141*3ac0a46fSAndroid Build Coastguard Worker     if (!abbr.IsEmpty())
142*3ac0a46fSAndroid Build Coastguard Worker       abbr_value = abbr.EqualsASCII("1");
143*3ac0a46fSAndroid Build Coastguard Worker     if (abbr_value != bAbbr)
144*3ac0a46fSAndroid Build Coastguard Worker       continue;
145*3ac0a46fSAndroid Build Coastguard Worker 
146*3ac0a46fSAndroid Build Coastguard Worker     name_child = elem;
147*3ac0a46fSAndroid Build Coastguard Worker     break;
148*3ac0a46fSAndroid Build Coastguard Worker   }
149*3ac0a46fSAndroid Build Coastguard Worker   if (!name_child)
150*3ac0a46fSAndroid Build Coastguard Worker     return WideString();
151*3ac0a46fSAndroid Build Coastguard Worker 
152*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* sym_element = name_child->GetNthChildNamed(symbol, index);
153*3ac0a46fSAndroid Build Coastguard Worker   return sym_element ? sym_element->GetTextData() : WideString();
154*3ac0a46fSAndroid Build Coastguard Worker }
155*3ac0a46fSAndroid Build Coastguard Worker 
GetDatePattern(DateTimeSubcategory eType) const156*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetDatePattern(DateTimeSubcategory eType) const {
157*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* patterns = locale_->GetFirstChildNamed(L"datePatterns");
158*3ac0a46fSAndroid Build Coastguard Worker   if (!patterns)
159*3ac0a46fSAndroid Build Coastguard Worker     return WideString();
160*3ac0a46fSAndroid Build Coastguard Worker 
161*3ac0a46fSAndroid Build Coastguard Worker   WideString wsName;
162*3ac0a46fSAndroid Build Coastguard Worker   switch (eType) {
163*3ac0a46fSAndroid Build Coastguard Worker     case DateTimeSubcategory::kShort:
164*3ac0a46fSAndroid Build Coastguard Worker       wsName = L"short";
165*3ac0a46fSAndroid Build Coastguard Worker       break;
166*3ac0a46fSAndroid Build Coastguard Worker     case DateTimeSubcategory::kDefault:
167*3ac0a46fSAndroid Build Coastguard Worker     case DateTimeSubcategory::kMedium:
168*3ac0a46fSAndroid Build Coastguard Worker       wsName = L"med";
169*3ac0a46fSAndroid Build Coastguard Worker       break;
170*3ac0a46fSAndroid Build Coastguard Worker     case DateTimeSubcategory::kFull:
171*3ac0a46fSAndroid Build Coastguard Worker       wsName = L"full";
172*3ac0a46fSAndroid Build Coastguard Worker       break;
173*3ac0a46fSAndroid Build Coastguard Worker     case DateTimeSubcategory::kLong:
174*3ac0a46fSAndroid Build Coastguard Worker       wsName = L"long";
175*3ac0a46fSAndroid Build Coastguard Worker       break;
176*3ac0a46fSAndroid Build Coastguard Worker   }
177*3ac0a46fSAndroid Build Coastguard Worker   return GetPattern(patterns, L"datePattern", wsName.AsStringView());
178*3ac0a46fSAndroid Build Coastguard Worker }
179*3ac0a46fSAndroid Build Coastguard Worker 
GetTimePattern(DateTimeSubcategory eType) const180*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetTimePattern(DateTimeSubcategory eType) const {
181*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* patterns = locale_->GetFirstChildNamed(L"timePatterns");
182*3ac0a46fSAndroid Build Coastguard Worker   if (!patterns)
183*3ac0a46fSAndroid Build Coastguard Worker     return WideString();
184*3ac0a46fSAndroid Build Coastguard Worker 
185*3ac0a46fSAndroid Build Coastguard Worker   WideString wsName;
186*3ac0a46fSAndroid Build Coastguard Worker   switch (eType) {
187*3ac0a46fSAndroid Build Coastguard Worker     case DateTimeSubcategory::kShort:
188*3ac0a46fSAndroid Build Coastguard Worker       wsName = L"short";
189*3ac0a46fSAndroid Build Coastguard Worker       break;
190*3ac0a46fSAndroid Build Coastguard Worker     case DateTimeSubcategory::kDefault:
191*3ac0a46fSAndroid Build Coastguard Worker     case DateTimeSubcategory::kMedium:
192*3ac0a46fSAndroid Build Coastguard Worker       wsName = L"med";
193*3ac0a46fSAndroid Build Coastguard Worker       break;
194*3ac0a46fSAndroid Build Coastguard Worker     case DateTimeSubcategory::kFull:
195*3ac0a46fSAndroid Build Coastguard Worker       wsName = L"full";
196*3ac0a46fSAndroid Build Coastguard Worker       break;
197*3ac0a46fSAndroid Build Coastguard Worker     case DateTimeSubcategory::kLong:
198*3ac0a46fSAndroid Build Coastguard Worker       wsName = L"long";
199*3ac0a46fSAndroid Build Coastguard Worker       break;
200*3ac0a46fSAndroid Build Coastguard Worker   }
201*3ac0a46fSAndroid Build Coastguard Worker   return GetPattern(patterns, L"timePattern", wsName.AsStringView());
202*3ac0a46fSAndroid Build Coastguard Worker }
203*3ac0a46fSAndroid Build Coastguard Worker 
GetNumPattern(NumSubcategory eType) const204*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetNumPattern(NumSubcategory eType) const {
205*3ac0a46fSAndroid Build Coastguard Worker   CFX_XMLElement* patterns = locale_->GetFirstChildNamed(L"numberPatterns");
206*3ac0a46fSAndroid Build Coastguard Worker   return patterns ? XFA_PatternToString(eType) : WideString();
207*3ac0a46fSAndroid Build Coastguard Worker }
208*3ac0a46fSAndroid Build Coastguard Worker 
GetPattern(CFX_XMLElement * patterns,WideStringView bsTag,WideStringView wsName) const209*3ac0a46fSAndroid Build Coastguard Worker WideString CXFA_XMLLocale::GetPattern(CFX_XMLElement* patterns,
210*3ac0a46fSAndroid Build Coastguard Worker                                       WideStringView bsTag,
211*3ac0a46fSAndroid Build Coastguard Worker                                       WideStringView wsName) const {
212*3ac0a46fSAndroid Build Coastguard Worker   for (auto* child = patterns->GetFirstChild(); child;
213*3ac0a46fSAndroid Build Coastguard Worker        child = child->GetNextSibling()) {
214*3ac0a46fSAndroid Build Coastguard Worker     CFX_XMLElement* pattern = ToXMLElement(child);
215*3ac0a46fSAndroid Build Coastguard Worker     if (pattern && pattern->GetName() == bsTag &&
216*3ac0a46fSAndroid Build Coastguard Worker         pattern->GetAttribute(L"name") == wsName) {
217*3ac0a46fSAndroid Build Coastguard Worker       return pattern->GetTextData();
218*3ac0a46fSAndroid Build Coastguard Worker     }
219*3ac0a46fSAndroid Build Coastguard Worker   }
220*3ac0a46fSAndroid Build Coastguard Worker   return WideString();
221*3ac0a46fSAndroid Build Coastguard Worker }
222