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