1 // Copyright 2014 PDFium Authors. All rights reserved.
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 <algorithm>
8
9 #include "core/include/fxcrt/fx_xml.h"
10 #include "xfa/src/fgas/src/fgas_base.h"
11 #include "fx_localeimp.h"
12
13 #define FX_LOCALECATEGORY_DateHash 0xbde9abde
14 #define FX_LOCALECATEGORY_TimeHash 0x2d71b00f
15 #define FX_LOCALECATEGORY_DateTimeHash 0x158c72ed
16 #define FX_LOCALECATEGORY_NumHash 0x0b4ff870
17 #define FX_LOCALECATEGORY_TextHash 0x2d08af85
18 #define FX_LOCALECATEGORY_ZeroHash 0x568cb500
19 #define FX_LOCALECATEGORY_NullHash 0x052931bb
20 typedef struct _FX_LOCALESUBCATEGORYINFO {
21 uint32_t uHash;
22 const FX_WCHAR* pName;
23 int32_t eSubCategory;
24 } FX_LOCALESUBCATEGORYINFO, *FX_LPLOCALESUBCATEGORYINFO;
25 typedef FX_LOCALESUBCATEGORYINFO const* FX_LPCLOCALESUBCATEGORYINFO;
26 const static FX_LOCALESUBCATEGORYINFO g_FXLocaleDateTimeSubCatData[] = {
27 {0x14da2125, L"default", FX_LOCALEDATETIMESUBCATEGORY_Default},
28 {0x9041d4b0, L"short", FX_LOCALEDATETIMESUBCATEGORY_Short},
29 {0xa084a381, L"medium", FX_LOCALEDATETIMESUBCATEGORY_Medium},
30 {0xcdce56b3, L"full", FX_LOCALEDATETIMESUBCATEGORY_Full},
31 {0xf6b4afb0, L"long", FX_LOCALEDATETIMESUBCATEGORY_Long},
32 };
33 const static int32_t g_iFXLocaleDateTimeSubCatCount =
34 sizeof(g_FXLocaleDateTimeSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO);
35 const static FX_LOCALESUBCATEGORYINFO g_FXLocaleNumSubCatData[] = {
36 {0x46f95531, L"percent", FX_LOCALENUMPATTERN_Percent},
37 {0x4c4e8acb, L"currency", FX_LOCALENUMPATTERN_Currency},
38 {0x54034c2f, L"decimal", FX_LOCALENUMPATTERN_Decimal},
39 {0x7568e6ae, L"integer", FX_LOCALENUMPATTERN_Integer},
40 };
41 const static int32_t g_iFXLocaleNumSubCatCount =
42 sizeof(g_FXLocaleNumSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO);
43 typedef struct _FX_LOCALETIMEZONEINFO {
44 FX_DWORD uHash;
45 int16_t iHour;
46 int16_t iMinute;
47 } FX_LOCALETIMEZONEINFO, *FX_LPLOCALETIMEZONEINFO;
48 typedef FX_LOCALETIMEZONEINFO const* FX_LPCLOCALETIMEZONEINFO;
49 const static FX_LOCALETIMEZONEINFO g_FXLocaleTimeZoneData[] = {
50 {FXBSTR_ID(0, 'C', 'D', 'T'), -5, 0}, {FXBSTR_ID(0, 'C', 'S', 'T'), -6, 0},
51 {FXBSTR_ID(0, 'E', 'D', 'T'), -4, 0}, {FXBSTR_ID(0, 'E', 'S', 'T'), -5, 0},
52 {FXBSTR_ID(0, 'M', 'D', 'T'), -6, 0}, {FXBSTR_ID(0, 'M', 'S', 'T'), -7, 0},
53 {FXBSTR_ID(0, 'P', 'D', 'T'), -7, 0}, {FXBSTR_ID(0, 'P', 'S', 'T'), -8, 0},
54 };
55 const static int32_t g_iFXLocaleTimeZoneCount =
56 sizeof(g_FXLocaleTimeZoneData) / sizeof(FX_LOCALETIMEZONEINFO);
57 const static CFX_WideStringC gs_wsTextSymbols = FX_WSTRC(L"AXO09");
58 const static CFX_WideStringC gs_wsTimeSymbols = FX_WSTRC(L"hHkKMSFAzZ");
59 const static CFX_WideStringC gs_wsDateSymbols = FX_WSTRC(L"DJMEeGgYwW");
60 const static CFX_WideStringC gs_wsConstChars = FX_WSTRC(L",-:/. ");
FX_Local_Find(const CFX_WideStringC & wsSymbols,FX_WCHAR ch,FX_STRSIZE nStart=0)61 static FX_STRSIZE FX_Local_Find(const CFX_WideStringC& wsSymbols,
62 FX_WCHAR ch,
63 FX_STRSIZE nStart = 0) {
64 FX_STRSIZE nLength = wsSymbols.GetLength();
65 if (nLength < 1 || nStart > nLength) {
66 return -1;
67 }
68 const FX_WCHAR* lpsz =
69 (const FX_WCHAR*)FXSYS_wcschr(wsSymbols.GetPtr() + nStart, ch);
70 return (lpsz == NULL) ? -1 : (FX_STRSIZE)(lpsz - wsSymbols.GetPtr());
71 }
72 static const FX_WCHAR* const gs_LocalNumberSymbols[] = {
73 L"decimal", L"grouping", L"percent", L"minus",
74 L"zero", L"currencySymbol", L"currencyName",
75 };
Create(CXML_Element * pLocaleData)76 IFX_Locale* IFX_Locale::Create(CXML_Element* pLocaleData) {
77 return new CFX_Locale(pLocaleData);
78 }
CFX_Locale(CXML_Element * pLocaleData)79 CFX_Locale::CFX_Locale(CXML_Element* pLocaleData) {
80 m_pElement = pLocaleData;
81 }
~CFX_Locale()82 CFX_Locale::~CFX_Locale() {}
GetName()83 CFX_WideString CFX_Locale::GetName() {
84 return CFX_WideString();
85 }
FX_GetXMLContent(const CFX_ByteStringC & bsSpace,CXML_Element * pxmlElement,const CFX_ByteStringC & bsTag,const CFX_WideStringC & wsName)86 static CFX_WideString FX_GetXMLContent(const CFX_ByteStringC& bsSpace,
87 CXML_Element* pxmlElement,
88 const CFX_ByteStringC& bsTag,
89 const CFX_WideStringC& wsName) {
90 CXML_Element* pDatePattern = NULL;
91 int32_t nCount = pxmlElement->CountElements(bsSpace, bsTag);
92 int32_t i = 0;
93 for (; i < nCount; i++) {
94 pDatePattern = pxmlElement->GetElement(bsSpace, bsTag, i);
95 if (pDatePattern->GetAttrValue("name") == wsName) {
96 break;
97 }
98 }
99 if (i < nCount && pDatePattern) {
100 return pDatePattern->GetContent(0);
101 }
102 return L"";
103 }
GetNumbericSymbol(FX_LOCALENUMSYMBOL eType,CFX_WideString & wsNumSymbol) const104 void CFX_Locale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType,
105 CFX_WideString& wsNumSymbol) const {
106 if (!m_pElement) {
107 return;
108 }
109 CFX_ByteString bsSpace;
110 CFX_WideString wsName = gs_LocalNumberSymbols[eType];
111 CXML_Element* pNumberSymbols =
112 m_pElement->GetElement(bsSpace, "numberSymbols");
113 if (!pNumberSymbols) {
114 return;
115 }
116 wsNumSymbol =
117 FX_GetXMLContent(bsSpace, pNumberSymbols, "numberSymbol", wsName);
118 }
GetDateTimeSymbols(CFX_WideString & wsDtSymbol) const119 void CFX_Locale::GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const {
120 if (!m_pElement) {
121 return;
122 }
123 CFX_ByteString bsSpace;
124 CXML_Element* pNumberSymbols =
125 m_pElement->GetElement(bsSpace, "dateTimeSymbols");
126 if (!pNumberSymbols) {
127 return;
128 }
129 wsDtSymbol = pNumberSymbols->GetContent(0);
130 }
FX_GetCalendarSymbol(CXML_Element * pXmlElement,const CFX_ByteString & symbol_type,int32_t index,FX_BOOL bAbbr,CFX_WideString & wsName)131 static void FX_GetCalendarSymbol(CXML_Element* pXmlElement,
132 const CFX_ByteString& symbol_type,
133 int32_t index,
134 FX_BOOL bAbbr,
135 CFX_WideString& wsName) {
136 CFX_ByteString bsSpace;
137 CFX_ByteString pstrSymbolNames = symbol_type + "Names";
138 CXML_Element* pChild = pXmlElement->GetElement(bsSpace, "calendarSymbols");
139 if (!pChild) {
140 return;
141 }
142 CXML_Element* pSymbolNames = pChild->GetElement(bsSpace, pstrSymbolNames);
143 if (!pSymbolNames) {
144 return;
145 }
146 if (pSymbolNames->GetAttrInteger("abbr") != bAbbr) {
147 pSymbolNames = pChild->GetElement(bsSpace, pstrSymbolNames, 1);
148 }
149 if (pSymbolNames && pSymbolNames->GetAttrInteger("abbr") == bAbbr) {
150 CXML_Element* pSymbolName =
151 pSymbolNames->GetElement(bsSpace, symbol_type, index);
152 if (pSymbolName) {
153 wsName = pSymbolName->GetContent(0);
154 }
155 }
156 }
GetMonthName(int32_t nMonth,CFX_WideString & wsMonthName,FX_BOOL bAbbr) const157 void CFX_Locale::GetMonthName(int32_t nMonth,
158 CFX_WideString& wsMonthName,
159 FX_BOOL bAbbr) const {
160 if (!m_pElement) {
161 return;
162 }
163 FX_GetCalendarSymbol(m_pElement, "month", nMonth, bAbbr, wsMonthName);
164 }
GetDayName(int32_t nWeek,CFX_WideString & wsDayName,FX_BOOL bAbbr) const165 void CFX_Locale::GetDayName(int32_t nWeek,
166 CFX_WideString& wsDayName,
167 FX_BOOL bAbbr) const {
168 if (!m_pElement) {
169 return;
170 }
171 FX_GetCalendarSymbol(m_pElement, "day", nWeek, bAbbr, wsDayName);
172 }
GetMeridiemName(CFX_WideString & wsMeridiemName,FX_BOOL bAM) const173 void CFX_Locale::GetMeridiemName(CFX_WideString& wsMeridiemName,
174 FX_BOOL bAM) const {
175 if (!m_pElement) {
176 return;
177 }
178 FX_GetCalendarSymbol(m_pElement, "meridiem", bAM ? 0 : 1, FALSE,
179 wsMeridiemName);
180 }
FX_ParseTimeZone(const FX_WCHAR * pStr,int32_t iLen,FX_TIMEZONE & tz)181 static int32_t FX_ParseTimeZone(const FX_WCHAR* pStr,
182 int32_t iLen,
183 FX_TIMEZONE& tz) {
184 tz.tzHour = 0;
185 tz.tzMinute = 0;
186 if (iLen < 0) {
187 return 0;
188 }
189 int32_t iStart = 1;
190 int32_t iEnd = iStart + 2;
191 while (iStart < iLen && iStart < iEnd) {
192 tz.tzHour = tz.tzHour * 10 + pStr[iStart++] - '0';
193 }
194 if (iStart < iLen && pStr[iStart] == ':') {
195 iStart++;
196 }
197 iEnd = iStart + 2;
198 while (iStart < iLen && iStart < iEnd) {
199 tz.tzMinute = tz.tzMinute * 10 + pStr[iStart++] - '0';
200 }
201 if (pStr[0] == '-') {
202 tz.tzHour = -tz.tzHour;
203 }
204 return iStart;
205 }
GetTimeZone(FX_TIMEZONE & tz) const206 void CFX_Locale::GetTimeZone(FX_TIMEZONE& tz) const {
207 tz.tzHour = 0;
208 tz.tzMinute = 0;
209 if (!m_pElement) {
210 return;
211 }
212 CXML_Element* pxmlTimeZone = m_pElement->GetElement("", "timeZone");
213 if (pxmlTimeZone) {
214 CFX_WideString wsTimeZone = pxmlTimeZone->GetContent(0);
215 FX_ParseTimeZone(wsTimeZone, wsTimeZone.GetLength(), tz);
216 }
217 }
GetEraName(CFX_WideString & wsEraName,FX_BOOL bAD) const218 void CFX_Locale::GetEraName(CFX_WideString& wsEraName, FX_BOOL bAD) const {
219 if (!m_pElement) {
220 return;
221 }
222 FX_GetCalendarSymbol(m_pElement, "era", bAD ? 0 : 1, FALSE, wsEraName);
223 }
FX_GetPattern(CXML_Element * pXmlElement,const CFX_ByteString & bsCategory,const CFX_WideString & wsSubCategory,CFX_WideString & wsPattern)224 static void FX_GetPattern(CXML_Element* pXmlElement,
225 const CFX_ByteString& bsCategory,
226 const CFX_WideString& wsSubCategory,
227 CFX_WideString& wsPattern) {
228 CFX_ByteString bsSpace;
229 CXML_Element* pDatePatterns =
230 pXmlElement->GetElement(bsSpace, bsCategory + "s");
231 if (!pDatePatterns) {
232 return;
233 }
234 wsPattern =
235 FX_GetXMLContent(bsSpace, pDatePatterns, bsCategory, wsSubCategory);
236 }
FX_GetDateTimePattern(CXML_Element * pXmlElement,const CFX_ByteString & bsCategory,FX_LOCALEDATETIMESUBCATEGORY eType,CFX_WideString & wsPattern)237 static void FX_GetDateTimePattern(CXML_Element* pXmlElement,
238 const CFX_ByteString& bsCategory,
239 FX_LOCALEDATETIMESUBCATEGORY eType,
240 CFX_WideString& wsPattern) {
241 CFX_WideString wsType = g_FXLocaleDateTimeSubCatData[eType].pName;
242 FX_GetPattern(pXmlElement, bsCategory, wsType, wsPattern);
243 }
GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType,CFX_WideString & wsPattern) const244 void CFX_Locale::GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
245 CFX_WideString& wsPattern) const {
246 if (!m_pElement) {
247 return;
248 }
249 FX_GetDateTimePattern(m_pElement, "datePattern", eType, wsPattern);
250 }
GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType,CFX_WideString & wsPattern) const251 void CFX_Locale::GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
252 CFX_WideString& wsPattern) const {
253 if (!m_pElement) {
254 return;
255 }
256 FX_GetDateTimePattern(m_pElement, "timePattern", eType, wsPattern);
257 }
GetNumPattern(FX_LOCALENUMSUBCATEGORY eType,CFX_WideString & wsPattern) const258 void CFX_Locale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType,
259 CFX_WideString& wsPattern) const {
260 CFX_WideString wsType = g_FXLocaleNumSubCatData[eType].pName;
261 FX_GetPattern(m_pElement, "numberPattern", wsType, wsPattern);
262 }
FX_IsDigit(FX_WCHAR c)263 static FX_BOOL FX_IsDigit(FX_WCHAR c) {
264 return c >= '0' && c <= '9';
265 }
FX_IsAlpha(FX_WCHAR c)266 static FX_BOOL FX_IsAlpha(FX_WCHAR c) {
267 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
268 }
FX_IsSpace(FX_WCHAR c)269 static FX_BOOL FX_IsSpace(FX_WCHAR c) {
270 return (c == 0x20) || (c == 0x0d) || (c == 0x0a) || (c == 0x09);
271 }
272 static const FX_FLOAT gs_fraction_scales[] = {
273 0.1f, 0.01f, 0.001f, 0.0001f,
274 0.00001f, 0.000001f, 0.0000001f, 0.00000001f,
275 0.000000001f, 0.0000000001f, 0.00000000001f};
276 static const int32_t gs_fraction_count =
277 sizeof(gs_fraction_scales) / sizeof(FX_FLOAT);
278 class CFX_LCNumeric {
279 public:
280 CFX_LCNumeric();
281 CFX_LCNumeric(int64_t integral,
282 FX_DWORD fractional = 0,
283 int32_t exponent = 0);
284 CFX_LCNumeric(FX_FLOAT dbRetValue);
285 CFX_LCNumeric(double dbvalue);
286 CFX_LCNumeric(CFX_WideString& wsNumeric);
287
288 FX_FLOAT GetFloat() const;
289 double GetDouble() const;
290 CFX_WideString ToString() const;
291 CFX_WideString ToString(int32_t nTreading, FX_BOOL bTrimTailZeros) const;
292 int64_t m_Integral;
293 FX_DWORD m_Fractional;
294 #ifdef FX_NUM_DOUBLE
295 CFX_WideString m_wsValue;
296 #endif
297 int32_t m_Exponent;
298 };
FX_WStringToNumeric(const CFX_WideString & wsValue,CFX_LCNumeric & lcnum)299 static FX_BOOL FX_WStringToNumeric(const CFX_WideString& wsValue,
300 CFX_LCNumeric& lcnum) {
301 int64_t* pIntegral = &lcnum.m_Integral;
302 FX_DWORD* pFractional = &lcnum.m_Fractional;
303 int32_t* pExponent = &lcnum.m_Exponent;
304 *pIntegral = 0;
305 *pFractional = 0;
306 *pExponent = 0;
307 #ifdef FX_NUM_DOUBLE
308 lcnum.m_wsValue.Empty();
309 #endif
310 if (wsValue.IsEmpty()) {
311 return FALSE;
312 }
313 const int32_t nIntegralMaxLen = 17;
314 int32_t cc = 0;
315 FX_BOOL bNegative = FALSE, bExpSign = FALSE;
316 const FX_WCHAR* str = (const FX_WCHAR*)wsValue;
317 int32_t len = wsValue.GetLength();
318 while (cc < len && FX_IsSpace(str[cc])) {
319 cc++;
320 }
321 if (cc >= len) {
322 return FALSE;
323 }
324 if (str[cc] == '+') {
325 cc++;
326 } else if (str[cc] == '-') {
327 bNegative = TRUE;
328 cc++;
329 }
330 int32_t nIntegralLen = 0;
331 while (cc < len) {
332 if (str[cc] == '.') {
333 break;
334 }
335 if (!FX_IsDigit(str[cc])) {
336 if ((str[cc] == 'E' || str[cc] == 'e')) {
337 break;
338 } else {
339 return FALSE;
340 }
341 }
342 if (nIntegralLen < nIntegralMaxLen) {
343 *pIntegral = *pIntegral * 10 + str[cc] - '0';
344 nIntegralLen++;
345 }
346 cc++;
347 }
348 *pIntegral = bNegative ? -*pIntegral : *pIntegral;
349 if (cc < len && str[cc] == '.') {
350 int scale = 0;
351 double fraction = 0.0;
352 cc++;
353 while (cc < len) {
354 if (scale >= gs_fraction_count) {
355 while (cc < len) {
356 if (!FX_IsDigit(str[cc])) {
357 break;
358 }
359 cc++;
360 }
361 }
362 if (!FX_IsDigit(str[cc])) {
363 if ((str[cc] == 'E' || str[cc] == 'e')) {
364 break;
365 } else {
366 return FALSE;
367 }
368 }
369 fraction += gs_fraction_scales[scale] * (str[cc] - '0');
370 scale++;
371 cc++;
372 }
373 *pFractional = (FX_DWORD)(fraction * 4294967296.0);
374 }
375 if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) {
376 cc++;
377 if (cc < len) {
378 if (str[cc] == '+') {
379 cc++;
380 } else if (str[cc] == '-') {
381 bExpSign = TRUE;
382 cc++;
383 }
384 }
385 while (cc < len) {
386 if (FX_IsDigit(str[cc])) {
387 return FALSE;
388 }
389 *pExponent = *pExponent * 10 + str[cc] - '0';
390 cc++;
391 }
392 *pExponent = bExpSign ? -*pExponent : *pExponent;
393 }
394 #ifdef FX_NUM_DOUBLE
395 else {
396 lcnum.m_wsValue = wsValue;
397 }
398 #endif
399 return TRUE;
400 }
CFX_LCNumeric()401 CFX_LCNumeric::CFX_LCNumeric() {
402 m_Integral = 0;
403 m_Fractional = 0;
404 m_Exponent = 0;
405 }
CFX_LCNumeric(int64_t integral,FX_DWORD fractional,int32_t exponent)406 CFX_LCNumeric::CFX_LCNumeric(int64_t integral,
407 FX_DWORD fractional,
408 int32_t exponent) {
409 m_Integral = integral;
410 m_Fractional = fractional;
411 m_Exponent = exponent;
412 }
CFX_LCNumeric(FX_FLOAT dbRetValue)413 CFX_LCNumeric::CFX_LCNumeric(FX_FLOAT dbRetValue) {
414 m_Integral = (int64_t)dbRetValue;
415 m_Fractional = (FX_DWORD)(((dbRetValue > 0) ? (dbRetValue - m_Integral)
416 : (m_Integral - dbRetValue)) *
417 4294967296);
418 m_Exponent = 0;
419 }
CFX_LCNumeric(double dbvalue)420 CFX_LCNumeric::CFX_LCNumeric(double dbvalue) {
421 m_Integral = (int64_t)dbvalue;
422 m_Fractional = (FX_DWORD)(
423 ((dbvalue > 0) ? (dbvalue - m_Integral) : (m_Integral - dbvalue)) *
424 4294967296);
425 m_Exponent = 0;
426 }
CFX_LCNumeric(CFX_WideString & wsNumeric)427 CFX_LCNumeric::CFX_LCNumeric(CFX_WideString& wsNumeric) {
428 FX_WStringToNumeric(wsNumeric, *this);
429 }
GetFloat() const430 FX_FLOAT CFX_LCNumeric::GetFloat() const {
431 FX_FLOAT dbRetValue = m_Fractional / 4294967296.0f;
432 dbRetValue = m_Integral + (m_Integral >= 0 ? dbRetValue : -dbRetValue);
433 if (m_Exponent != 0) {
434 dbRetValue *= FXSYS_pow(10, (FX_FLOAT)m_Exponent);
435 }
436 return dbRetValue;
437 }
GetDouble() const438 double CFX_LCNumeric::GetDouble() const {
439 double value = m_Fractional / 4294967296.0;
440 value = m_Integral + (m_Integral >= 0 ? value : -value);
441 if (m_Exponent != 0) {
442 value *= FXSYS_pow(10, (FX_FLOAT)m_Exponent);
443 }
444 return value;
445 }
ToString() const446 CFX_WideString CFX_LCNumeric::ToString() const {
447 return ToString(8, TRUE);
448 }
ToString(int32_t nTreading,FX_BOOL bTrimTailZeros) const449 CFX_WideString CFX_LCNumeric::ToString(int32_t nTreading,
450 FX_BOOL bTrimTailZeros) const {
451 #ifdef FX_NUM_DOUBLE
452 CFX_WideString wsResult;
453 if (!m_wsValue.IsEmpty()) {
454 const int32_t nIntegralMaxLen = 17;
455 int32_t cc = 0;
456 FX_BOOL bNegative = FALSE, bExpSign = FALSE;
457 const FX_WCHAR* str = (const FX_WCHAR*)m_wsValue;
458 int32_t len = m_wsValue.GetLength();
459 while (cc < len && FX_IsSpace(str[cc])) {
460 cc++;
461 }
462 if (cc >= len) {
463 return wsResult;
464 }
465 if (str[cc] == '+') {
466 cc++;
467 } else if (str[cc] == '-') {
468 bNegative = TRUE;
469 cc++;
470 }
471 int32_t nIntegralLen = 0;
472 while (cc < len) {
473 if (str[cc] == '.') {
474 break;
475 }
476 if (!FX_IsDigit(str[cc])) {
477 if ((str[cc] == 'E' || str[cc] == 'e')) {
478 break;
479 } else {
480 return wsResult;
481 }
482 }
483 if (nIntegralLen < nIntegralMaxLen) {
484 *pIntegral = *pIntegral * 10 + str[cc] - '0';
485 nIntegralLen++;
486 }
487 cc++;
488 }
489 *pIntegral = bNegative ? -*pIntegral : *pIntegral;
490 if (cc < len && str[cc] == '.') {
491 int scale = 0;
492 double fraction = 0.0;
493 cc++;
494 while (cc < len) {
495 if (scale >= gs_fraction_count) {
496 while (cc < len) {
497 if (!FX_IsDigit(str[cc])) {
498 break;
499 }
500 cc++;
501 }
502 }
503 if (!FX_IsDigit(str[cc])) {
504 if ((str[cc] == 'E' || str[cc] == 'e')) {
505 break;
506 } else {
507 return FALSE;
508 }
509 }
510 fraction += gs_fraction_scales[scale] * (str[cc] - '0');
511 scale++;
512 cc++;
513 }
514 *pFractional = (FX_DWORD)(fraction * 4294967296.0);
515 }
516 }
517 double dbValeu = GetDouble();
518 int64_t iInte = (int64_t)dbValeu;
519 wsResult.Format(L"%l", (int64_t)iInte);
520 if (m_Fractional) {
521 CFX_WideString wsFormat;
522 wsFormat.Format(L"%%.%dG", nTreading);
523 double dblMantissa = (dbValeu > 0) ? (dbValeu - iInte) : (iInte - dbValeu);
524 CFX_WideString wsFrac;
525 wsFrac.Format((const FX_WCHAR*)wsFormat, dblMantissa);
526 wsResult +=
527 CFX_WideStringC((const FX_WCHAR*)wsFrac + 1, wsFrac.GetLength() - 1);
528 if (bTrimTailZeros && nTreading > 0) {
529 wsResult.TrimRight(L"0");
530 wsResult.TrimRight(L".");
531 }
532 }
533 #endif
534 CFX_WideString wsFormat;
535 wsFormat.Format(L"%%.%df", nTreading);
536 CFX_WideString wsResult;
537 wsResult.Format(wsFormat.c_str(), GetDouble());
538 if (bTrimTailZeros && nTreading > 0) {
539 wsResult.TrimRight(L"0");
540 wsResult.TrimRight(L".");
541 }
542 return wsResult;
543 }
Create(IFX_LocaleMgr * pLocaleMgr,FX_BOOL bUseLCID)544 IFX_FormatString* IFX_FormatString::Create(IFX_LocaleMgr* pLocaleMgr,
545 FX_BOOL bUseLCID) {
546 if (!pLocaleMgr) {
547 return NULL;
548 }
549 return new CFX_FormatString(pLocaleMgr, bUseLCID);
550 }
CFX_FormatString(IFX_LocaleMgr * pLocaleMgr,FX_BOOL bUseLCID)551 CFX_FormatString::CFX_FormatString(IFX_LocaleMgr* pLocaleMgr, FX_BOOL bUseLCID)
552 : m_pLocaleMgr(pLocaleMgr), m_bUseLCID(bUseLCID) {}
~CFX_FormatString()553 CFX_FormatString::~CFX_FormatString() {}
SplitFormatString(const CFX_WideString & wsFormatString,CFX_WideStringArray & wsPatterns)554 void CFX_FormatString::SplitFormatString(const CFX_WideString& wsFormatString,
555 CFX_WideStringArray& wsPatterns) {
556 int32_t iStrLen = wsFormatString.GetLength();
557 const FX_WCHAR* pStr = (const FX_WCHAR*)wsFormatString;
558 const FX_WCHAR* pToken = pStr;
559 const FX_WCHAR* pEnd = pStr + iStrLen;
560 FX_BOOL iQuote = FALSE;
561 while (TRUE) {
562 if (pStr >= pEnd) {
563 CFX_WideString sub(pToken, pStr - pToken);
564 wsPatterns.Add(sub);
565 return;
566 } else if (*pStr == '\'') {
567 iQuote = !iQuote;
568 } else if (*pStr == L'|' && !iQuote) {
569 CFX_WideString sub(pToken, pStr - pToken);
570 wsPatterns.Add(sub);
571 pToken = pStr + 1;
572 }
573 pStr++;
574 }
575 }
FX_GetLiteralText(const FX_WCHAR * pStrPattern,int32_t & iPattern,int32_t iLenPattern)576 static CFX_WideString FX_GetLiteralText(const FX_WCHAR* pStrPattern,
577 int32_t& iPattern,
578 int32_t iLenPattern) {
579 CFX_WideString wsOutput;
580 if (pStrPattern[iPattern] != '\'') {
581 return wsOutput;
582 }
583 iPattern++;
584 int32_t iQuote = 1;
585 while (iPattern < iLenPattern) {
586 if (pStrPattern[iPattern] == '\'') {
587 iQuote++;
588 if ((iPattern + 1 >= iLenPattern) ||
589 ((pStrPattern[iPattern + 1] != '\'') && (iQuote % 2 == 0))) {
590 break;
591 } else {
592 iQuote++;
593 }
594 iPattern++;
595 } else if (pStrPattern[iPattern] == '\\' && (iPattern + 1 < iLenPattern) &&
596 pStrPattern[iPattern + 1] == 'u') {
597 int32_t iKeyValue = 0;
598 iPattern += 2;
599 int32_t i = 0;
600 while (iPattern < iLenPattern && i++ < 4) {
601 FX_WCHAR ch = pStrPattern[iPattern++];
602 if ((ch >= '0' && ch <= '9')) {
603 iKeyValue = iKeyValue * 16 + ch - '0';
604 } else if ((ch >= 'a' && ch <= 'f')) {
605 iKeyValue = iKeyValue * 16 + ch - 'a' + 10;
606 } else if ((ch >= 'A' && ch <= 'F')) {
607 iKeyValue = iKeyValue * 16 + ch - 'A' + 10;
608 }
609 }
610 if (iKeyValue != 0) {
611 wsOutput += (FX_WCHAR)(iKeyValue & 0x0000FFFF);
612 }
613 continue;
614 }
615 wsOutput += pStrPattern[iPattern++];
616 }
617 return wsOutput;
618 }
FX_GetLiteralTextReverse(const FX_WCHAR * pStrPattern,int32_t & iPattern)619 static CFX_WideString FX_GetLiteralTextReverse(const FX_WCHAR* pStrPattern,
620 int32_t& iPattern) {
621 CFX_WideString wsOutput;
622 if (pStrPattern[iPattern] != '\'') {
623 return wsOutput;
624 }
625 iPattern--;
626 int32_t iQuote = 1;
627 while (iPattern >= 0) {
628 if (pStrPattern[iPattern] == '\'') {
629 iQuote++;
630 if (iPattern - 1 >= 0 ||
631 ((pStrPattern[iPattern - 1] != '\'') && (iQuote % 2 == 0))) {
632 break;
633 } else {
634 iQuote++;
635 }
636 iPattern--;
637 } else if (pStrPattern[iPattern] == '\\' &&
638 pStrPattern[iPattern + 1] == 'u') {
639 iPattern--;
640 int32_t iKeyValue = 0;
641 int32_t iLen = wsOutput.GetLength();
642 int32_t i = 1;
643 for (; i < iLen && i < 5; i++) {
644 FX_WCHAR ch = wsOutput[i];
645 if ((ch >= '0' && ch <= '9')) {
646 iKeyValue = iKeyValue * 16 + ch - '0';
647 } else if ((ch >= 'a' && ch <= 'f')) {
648 iKeyValue = iKeyValue * 16 + ch - 'a' + 10;
649 } else if ((ch >= 'A' && ch <= 'F')) {
650 iKeyValue = iKeyValue * 16 + ch - 'A' + 10;
651 }
652 }
653 if (iKeyValue != 0) {
654 wsOutput.Delete(0, i);
655 wsOutput = (FX_WCHAR)(iKeyValue & 0x0000FFFF) + wsOutput;
656 }
657 continue;
658 }
659 wsOutput = pStrPattern[iPattern--] + wsOutput;
660 }
661 return wsOutput;
662 }
GetCategory(const CFX_WideString & wsPattern)663 FX_LOCALECATEGORY CFX_FormatString::GetCategory(
664 const CFX_WideString& wsPattern) {
665 FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown;
666 int32_t ccf = 0;
667 int32_t iLenf = wsPattern.GetLength();
668 const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern;
669 FX_BOOL bBraceOpen = FALSE;
670 while (ccf < iLenf) {
671 if (pStr[ccf] == '\'') {
672 FX_GetLiteralText(pStr, ccf, iLenf);
673 } else if (!bBraceOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
674 CFX_WideString wsCategory(pStr[ccf]);
675 ccf++;
676 while (TRUE) {
677 if (ccf == iLenf) {
678 return eCategory;
679 }
680 if (pStr[ccf] == '.' || pStr[ccf] == '(') {
681 break;
682 }
683 if (pStr[ccf] == '{') {
684 bBraceOpen = TRUE;
685 break;
686 }
687 wsCategory += pStr[ccf];
688 ccf++;
689 }
690 FX_DWORD dwHash =
691 FX_HashCode_String_GetW(wsCategory, wsCategory.GetLength());
692 if (dwHash == FX_LOCALECATEGORY_DateHash) {
693 if (eCategory == FX_LOCALECATEGORY_Time) {
694 return FX_LOCALECATEGORY_DateTime;
695 }
696 eCategory = FX_LOCALECATEGORY_Date;
697 } else if (dwHash == FX_LOCALECATEGORY_TimeHash) {
698 if (eCategory == FX_LOCALECATEGORY_Date) {
699 return FX_LOCALECATEGORY_DateTime;
700 }
701 eCategory = FX_LOCALECATEGORY_Time;
702 } else if (dwHash == FX_LOCALECATEGORY_DateTimeHash) {
703 return FX_LOCALECATEGORY_DateTime;
704 } else if (dwHash == FX_LOCALECATEGORY_TextHash) {
705 return FX_LOCALECATEGORY_Text;
706 } else if (dwHash == FX_LOCALECATEGORY_NumHash) {
707 return FX_LOCALECATEGORY_Num;
708 } else if (dwHash == FX_LOCALECATEGORY_ZeroHash) {
709 return FX_LOCALECATEGORY_Zero;
710 } else if (dwHash == FX_LOCALECATEGORY_NullHash) {
711 return FX_LOCALECATEGORY_Null;
712 }
713 } else if (pStr[ccf] == '}') {
714 bBraceOpen = FALSE;
715 }
716 ccf++;
717 }
718 return eCategory;
719 }
FX_WStringToLCID(const FX_WCHAR * pstrLCID)720 static FX_WORD FX_WStringToLCID(const FX_WCHAR* pstrLCID) {
721 if (!pstrLCID) {
722 return 0;
723 }
724 wchar_t* pEnd;
725 return (FX_WORD)wcstol((wchar_t*)pstrLCID, &pEnd, 16);
726 }
GetLCID(const CFX_WideString & wsPattern)727 FX_WORD CFX_FormatString::GetLCID(const CFX_WideString& wsPattern) {
728 return FX_WStringToLCID(GetLocaleName(wsPattern));
729 }
GetLocaleName(const CFX_WideString & wsPattern)730 CFX_WideString CFX_FormatString::GetLocaleName(
731 const CFX_WideString& wsPattern) {
732 int32_t ccf = 0;
733 int32_t iLenf = wsPattern.GetLength();
734 const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern;
735 while (ccf < iLenf) {
736 if (pStr[ccf] == '\'') {
737 FX_GetLiteralText(pStr, ccf, iLenf);
738 } else if (pStr[ccf] == '(') {
739 ccf++;
740 CFX_WideString wsLCID;
741 while (ccf < iLenf && pStr[ccf] != ')') {
742 wsLCID += pStr[ccf++];
743 }
744 return wsLCID;
745 }
746 ccf++;
747 }
748 return CFX_WideString();
749 }
GetTextFormat(const CFX_WideString & wsPattern,const CFX_WideStringC & wsCategory,CFX_WideString & wsPurgePattern)750 IFX_Locale* CFX_FormatString::GetTextFormat(const CFX_WideString& wsPattern,
751 const CFX_WideStringC& wsCategory,
752 CFX_WideString& wsPurgePattern) {
753 IFX_Locale* pLocale = NULL;
754 int32_t ccf = 0;
755 int32_t iLenf = wsPattern.GetLength();
756 const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern;
757 FX_BOOL bBrackOpen = FALSE;
758 while (ccf < iLenf) {
759 if (pStr[ccf] == '\'') {
760 int32_t iCurChar = ccf;
761 FX_GetLiteralText(pStr, ccf, iLenf);
762 wsPurgePattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1);
763 } else if (!bBrackOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
764 CFX_WideString wsSearchCategory(pStr[ccf]);
765 ccf++;
766 while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' &&
767 pStr[ccf] != '(') {
768 wsSearchCategory += pStr[ccf];
769 ccf++;
770 }
771 if (wsSearchCategory != wsCategory) {
772 continue;
773 }
774 while (ccf < iLenf) {
775 if (pStr[ccf] == '(') {
776 ccf++;
777 CFX_WideString wsLCID;
778 while (ccf < iLenf && pStr[ccf] != ')') {
779 wsLCID += pStr[ccf++];
780 }
781 pLocale = GetPatternLocale(wsLCID);
782 } else if (pStr[ccf] == '{') {
783 bBrackOpen = TRUE;
784 break;
785 }
786 ccf++;
787 }
788 } else if (pStr[ccf] != '}') {
789 wsPurgePattern += pStr[ccf];
790 }
791 ccf++;
792 }
793 if (!bBrackOpen) {
794 wsPurgePattern = wsPattern;
795 }
796 if (!pLocale) {
797 pLocale = m_pLocaleMgr->GetDefLocale();
798 }
799 return pLocale;
800 }
801 #define FX_NUMSTYLE_Percent 0x01
802 #define FX_NUMSTYLE_Exponent 0x02
803 #define FX_NUMSTYLE_DotVorv 0x04
GetNumericFormat(const CFX_WideString & wsPattern,int32_t & iDotIndex,FX_DWORD & dwStyle,CFX_WideString & wsPurgePattern)804 IFX_Locale* CFX_FormatString::GetNumericFormat(const CFX_WideString& wsPattern,
805 int32_t& iDotIndex,
806 FX_DWORD& dwStyle,
807 CFX_WideString& wsPurgePattern) {
808 dwStyle = 0;
809 IFX_Locale* pLocale = NULL;
810 int32_t ccf = 0;
811 int32_t iLenf = wsPattern.GetLength();
812 const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern;
813 FX_BOOL bFindDot = FALSE;
814 FX_BOOL bBrackOpen = FALSE;
815 while (ccf < iLenf) {
816 if (pStr[ccf] == '\'') {
817 int32_t iCurChar = ccf;
818 FX_GetLiteralText(pStr, ccf, iLenf);
819 wsPurgePattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1);
820 } else if (!bBrackOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
821 CFX_WideString wsCategory(pStr[ccf]);
822 ccf++;
823 while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' &&
824 pStr[ccf] != '(') {
825 wsCategory += pStr[ccf];
826 ccf++;
827 }
828 if (wsCategory != FX_WSTRC(L"num")) {
829 bBrackOpen = TRUE;
830 ccf = 0;
831 continue;
832 }
833 while (ccf < iLenf) {
834 if (pStr[ccf] == '(') {
835 ccf++;
836 CFX_WideString wsLCID;
837 while (ccf < iLenf && pStr[ccf] != ')') {
838 wsLCID += pStr[ccf++];
839 }
840 pLocale = GetPatternLocale(wsLCID);
841 } else if (pStr[ccf] == '{') {
842 bBrackOpen = TRUE;
843 break;
844 } else if (pStr[ccf] == '.') {
845 CFX_WideString wsSubCategory;
846 ccf++;
847 while (ccf < iLenf && pStr[ccf] != '(' && pStr[ccf] != '{') {
848 wsSubCategory += pStr[ccf++];
849 }
850 FX_DWORD dwSubHash =
851 FX_HashCode_String_GetW(wsSubCategory, wsSubCategory.GetLength());
852 FX_LOCALENUMSUBCATEGORY eSubCategory = FX_LOCALENUMPATTERN_Decimal;
853 for (int32_t i = 0; i < g_iFXLocaleNumSubCatCount; i++) {
854 if (g_FXLocaleNumSubCatData[i].uHash == dwSubHash) {
855 eSubCategory = (FX_LOCALENUMSUBCATEGORY)g_FXLocaleNumSubCatData[i]
856 .eSubCategory;
857 break;
858 }
859 }
860 wsSubCategory.Empty();
861 if (!pLocale) {
862 pLocale = m_pLocaleMgr->GetDefLocale();
863 }
864 FXSYS_assert(pLocale != NULL);
865 pLocale->GetNumPattern(eSubCategory, wsSubCategory);
866 iDotIndex = wsSubCategory.Find('.');
867 if (iDotIndex > 0) {
868 iDotIndex += wsPurgePattern.GetLength();
869 bFindDot = TRUE;
870 dwStyle |= FX_NUMSTYLE_DotVorv;
871 }
872 wsPurgePattern += wsSubCategory;
873 if (eSubCategory == FX_LOCALENUMPATTERN_Percent) {
874 dwStyle |= FX_NUMSTYLE_Percent;
875 }
876 continue;
877 }
878 ccf++;
879 }
880 } else if (pStr[ccf] == 'E') {
881 dwStyle |= FX_NUMSTYLE_Exponent;
882 wsPurgePattern += pStr[ccf];
883 } else if (pStr[ccf] == '%') {
884 dwStyle |= FX_NUMSTYLE_Percent;
885 wsPurgePattern += pStr[ccf];
886 } else if (pStr[ccf] != '}') {
887 wsPurgePattern += pStr[ccf];
888 }
889 if (!bFindDot) {
890 if (pStr[ccf] == '.' || pStr[ccf] == 'V' || pStr[ccf] == 'v') {
891 bFindDot = TRUE;
892 iDotIndex = wsPurgePattern.GetLength() - 1;
893 dwStyle |= FX_NUMSTYLE_DotVorv;
894 }
895 }
896 ccf++;
897 }
898 if (!bFindDot) {
899 iDotIndex = wsPurgePattern.GetLength();
900 }
901 if (!pLocale) {
902 pLocale = m_pLocaleMgr->GetDefLocale();
903 }
904 return pLocale;
905 }
FX_GetNumericDotIndex(const CFX_WideString & wsNum,const CFX_WideString & wsDotSymbol,int32_t & iDotIndex)906 static FX_BOOL FX_GetNumericDotIndex(const CFX_WideString& wsNum,
907 const CFX_WideString& wsDotSymbol,
908 int32_t& iDotIndex) {
909 int32_t ccf = 0;
910 int32_t iLenf = wsNum.GetLength();
911 const FX_WCHAR* pStr = (const FX_WCHAR*)wsNum;
912 int32_t iLenDot = wsDotSymbol.GetLength();
913 while (ccf < iLenf) {
914 if (pStr[ccf] == '\'') {
915 FX_GetLiteralText(pStr, ccf, iLenf);
916 } else if (ccf + iLenDot <= iLenf &&
917 !FXSYS_wcsncmp(pStr + ccf, (const FX_WCHAR*)wsDotSymbol,
918 iLenDot)) {
919 iDotIndex = ccf;
920 return TRUE;
921 }
922 ccf++;
923 }
924 iDotIndex = wsNum.Find('.');
925 if (iDotIndex < 0) {
926 iDotIndex = iLenf;
927 return FALSE;
928 }
929 return TRUE;
930 }
ParseText(const CFX_WideString & wsSrcText,const CFX_WideString & wsPattern,CFX_WideString & wsValue)931 FX_BOOL CFX_FormatString::ParseText(const CFX_WideString& wsSrcText,
932 const CFX_WideString& wsPattern,
933 CFX_WideString& wsValue) {
934 wsValue.Empty();
935 if (wsSrcText.IsEmpty() || wsPattern.IsEmpty()) {
936 return FALSE;
937 }
938 CFX_WideString wsTextFormat;
939 GetTextFormat(wsPattern, FX_WSTRC(L"text"), wsTextFormat);
940 if (wsTextFormat.IsEmpty()) {
941 return FALSE;
942 }
943 int32_t iText = 0, iPattern = 0;
944 const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText;
945 int32_t iLenText = wsSrcText.GetLength();
946 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
947 int32_t iLenPattern = wsTextFormat.GetLength();
948 while (iPattern < iLenPattern && iText < iLenText) {
949 switch (pStrPattern[iPattern]) {
950 case '\'': {
951 CFX_WideString wsLiteral =
952 FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
953 int32_t iLiteralLen = wsLiteral.GetLength();
954 if (iText + iLiteralLen > iLenText ||
955 FXSYS_wcsncmp(pStrText + iText, (const FX_WCHAR*)wsLiteral,
956 iLiteralLen)) {
957 wsValue = wsSrcText;
958 return FALSE;
959 }
960 iText += iLiteralLen;
961 iPattern++;
962 break;
963 }
964 case 'A':
965 if (FX_IsAlpha(pStrText[iText])) {
966 wsValue += pStrText[iText];
967 iText++;
968 }
969 iPattern++;
970 break;
971 case 'X':
972 wsValue += pStrText[iText];
973 iText++;
974 iPattern++;
975 break;
976 case 'O':
977 case '0':
978 if (FX_IsDigit(pStrText[iText]) || FX_IsAlpha(pStrText[iText])) {
979 wsValue += pStrText[iText];
980 iText++;
981 }
982 iPattern++;
983 break;
984 case '9':
985 if (FX_IsDigit(pStrText[iText])) {
986 wsValue += pStrText[iText];
987 iText++;
988 }
989 iPattern++;
990 break;
991 default:
992 if (pStrPattern[iPattern] != pStrText[iText]) {
993 wsValue = wsSrcText;
994 return FALSE;
995 }
996 iPattern++;
997 iText++;
998 break;
999 }
1000 }
1001 return iPattern == iLenPattern && iText == iLenText;
1002 }
ParseNum(const CFX_WideString & wsSrcNum,const CFX_WideString & wsPattern,FX_FLOAT & fValue)1003 FX_BOOL CFX_FormatString::ParseNum(const CFX_WideString& wsSrcNum,
1004 const CFX_WideString& wsPattern,
1005 FX_FLOAT& fValue) {
1006 fValue = 0.0f;
1007 if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) {
1008 return FALSE;
1009 }
1010 int32_t dot_index_f = -1;
1011 FX_DWORD dwFormatStyle = 0;
1012 CFX_WideString wsNumFormat;
1013 IFX_Locale* pLocale =
1014 GetNumericFormat(wsPattern, dot_index_f, dwFormatStyle, wsNumFormat);
1015 if (!pLocale || wsNumFormat.IsEmpty()) {
1016 return FALSE;
1017 }
1018 int32_t iExponent = 0;
1019 CFX_WideString wsDotSymbol;
1020 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
1021 CFX_WideString wsGroupSymbol;
1022 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
1023 int32_t iGroupLen = wsGroupSymbol.GetLength();
1024 CFX_WideString wsMinus;
1025 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinus);
1026 int32_t iMinusLen = wsMinus.GetLength();
1027 int cc = 0, ccf = 0;
1028 const FX_WCHAR* str = (const FX_WCHAR*)wsSrcNum;
1029 int len = wsSrcNum.GetLength();
1030 const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat;
1031 int lenf = wsNumFormat.GetLength();
1032 double dbRetValue = 0;
1033 double coeff = 1;
1034 FX_BOOL bHavePercentSymbol = FALSE;
1035 FX_BOOL bNeg = FALSE;
1036 FX_BOOL bReverseParse = FALSE;
1037 int32_t dot_index = 0;
1038 if (!FX_GetNumericDotIndex(wsSrcNum, wsDotSymbol, dot_index) &&
1039 (dwFormatStyle & FX_NUMSTYLE_DotVorv)) {
1040 bReverseParse = TRUE;
1041 }
1042 bReverseParse = FALSE;
1043 if (bReverseParse) {
1044 ccf = lenf - 1;
1045 cc = len - 1;
1046 while (ccf > dot_index_f && cc >= 0) {
1047 switch (strf[ccf]) {
1048 case '\'': {
1049 CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf);
1050 int32_t iLiteralLen = wsLiteral.GetLength();
1051 cc -= iLiteralLen - 1;
1052 if (cc < 0 || FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral,
1053 iLiteralLen)) {
1054 return FALSE;
1055 }
1056 cc--;
1057 ccf--;
1058 break;
1059 }
1060 case '9':
1061 if (!FX_IsDigit(str[cc])) {
1062 return FALSE;
1063 }
1064 dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1;
1065 coeff *= 0.1;
1066 cc--;
1067 ccf--;
1068 break;
1069 case 'z':
1070 if (cc >= 0) {
1071 dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1;
1072 coeff *= 0.1;
1073 cc--;
1074 }
1075 ccf--;
1076 break;
1077 case 'Z':
1078 if (str[cc] != ' ') {
1079 dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1;
1080 coeff *= 0.1;
1081 }
1082 cc--;
1083 ccf--;
1084 break;
1085 case 'S':
1086 if (str[cc] == '+' || str[cc] == ' ') {
1087 cc--;
1088 } else {
1089 cc -= iMinusLen - 1;
1090 if (cc < 0 ||
1091 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
1092 return FALSE;
1093 }
1094 cc--;
1095 bNeg = TRUE;
1096 }
1097 ccf--;
1098 break;
1099 case 's':
1100 if (str[cc] == '+') {
1101 cc--;
1102 } else {
1103 cc -= iMinusLen - 1;
1104 if (cc < 0 ||
1105 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
1106 return FALSE;
1107 }
1108 cc--;
1109 bNeg = TRUE;
1110 }
1111 ccf--;
1112 break;
1113 case 'E': {
1114 if (cc >= dot_index) {
1115 return FALSE;
1116 }
1117 FX_BOOL bExpSign = FALSE;
1118 while (cc >= 0) {
1119 if (str[cc] == 'E' || str[cc] == 'e') {
1120 break;
1121 }
1122 if (FX_IsDigit(str[cc])) {
1123 iExponent = iExponent + (str[cc] - '0') * 10;
1124 cc--;
1125 continue;
1126 } else if (str[cc] == '+') {
1127 cc--;
1128 continue;
1129 } else if (cc - iMinusLen + 1 > 0 &&
1130 !FXSYS_wcsncmp(str + (cc - iMinusLen + 1),
1131 (const FX_WCHAR*)wsMinus, iMinusLen)) {
1132 bExpSign = TRUE;
1133 cc -= iMinusLen;
1134 } else {
1135 return FALSE;
1136 }
1137 }
1138 cc--;
1139 iExponent = bExpSign ? -iExponent : iExponent;
1140 ccf--;
1141 } break;
1142 case '$': {
1143 CFX_WideString wsSymbol;
1144 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol,
1145 wsSymbol);
1146 int32_t iSymbolLen = wsSymbol.GetLength();
1147 cc -= iSymbolLen - 1;
1148 if (cc < 0 ||
1149 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) {
1150 return FALSE;
1151 }
1152 cc--;
1153 ccf--;
1154 } break;
1155 case 'r':
1156 if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
1157 if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
1158 bNeg = TRUE;
1159 cc -= 2;
1160 }
1161 ccf -= 2;
1162 } else {
1163 ccf--;
1164 }
1165 break;
1166 case 'R':
1167 if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
1168 if (str[cc] == ' ') {
1169 cc++;
1170 } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
1171 bNeg = TRUE;
1172 cc -= 2;
1173 }
1174 ccf -= 2;
1175 } else {
1176 ccf--;
1177 }
1178 break;
1179 case 'b':
1180 if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
1181 if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
1182 bNeg = TRUE;
1183 cc -= 2;
1184 }
1185 ccf -= 2;
1186 } else {
1187 ccf--;
1188 }
1189 break;
1190 case 'B':
1191 if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
1192 if (str[cc] == ' ') {
1193 cc++;
1194 } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
1195 bNeg = TRUE;
1196 cc -= 2;
1197 }
1198 ccf -= 2;
1199 } else {
1200 ccf--;
1201 }
1202 break;
1203 case '.':
1204 case 'V':
1205 case 'v':
1206 return FALSE;
1207 case '%': {
1208 CFX_WideString wsSymbol;
1209 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
1210 int32_t iSysmbolLen = wsSymbol.GetLength();
1211 cc -= iSysmbolLen - 1;
1212 if (cc < 0 ||
1213 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSysmbolLen)) {
1214 return FALSE;
1215 }
1216 cc--;
1217 ccf--;
1218 bHavePercentSymbol = TRUE;
1219 } break;
1220 case '8':
1221 while (ccf < lenf && strf[ccf] == '8') {
1222 ccf++;
1223 }
1224 while (cc < len && FX_IsDigit(str[cc])) {
1225 dbRetValue = (str[cc] - '0') * coeff + dbRetValue;
1226 coeff *= 0.1;
1227 cc++;
1228 }
1229 break;
1230 case ',': {
1231 if (cc >= 0) {
1232 cc -= iGroupLen - 1;
1233 if (cc >= 0 &&
1234 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol,
1235 iGroupLen) == 0) {
1236 cc--;
1237 } else {
1238 cc += iGroupLen - 1;
1239 }
1240 }
1241 ccf--;
1242 } break;
1243 case '(':
1244 if (str[cc] == L'(') {
1245 bNeg = TRUE;
1246 } else if (str[cc] != L' ') {
1247 return FALSE;
1248 }
1249 cc--;
1250 ccf--;
1251 break;
1252 case ')':
1253 if (str[cc] == L')') {
1254 bNeg = TRUE;
1255 } else if (str[cc] != L' ') {
1256 return FALSE;
1257 }
1258 cc--;
1259 ccf--;
1260 break;
1261 default:
1262 if (strf[ccf] != str[cc]) {
1263 return FALSE;
1264 }
1265 cc--;
1266 ccf--;
1267 }
1268 }
1269 dot_index = cc + 1;
1270 }
1271 ccf = dot_index_f - 1;
1272 cc = dot_index - 1;
1273 coeff = 1;
1274 while (ccf >= 0 && cc >= 0) {
1275 switch (strf[ccf]) {
1276 case '\'': {
1277 CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf);
1278 int32_t iLiteralLen = wsLiteral.GetLength();
1279 cc -= iLiteralLen - 1;
1280 if (cc < 0 ||
1281 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) {
1282 return FALSE;
1283 }
1284 cc--;
1285 ccf--;
1286 break;
1287 }
1288 case '9':
1289 if (!FX_IsDigit(str[cc])) {
1290 return FALSE;
1291 }
1292 dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
1293 coeff *= 10;
1294 cc--;
1295 ccf--;
1296 break;
1297 case 'z':
1298 if (FX_IsDigit(str[cc])) {
1299 dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
1300 coeff *= 10;
1301 cc--;
1302 }
1303 ccf--;
1304 break;
1305 case 'Z':
1306 if (str[cc] != ' ') {
1307 if (FX_IsDigit(str[cc])) {
1308 dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
1309 coeff *= 10;
1310 cc--;
1311 }
1312 } else {
1313 cc--;
1314 }
1315 ccf--;
1316 break;
1317 case 'S':
1318 if (str[cc] == '+' || str[cc] == ' ') {
1319 cc--;
1320 } else {
1321 cc -= iMinusLen - 1;
1322 if (cc < 0 ||
1323 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
1324 return FALSE;
1325 }
1326 cc--;
1327 bNeg = TRUE;
1328 }
1329 ccf--;
1330 break;
1331 case 's':
1332 if (str[cc] == '+') {
1333 cc--;
1334 } else {
1335 cc -= iMinusLen - 1;
1336 if (cc < 0 ||
1337 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
1338 return FALSE;
1339 }
1340 cc--;
1341 bNeg = TRUE;
1342 }
1343 ccf--;
1344 break;
1345 case 'E': {
1346 if (cc >= dot_index) {
1347 return FALSE;
1348 }
1349 FX_BOOL bExpSign = FALSE;
1350 while (cc >= 0) {
1351 if (str[cc] == 'E' || str[cc] == 'e') {
1352 break;
1353 }
1354 if (FX_IsDigit(str[cc])) {
1355 iExponent = iExponent + (str[cc] - '0') * 10;
1356 cc--;
1357 continue;
1358 } else if (str[cc] == '+') {
1359 cc--;
1360 continue;
1361 } else if (cc - iMinusLen + 1 > 0 &&
1362 !FXSYS_wcsncmp(str + (cc - iMinusLen + 1),
1363 (const FX_WCHAR*)wsMinus, iMinusLen)) {
1364 bExpSign = TRUE;
1365 cc -= iMinusLen;
1366 } else {
1367 return FALSE;
1368 }
1369 }
1370 cc--;
1371 iExponent = bExpSign ? -iExponent : iExponent;
1372 ccf--;
1373 } break;
1374 case '$': {
1375 CFX_WideString wsSymbol;
1376 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
1377 int32_t iSymbolLen = wsSymbol.GetLength();
1378 cc -= iSymbolLen - 1;
1379 if (cc < 0 ||
1380 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) {
1381 return FALSE;
1382 }
1383 cc--;
1384 ccf--;
1385 } break;
1386 case 'r':
1387 if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
1388 if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
1389 bNeg = TRUE;
1390 cc -= 2;
1391 }
1392 ccf -= 2;
1393 } else {
1394 ccf--;
1395 }
1396 break;
1397 case 'R':
1398 if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
1399 if (str[cc] == ' ') {
1400 cc++;
1401 } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
1402 bNeg = TRUE;
1403 cc -= 2;
1404 }
1405 ccf -= 2;
1406 } else {
1407 ccf--;
1408 }
1409 break;
1410 case 'b':
1411 if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
1412 if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
1413 bNeg = TRUE;
1414 cc -= 2;
1415 }
1416 ccf -= 2;
1417 } else {
1418 ccf--;
1419 }
1420 break;
1421 case 'B':
1422 if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
1423 if (str[cc] == ' ') {
1424 cc++;
1425 } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
1426 bNeg = TRUE;
1427 cc -= 2;
1428 }
1429 ccf -= 2;
1430 } else {
1431 ccf--;
1432 }
1433 break;
1434 case '.':
1435 case 'V':
1436 case 'v':
1437 return FALSE;
1438 case '%': {
1439 CFX_WideString wsSymbol;
1440 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
1441 int32_t iSysmbolLen = wsSymbol.GetLength();
1442 cc -= iSysmbolLen - 1;
1443 if (cc < 0 ||
1444 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSysmbolLen)) {
1445 return FALSE;
1446 }
1447 cc--;
1448 ccf--;
1449 bHavePercentSymbol = TRUE;
1450 } break;
1451 case '8':
1452 return FALSE;
1453 case ',': {
1454 if (cc >= 0) {
1455 cc -= iGroupLen - 1;
1456 if (cc >= 0 &&
1457 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol,
1458 iGroupLen) == 0) {
1459 cc--;
1460 } else {
1461 cc += iGroupLen - 1;
1462 }
1463 }
1464 ccf--;
1465 } break;
1466 case '(':
1467 if (str[cc] == L'(') {
1468 bNeg = TRUE;
1469 } else if (str[cc] != L' ') {
1470 return FALSE;
1471 }
1472 cc--;
1473 ccf--;
1474 break;
1475 case ')':
1476 if (str[cc] == L')') {
1477 bNeg = TRUE;
1478 } else if (str[cc] != L' ') {
1479 return FALSE;
1480 }
1481 cc--;
1482 ccf--;
1483 break;
1484 default:
1485 if (strf[ccf] != str[cc]) {
1486 return FALSE;
1487 }
1488 cc--;
1489 ccf--;
1490 }
1491 }
1492 if (cc >= 0) {
1493 return FALSE;
1494 }
1495 if (!bReverseParse) {
1496 ccf = dot_index_f + 1;
1497 cc = (dot_index == len) ? len : dot_index + 1;
1498 coeff = 0.1;
1499 while (cc < len && ccf < lenf) {
1500 switch (strf[ccf]) {
1501 case '\'': {
1502 CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
1503 int32_t iLiteralLen = wsLiteral.GetLength();
1504 if (cc + iLiteralLen > len ||
1505 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral,
1506 iLiteralLen)) {
1507 return FALSE;
1508 }
1509 cc += iLiteralLen;
1510 ccf++;
1511 break;
1512 }
1513 case '9':
1514 if (!FX_IsDigit(str[cc])) {
1515 return FALSE;
1516 }
1517 {
1518 dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
1519 coeff *= 0.1;
1520 }
1521 cc++;
1522 ccf++;
1523 break;
1524 case 'z':
1525 if (FX_IsDigit(str[cc])) {
1526 dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
1527 coeff *= 0.1;
1528 cc++;
1529 }
1530 ccf++;
1531 break;
1532 case 'Z':
1533 if (str[cc] != ' ') {
1534 if (FX_IsDigit(str[cc])) {
1535 dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
1536 coeff *= 0.1;
1537 cc++;
1538 }
1539 } else {
1540 cc++;
1541 }
1542 ccf++;
1543 break;
1544 case 'S':
1545 if (str[cc] == '+' || str[cc] == ' ') {
1546 cc++;
1547 } else {
1548 if (cc + iMinusLen > len ||
1549 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
1550 return FALSE;
1551 }
1552 bNeg = TRUE;
1553 cc += iMinusLen;
1554 }
1555 ccf++;
1556 break;
1557 case 's':
1558 if (str[cc] == '+') {
1559 cc++;
1560 } else {
1561 if (cc + iMinusLen > len ||
1562 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
1563 return FALSE;
1564 }
1565 bNeg = TRUE;
1566 cc += iMinusLen;
1567 }
1568 ccf++;
1569 break;
1570 case 'E': {
1571 if (cc >= len || (str[cc] != 'E' && str[cc] != 'e')) {
1572 return FALSE;
1573 }
1574 FX_BOOL bExpSign = FALSE;
1575 cc++;
1576 if (cc < len) {
1577 if (str[cc] == '+') {
1578 cc++;
1579 } else if (str[cc] == '-') {
1580 bExpSign = TRUE;
1581 cc++;
1582 }
1583 }
1584 while (cc < len) {
1585 if (!FX_IsDigit(str[cc])) {
1586 break;
1587 }
1588 iExponent = iExponent * 10 + str[cc] - '0';
1589 cc++;
1590 }
1591 iExponent = bExpSign ? -iExponent : iExponent;
1592 ccf++;
1593 } break;
1594 case '$': {
1595 CFX_WideString wsSymbol;
1596 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol,
1597 wsSymbol);
1598 int32_t iSymbolLen = wsSymbol.GetLength();
1599 if (cc + iSymbolLen > len ||
1600 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) {
1601 return FALSE;
1602 }
1603 cc += iSymbolLen;
1604 ccf++;
1605 } break;
1606 case 'c':
1607 if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
1608 if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
1609 bNeg = TRUE;
1610 cc += 2;
1611 }
1612 ccf += 2;
1613 }
1614 break;
1615 case 'C':
1616 if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
1617 if (str[cc] == ' ') {
1618 cc++;
1619 } else if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
1620 bNeg = TRUE;
1621 cc += 2;
1622 }
1623 ccf += 2;
1624 }
1625 break;
1626 case 'd':
1627 if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
1628 if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
1629 bNeg = TRUE;
1630 cc += 2;
1631 }
1632 ccf += 2;
1633 }
1634 break;
1635 case 'D':
1636 if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
1637 if (str[cc] == ' ') {
1638 cc++;
1639 } else if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
1640 bNeg = TRUE;
1641 cc += 2;
1642 }
1643 ccf += 2;
1644 }
1645 break;
1646 case '.':
1647 case 'V':
1648 case 'v':
1649 return FALSE;
1650 case '%': {
1651 CFX_WideString wsSymbol;
1652 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
1653 int32_t iSysmbolLen = wsSymbol.GetLength();
1654 if (cc + iSysmbolLen <= len &&
1655 !FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol,
1656 iSysmbolLen)) {
1657 cc += iSysmbolLen;
1658 }
1659 ccf++;
1660 bHavePercentSymbol = TRUE;
1661 } break;
1662 case '8': {
1663 while (ccf < lenf && strf[ccf] == '8') {
1664 ccf++;
1665 }
1666 while (cc < len && FX_IsDigit(str[cc])) {
1667 dbRetValue = (str[cc] - '0') * coeff + dbRetValue;
1668 coeff *= 0.1;
1669 cc++;
1670 }
1671 } break;
1672 case ',': {
1673 if (cc + iGroupLen <= len &&
1674 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol,
1675 iGroupLen) == 0) {
1676 cc += iGroupLen;
1677 }
1678 ccf++;
1679 } break;
1680 case '(':
1681 if (str[cc] == L'(') {
1682 bNeg = TRUE;
1683 } else if (str[cc] != L' ') {
1684 return FALSE;
1685 }
1686 cc++;
1687 ccf++;
1688 break;
1689 case ')':
1690 if (str[cc] == L')') {
1691 bNeg = TRUE;
1692 } else if (str[cc] != L' ') {
1693 return FALSE;
1694 }
1695 cc++;
1696 ccf++;
1697 break;
1698 default:
1699 if (strf[ccf] != str[cc]) {
1700 return FALSE;
1701 }
1702 cc++;
1703 ccf++;
1704 }
1705 }
1706 if (cc != len) {
1707 return FALSE;
1708 }
1709 }
1710 if (iExponent) {
1711 dbRetValue *= FXSYS_pow(10, (FX_FLOAT)iExponent);
1712 }
1713 if (bHavePercentSymbol) {
1714 dbRetValue /= 100.0;
1715 }
1716 if (bNeg) {
1717 dbRetValue = -dbRetValue;
1718 }
1719 fValue = (FX_FLOAT)dbRetValue;
1720 return TRUE;
1721 }
FX_ParseNumString(const CFX_WideString & wsNum,CFX_WideString & wsResult)1722 void FX_ParseNumString(const CFX_WideString& wsNum, CFX_WideString& wsResult) {
1723 int32_t iCount = wsNum.GetLength();
1724 const FX_WCHAR* pStr = (const FX_WCHAR*)wsNum;
1725 FX_WCHAR* pDst = wsResult.GetBuffer(iCount);
1726 int32_t nIndex = 0;
1727 FX_BOOL bMinus = FALSE;
1728 int32_t i = 0;
1729 for (i = 0; i < iCount; i++) {
1730 FX_WCHAR wc = pStr[i];
1731 if (wc == '.') {
1732 break;
1733 }
1734 if ((wc == L'0' || wc == L' ' || wc == '+') && nIndex == 0) {
1735 continue;
1736 }
1737 if (wc == '-') {
1738 pDst[nIndex++] = wc;
1739 bMinus = TRUE;
1740 continue;
1741 }
1742 if (wc == L'0' && nIndex == 1 && bMinus) {
1743 continue;
1744 }
1745 pDst[nIndex++] = wc;
1746 }
1747 if (bMinus && nIndex == 1) {
1748 pDst[nIndex++] = '0';
1749 }
1750 if (nIndex == 0) {
1751 wsResult.ReleaseBuffer(0);
1752 pDst = wsResult.GetBuffer(iCount + 1);
1753 pDst[nIndex++] = '0';
1754 }
1755 int32_t j = 0;
1756 for (j = iCount - 1; j > i; j--) {
1757 FX_WCHAR wc = pStr[j];
1758 if (wc != L'0' && wc != L' ') {
1759 break;
1760 }
1761 }
1762 if (j > i) {
1763 pDst[nIndex++] = '.';
1764 FXSYS_wcsncpy(pDst + nIndex, pStr + i + 1, j - i);
1765 nIndex += j - i;
1766 }
1767 wsResult.ReleaseBuffer(nIndex);
1768 }
ParseNum(const CFX_WideString & wsSrcNum,const CFX_WideString & wsPattern,CFX_WideString & wsValue)1769 FX_BOOL CFX_FormatString::ParseNum(const CFX_WideString& wsSrcNum,
1770 const CFX_WideString& wsPattern,
1771 CFX_WideString& wsValue) {
1772 wsValue.Empty();
1773 if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) {
1774 return FALSE;
1775 }
1776 int32_t dot_index_f = -1;
1777 FX_DWORD dwFormatStyle = 0;
1778 CFX_WideString wsNumFormat;
1779 IFX_Locale* pLocale =
1780 GetNumericFormat(wsPattern, dot_index_f, dwFormatStyle, wsNumFormat);
1781 if (!pLocale || wsNumFormat.IsEmpty()) {
1782 return FALSE;
1783 }
1784 int32_t iExponent = 0;
1785 CFX_WideString wsDotSymbol;
1786 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
1787 CFX_WideString wsGroupSymbol;
1788 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
1789 int32_t iGroupLen = wsGroupSymbol.GetLength();
1790 CFX_WideString wsMinus;
1791 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinus);
1792 int32_t iMinusLen = wsMinus.GetLength();
1793 int cc = 0, ccf = 0;
1794 const FX_WCHAR* str = (const FX_WCHAR*)wsSrcNum;
1795 int len = wsSrcNum.GetLength();
1796 const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat;
1797 int lenf = wsNumFormat.GetLength();
1798 FX_BOOL bHavePercentSymbol = FALSE;
1799 FX_BOOL bNeg = FALSE;
1800 FX_BOOL bReverseParse = FALSE;
1801 int32_t dot_index = 0;
1802 if (!FX_GetNumericDotIndex(wsSrcNum, wsDotSymbol, dot_index) &&
1803 (dwFormatStyle & FX_NUMSTYLE_DotVorv)) {
1804 bReverseParse = TRUE;
1805 }
1806 bReverseParse = FALSE;
1807 ccf = dot_index_f - 1;
1808 cc = dot_index - 1;
1809 while (ccf >= 0 && cc >= 0) {
1810 switch (strf[ccf]) {
1811 case '\'': {
1812 CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf);
1813 int32_t iLiteralLen = wsLiteral.GetLength();
1814 cc -= iLiteralLen - 1;
1815 if (cc < 0 ||
1816 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) {
1817 return FALSE;
1818 }
1819 cc--;
1820 ccf--;
1821 break;
1822 }
1823 case '9':
1824 if (!FX_IsDigit(str[cc])) {
1825 return FALSE;
1826 }
1827 wsValue = CFX_WideStringC(str[cc]) + wsValue;
1828 cc--;
1829 ccf--;
1830 break;
1831 case 'z':
1832 if (FX_IsDigit(str[cc])) {
1833 wsValue = CFX_WideStringC(str[cc]) + wsValue;
1834 cc--;
1835 }
1836 ccf--;
1837 break;
1838 case 'Z':
1839 if (str[cc] != ' ') {
1840 if (FX_IsDigit(str[cc])) {
1841 wsValue = CFX_WideStringC(str[cc]) + wsValue;
1842 cc--;
1843 }
1844 } else {
1845 cc--;
1846 }
1847 ccf--;
1848 break;
1849 case 'S':
1850 if (str[cc] == '+' || str[cc] == ' ') {
1851 cc--;
1852 } else {
1853 cc -= iMinusLen - 1;
1854 if (cc < 0 ||
1855 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
1856 return FALSE;
1857 }
1858 cc--;
1859 bNeg = TRUE;
1860 }
1861 ccf--;
1862 break;
1863 case 's':
1864 if (str[cc] == '+') {
1865 cc--;
1866 } else {
1867 cc -= iMinusLen - 1;
1868 if (cc < 0 ||
1869 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
1870 return FALSE;
1871 }
1872 cc--;
1873 bNeg = TRUE;
1874 }
1875 ccf--;
1876 break;
1877 case 'E': {
1878 if (cc >= dot_index) {
1879 return FALSE;
1880 }
1881 FX_BOOL bExpSign = FALSE;
1882 while (cc >= 0) {
1883 if (str[cc] == 'E' || str[cc] == 'e') {
1884 break;
1885 }
1886 if (FX_IsDigit(str[cc])) {
1887 iExponent = iExponent + (str[cc] - '0') * 10;
1888 cc--;
1889 continue;
1890 } else if (str[cc] == '+') {
1891 cc--;
1892 continue;
1893 } else if (cc - iMinusLen + 1 > 0 &&
1894 !FXSYS_wcsncmp(str + (cc - iMinusLen + 1),
1895 (const FX_WCHAR*)wsMinus, iMinusLen)) {
1896 bExpSign = TRUE;
1897 cc -= iMinusLen;
1898 } else {
1899 return FALSE;
1900 }
1901 }
1902 cc--;
1903 iExponent = bExpSign ? -iExponent : iExponent;
1904 ccf--;
1905 } break;
1906 case '$': {
1907 CFX_WideString wsSymbol;
1908 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
1909 int32_t iSymbolLen = wsSymbol.GetLength();
1910 cc -= iSymbolLen - 1;
1911 if (cc < 0 ||
1912 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) {
1913 return FALSE;
1914 }
1915 cc--;
1916 ccf--;
1917 } break;
1918 case 'r':
1919 if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
1920 if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
1921 bNeg = TRUE;
1922 cc -= 2;
1923 }
1924 ccf -= 2;
1925 } else {
1926 ccf--;
1927 }
1928 break;
1929 case 'R':
1930 if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
1931 if (str[cc] == ' ') {
1932 cc++;
1933 } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
1934 bNeg = TRUE;
1935 cc -= 2;
1936 }
1937 ccf -= 2;
1938 } else {
1939 ccf--;
1940 }
1941 break;
1942 case 'b':
1943 if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
1944 if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
1945 bNeg = TRUE;
1946 cc -= 2;
1947 }
1948 ccf -= 2;
1949 } else {
1950 ccf--;
1951 }
1952 break;
1953 case 'B':
1954 if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
1955 if (str[cc] == ' ') {
1956 cc++;
1957 } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
1958 bNeg = TRUE;
1959 cc -= 2;
1960 }
1961 ccf -= 2;
1962 } else {
1963 ccf--;
1964 }
1965 break;
1966 case '.':
1967 case 'V':
1968 case 'v':
1969 return FALSE;
1970 case '%': {
1971 CFX_WideString wsSymbol;
1972 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
1973 int32_t iSysmbolLen = wsSymbol.GetLength();
1974 cc -= iSysmbolLen - 1;
1975 if (cc < 0 ||
1976 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSysmbolLen)) {
1977 return FALSE;
1978 }
1979 cc--;
1980 ccf--;
1981 bHavePercentSymbol = TRUE;
1982 } break;
1983 case '8':
1984 return FALSE;
1985 case ',': {
1986 if (cc >= 0) {
1987 cc -= iGroupLen - 1;
1988 if (cc >= 0 &&
1989 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol,
1990 iGroupLen) == 0) {
1991 cc--;
1992 } else {
1993 cc += iGroupLen - 1;
1994 }
1995 }
1996 ccf--;
1997 } break;
1998 case '(':
1999 if (str[cc] == L'(') {
2000 bNeg = TRUE;
2001 } else if (str[cc] != L' ') {
2002 return FALSE;
2003 }
2004 cc--;
2005 ccf--;
2006 break;
2007 case ')':
2008 if (str[cc] == L')') {
2009 bNeg = TRUE;
2010 } else if (str[cc] != L' ') {
2011 return FALSE;
2012 }
2013 cc--;
2014 ccf--;
2015 break;
2016 default:
2017 if (strf[ccf] != str[cc]) {
2018 return FALSE;
2019 }
2020 cc--;
2021 ccf--;
2022 }
2023 }
2024 if (cc >= 0) {
2025 if (str[cc] == '-') {
2026 bNeg = TRUE;
2027 cc--;
2028 }
2029 if (cc >= 0) {
2030 return FALSE;
2031 }
2032 }
2033 if (dot_index < len && (dwFormatStyle & FX_NUMSTYLE_DotVorv)) {
2034 wsValue += '.';
2035 }
2036 if (!bReverseParse) {
2037 ccf = dot_index_f + 1;
2038 cc = (dot_index == len) ? len : dot_index + 1;
2039 while (cc < len && ccf < lenf) {
2040 switch (strf[ccf]) {
2041 case '\'': {
2042 CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
2043 int32_t iLiteralLen = wsLiteral.GetLength();
2044 if (cc + iLiteralLen > len ||
2045 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral,
2046 iLiteralLen)) {
2047 return FALSE;
2048 }
2049 cc += iLiteralLen;
2050 ccf++;
2051 break;
2052 }
2053 case '9':
2054 if (!FX_IsDigit(str[cc])) {
2055 return FALSE;
2056 }
2057 { wsValue += str[cc]; }
2058 cc++;
2059 ccf++;
2060 break;
2061 case 'z':
2062 if (FX_IsDigit(str[cc])) {
2063 wsValue += str[cc];
2064 cc++;
2065 }
2066 ccf++;
2067 break;
2068 case 'Z':
2069 if (str[cc] != ' ') {
2070 if (FX_IsDigit(str[cc])) {
2071 wsValue += str[cc];
2072 cc++;
2073 }
2074 } else {
2075 cc++;
2076 }
2077 ccf++;
2078 break;
2079 case 'S':
2080 if (str[cc] == '+' || str[cc] == ' ') {
2081 cc++;
2082 } else {
2083 if (cc + iMinusLen > len ||
2084 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
2085 return FALSE;
2086 }
2087 bNeg = TRUE;
2088 cc += iMinusLen;
2089 }
2090 ccf++;
2091 break;
2092 case 's':
2093 if (str[cc] == '+') {
2094 cc++;
2095 } else {
2096 if (cc + iMinusLen > len ||
2097 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
2098 return FALSE;
2099 }
2100 bNeg = TRUE;
2101 cc += iMinusLen;
2102 }
2103 ccf++;
2104 break;
2105 case 'E': {
2106 if (cc >= len || (str[cc] != 'E' && str[cc] != 'e')) {
2107 return FALSE;
2108 }
2109 FX_BOOL bExpSign = FALSE;
2110 cc++;
2111 if (cc < len) {
2112 if (str[cc] == '+') {
2113 cc++;
2114 } else if (str[cc] == '-') {
2115 bExpSign = TRUE;
2116 cc++;
2117 }
2118 }
2119 while (cc < len) {
2120 if (!FX_IsDigit(str[cc])) {
2121 break;
2122 }
2123 iExponent = iExponent * 10 + str[cc] - '0';
2124 cc++;
2125 }
2126 iExponent = bExpSign ? -iExponent : iExponent;
2127 ccf++;
2128 } break;
2129 case '$': {
2130 CFX_WideString wsSymbol;
2131 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol,
2132 wsSymbol);
2133 int32_t iSymbolLen = wsSymbol.GetLength();
2134 if (cc + iSymbolLen > len ||
2135 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) {
2136 return FALSE;
2137 }
2138 cc += iSymbolLen;
2139 ccf++;
2140 } break;
2141 case 'c':
2142 if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
2143 if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
2144 bNeg = TRUE;
2145 cc += 2;
2146 }
2147 ccf += 2;
2148 }
2149 break;
2150 case 'C':
2151 if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
2152 if (str[cc] == ' ') {
2153 cc++;
2154 } else if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
2155 bNeg = TRUE;
2156 cc += 2;
2157 }
2158 ccf += 2;
2159 }
2160 break;
2161 case 'd':
2162 if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
2163 if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
2164 bNeg = TRUE;
2165 cc += 2;
2166 }
2167 ccf += 2;
2168 }
2169 break;
2170 case 'D':
2171 if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
2172 if (str[cc] == ' ') {
2173 cc++;
2174 } else if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
2175 bNeg = TRUE;
2176 cc += 2;
2177 }
2178 ccf += 2;
2179 }
2180 break;
2181 case '.':
2182 case 'V':
2183 case 'v':
2184 return FALSE;
2185 case '%': {
2186 CFX_WideString wsSymbol;
2187 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
2188 int32_t iSysmbolLen = wsSymbol.GetLength();
2189 if (cc + iSysmbolLen <= len &&
2190 !FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol,
2191 iSysmbolLen)) {
2192 cc += iSysmbolLen;
2193 }
2194 ccf++;
2195 bHavePercentSymbol = TRUE;
2196 } break;
2197 case '8': {
2198 while (ccf < lenf && strf[ccf] == '8') {
2199 ccf++;
2200 }
2201 while (cc < len && FX_IsDigit(str[cc])) {
2202 wsValue += str[cc];
2203 cc++;
2204 }
2205 } break;
2206 case ',': {
2207 if (cc + iGroupLen <= len &&
2208 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol,
2209 iGroupLen) == 0) {
2210 cc += iGroupLen;
2211 }
2212 ccf++;
2213 } break;
2214 case '(':
2215 if (str[cc] == L'(') {
2216 bNeg = TRUE;
2217 } else if (str[cc] != L' ') {
2218 return FALSE;
2219 }
2220 cc++;
2221 ccf++;
2222 break;
2223 case ')':
2224 if (str[cc] == L')') {
2225 bNeg = TRUE;
2226 } else if (str[cc] != L' ') {
2227 return FALSE;
2228 }
2229 cc++;
2230 ccf++;
2231 break;
2232 default:
2233 if (strf[ccf] != str[cc]) {
2234 return FALSE;
2235 }
2236 cc++;
2237 ccf++;
2238 }
2239 }
2240 if (cc != len) {
2241 return FALSE;
2242 }
2243 }
2244 if (iExponent || bHavePercentSymbol) {
2245 CFX_Decimal decimal = CFX_Decimal(wsValue);
2246 if (iExponent) {
2247 decimal = decimal * CFX_Decimal(FXSYS_pow(10, (FX_FLOAT)iExponent));
2248 }
2249 if (bHavePercentSymbol) {
2250 decimal = decimal / CFX_Decimal(100);
2251 }
2252 wsValue = decimal;
2253 }
2254 if (bNeg) {
2255 wsValue = CFX_WideStringC('-') + wsValue;
2256 }
2257 return TRUE;
2258 }
GetDateTimeFormat(const CFX_WideString & wsPattern,IFX_Locale * & pLocale,CFX_WideString & wsDatePattern,CFX_WideString & wsTimePattern)2259 FX_DATETIMETYPE CFX_FormatString::GetDateTimeFormat(
2260 const CFX_WideString& wsPattern,
2261 IFX_Locale*& pLocale,
2262 CFX_WideString& wsDatePattern,
2263 CFX_WideString& wsTimePattern) {
2264 pLocale = NULL;
2265 CFX_WideString wsTempPattern;
2266 FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown;
2267 int32_t ccf = 0;
2268 int32_t iLenf = wsPattern.GetLength();
2269 const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern;
2270 int32_t iFindCategory = 0;
2271 FX_BOOL bBraceOpen = FALSE;
2272 while (ccf < iLenf) {
2273 if (pStr[ccf] == '\'') {
2274 int32_t iCurChar = ccf;
2275 FX_GetLiteralText(pStr, ccf, iLenf);
2276 wsTempPattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1);
2277 } else if (!bBraceOpen && iFindCategory != 3 &&
2278 FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
2279 CFX_WideString wsCategory(pStr[ccf]);
2280 ccf++;
2281 while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' &&
2282 pStr[ccf] != '(') {
2283 if (pStr[ccf] == 'T') {
2284 wsDatePattern = wsPattern.Left(ccf);
2285 wsTimePattern = wsPattern.Right(wsPattern.GetLength() - ccf);
2286 wsTimePattern.SetAt(0, ' ');
2287 if (!pLocale) {
2288 pLocale = m_pLocaleMgr->GetDefLocale();
2289 }
2290 return FX_DATETIMETYPE_DateTime;
2291 }
2292 wsCategory += pStr[ccf];
2293 ccf++;
2294 }
2295 if (!(iFindCategory & 1) && wsCategory == FX_WSTRC(L"date")) {
2296 iFindCategory |= 1;
2297 eCategory = FX_LOCALECATEGORY_Date;
2298 if (iFindCategory & 2) {
2299 iFindCategory = 4;
2300 }
2301 } else if (!(iFindCategory & 2) && wsCategory == FX_WSTRC(L"time")) {
2302 iFindCategory |= 2;
2303 eCategory = FX_LOCALECATEGORY_Time;
2304 } else if (wsCategory == FX_WSTRC(L"datetime")) {
2305 iFindCategory = 3;
2306 eCategory = FX_LOCALECATEGORY_DateTime;
2307 } else {
2308 continue;
2309 }
2310 while (ccf < iLenf) {
2311 if (pStr[ccf] == '(') {
2312 ccf++;
2313 CFX_WideString wsLCID;
2314 while (ccf < iLenf && pStr[ccf] != ')') {
2315 wsLCID += pStr[ccf++];
2316 }
2317 pLocale = GetPatternLocale(wsLCID);
2318 } else if (pStr[ccf] == '{') {
2319 bBraceOpen = TRUE;
2320 break;
2321 } else if (pStr[ccf] == '.') {
2322 CFX_WideString wsSubCategory;
2323 ccf++;
2324 while (ccf < iLenf && pStr[ccf] != '(' && pStr[ccf] != '{') {
2325 wsSubCategory += pStr[ccf++];
2326 }
2327 FX_DWORD dwSubHash =
2328 FX_HashCode_String_GetW(wsSubCategory, wsSubCategory.GetLength());
2329 FX_LOCALEDATETIMESUBCATEGORY eSubCategory =
2330 FX_LOCALEDATETIMESUBCATEGORY_Medium;
2331 for (int32_t i = 0; i < g_iFXLocaleDateTimeSubCatCount; i++) {
2332 if (g_FXLocaleDateTimeSubCatData[i].uHash == dwSubHash) {
2333 eSubCategory =
2334 (FX_LOCALEDATETIMESUBCATEGORY)g_FXLocaleDateTimeSubCatData[i]
2335 .eSubCategory;
2336 break;
2337 }
2338 }
2339 if (!pLocale) {
2340 pLocale = m_pLocaleMgr->GetDefLocale();
2341 }
2342 FXSYS_assert(pLocale != NULL);
2343 switch (eCategory) {
2344 case FX_LOCALECATEGORY_Date:
2345 pLocale->GetDatePattern(eSubCategory, wsDatePattern);
2346 wsDatePattern = wsTempPattern + wsDatePattern;
2347 break;
2348 case FX_LOCALECATEGORY_Time:
2349 pLocale->GetTimePattern(eSubCategory, wsTimePattern);
2350 wsTimePattern = wsTempPattern + wsTimePattern;
2351 break;
2352 case FX_LOCALECATEGORY_DateTime:
2353 pLocale->GetDatePattern(eSubCategory, wsDatePattern);
2354 wsDatePattern = wsTempPattern + wsDatePattern;
2355 pLocale->GetTimePattern(eSubCategory, wsTimePattern);
2356 break;
2357 default:
2358 break;
2359 }
2360 wsTempPattern.Empty();
2361 continue;
2362 }
2363 ccf++;
2364 }
2365 } else if (pStr[ccf] == '}') {
2366 bBraceOpen = FALSE;
2367 if (!wsTempPattern.IsEmpty()) {
2368 if (eCategory == FX_LOCALECATEGORY_Time) {
2369 wsTimePattern = wsTempPattern;
2370 } else if (eCategory == FX_LOCALECATEGORY_Date) {
2371 wsDatePattern = wsTempPattern;
2372 }
2373 wsTempPattern.Empty();
2374 }
2375 } else {
2376 wsTempPattern += pStr[ccf];
2377 }
2378 ccf++;
2379 }
2380 if (!wsTempPattern.IsEmpty()) {
2381 if (eCategory == FX_LOCALECATEGORY_Date) {
2382 wsDatePattern += wsTempPattern;
2383 } else {
2384 wsTimePattern += wsTempPattern;
2385 }
2386 }
2387 if (!pLocale) {
2388 pLocale = m_pLocaleMgr->GetDefLocale();
2389 }
2390 if (!iFindCategory) {
2391 wsTimePattern.Empty();
2392 wsDatePattern = wsPattern;
2393 }
2394 return (FX_DATETIMETYPE)iFindCategory;
2395 }
FX_ParseLocaleDate(const CFX_WideString & wsDate,const CFX_WideString & wsDatePattern,IFX_Locale * pLocale,CFX_Unitime & datetime,int32_t & cc)2396 static FX_BOOL FX_ParseLocaleDate(const CFX_WideString& wsDate,
2397 const CFX_WideString& wsDatePattern,
2398 IFX_Locale* pLocale,
2399 CFX_Unitime& datetime,
2400 int32_t& cc) {
2401 int32_t year = 1900;
2402 int32_t month = 1;
2403 int32_t day = 1;
2404 int32_t ccf = 0;
2405 const FX_WCHAR* str = (const FX_WCHAR*)wsDate;
2406 int32_t len = wsDate.GetLength();
2407 const FX_WCHAR* strf = (const FX_WCHAR*)wsDatePattern;
2408 int32_t lenf = wsDatePattern.GetLength();
2409 while (cc < len && ccf < lenf) {
2410 if (strf[ccf] == '\'') {
2411 CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
2412 int32_t iLiteralLen = wsLiteral.GetLength();
2413 if (cc + iLiteralLen > len ||
2414 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) {
2415 return FALSE;
2416 }
2417 cc += iLiteralLen;
2418 ccf++;
2419 continue;
2420 } else if (FX_Local_Find(gs_wsDateSymbols, strf[ccf]) < 0) {
2421 if (strf[ccf] != str[cc]) {
2422 return FALSE;
2423 }
2424 cc++;
2425 ccf++;
2426 continue;
2427 }
2428 FX_DWORD dwSymbolNum = 1;
2429 FX_DWORD dwSymbol = strf[ccf++];
2430 while (ccf < lenf && strf[ccf] == dwSymbol) {
2431 ccf++;
2432 dwSymbolNum++;
2433 }
2434 dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
2435 if (dwSymbol == FXBSTR_ID(0, 0, 'D', '1')) {
2436 if (!FX_IsDigit(str[cc])) {
2437 return FALSE;
2438 }
2439 day = str[cc++] - '0';
2440 if (cc < len && FX_IsDigit(str[cc])) {
2441 day = day * 10 + str[cc++] - '0';
2442 }
2443 } else if (dwSymbol == FXBSTR_ID(0, 0, 'D', '2')) {
2444 if (!FX_IsDigit(str[cc])) {
2445 return FALSE;
2446 }
2447 day = str[cc++] - '0';
2448 if (cc < len) {
2449 day = day * 10 + str[cc++] - '0';
2450 }
2451 } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '1')) {
2452 int i = 0;
2453 while (cc < len && i < 3 && FX_IsDigit(str[cc])) {
2454 cc++;
2455 i++;
2456 }
2457 } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '3')) {
2458 cc += 3;
2459 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
2460 if (!FX_IsDigit(str[cc])) {
2461 return FALSE;
2462 }
2463 month = str[cc++] - '0';
2464 if (cc < len && FX_IsDigit(str[cc])) {
2465 month = month * 10 + str[cc++] - '0';
2466 }
2467 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
2468 if (!FX_IsDigit(str[cc])) {
2469 return FALSE;
2470 }
2471 month = str[cc++] - '0';
2472 if (cc < len) {
2473 month = month * 10 + str[cc++] - '0';
2474 }
2475 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '3')) {
2476 CFX_WideString wsMonthNameAbbr;
2477 FX_WORD i = 0;
2478 for (; i < 12; i++) {
2479 pLocale->GetMonthName(i, wsMonthNameAbbr, TRUE);
2480 if (wsMonthNameAbbr.IsEmpty()) {
2481 continue;
2482 }
2483 if (!FXSYS_wcsncmp((const FX_WCHAR*)wsMonthNameAbbr, str + cc,
2484 wsMonthNameAbbr.GetLength())) {
2485 break;
2486 }
2487 }
2488 if (i < 12) {
2489 cc += wsMonthNameAbbr.GetLength();
2490 month = i + 1;
2491 }
2492 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '4')) {
2493 CFX_WideString wsMonthName;
2494 FX_WORD i = 0;
2495 for (; i < 12; i++) {
2496 pLocale->GetMonthName(i, wsMonthName, FALSE);
2497 if (wsMonthName.IsEmpty()) {
2498 continue;
2499 }
2500 if (!FXSYS_wcsncmp((const FX_WCHAR*)wsMonthName, str + cc,
2501 wsMonthName.GetLength())) {
2502 break;
2503 }
2504 }
2505 if (i < 12) {
2506 cc += wsMonthName.GetLength();
2507 month = i + 1;
2508 }
2509 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '1')) {
2510 cc += 1;
2511 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '3')) {
2512 CFX_WideString wsDayNameAbbr;
2513 FX_WORD i = 0;
2514 for (; i < 7; i++) {
2515 pLocale->GetDayName(i, wsDayNameAbbr, TRUE);
2516 if (wsDayNameAbbr.IsEmpty()) {
2517 continue;
2518 }
2519 if (!FXSYS_wcsncmp((const FX_WCHAR*)wsDayNameAbbr, str + cc,
2520 wsDayNameAbbr.GetLength())) {
2521 break;
2522 }
2523 }
2524 if (i < 12) {
2525 cc += wsDayNameAbbr.GetLength();
2526 }
2527 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '4')) {
2528 CFX_WideString wsDayName;
2529 int32_t i = 0;
2530 for (; i < 7; i++) {
2531 pLocale->GetDayName(i, wsDayName, FALSE);
2532 if (wsDayName == L"") {
2533 continue;
2534 }
2535 if (!FXSYS_wcsncmp((const FX_WCHAR*)wsDayName, str + cc,
2536 wsDayName.GetLength())) {
2537 break;
2538 }
2539 }
2540 if (i < 12) {
2541 cc += wsDayName.GetLength();
2542 }
2543 } else if (dwSymbol == FXBSTR_ID(0, 0, 'e', '1')) {
2544 cc += 1;
2545 } else if (dwSymbol == FXBSTR_ID(0, 0, 'G', '1')) {
2546 cc += 2;
2547 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '2')) {
2548 if (cc + 2 > len) {
2549 return FALSE;
2550 }
2551 if (!FX_IsDigit(str[cc])) {
2552 return FALSE;
2553 }
2554 year = str[cc++] - '0';
2555 if (cc >= len || !FX_IsDigit(str[cc])) {
2556 return FALSE;
2557 }
2558 year = year * 10 + str[cc++] - '0';
2559 if (year <= 29) {
2560 year += 2000;
2561 } else {
2562 year += 1900;
2563 }
2564 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '4')) {
2565 int i = 0;
2566 year = 0;
2567 if (cc + 4 > len) {
2568 return FALSE;
2569 }
2570 while (i < 4) {
2571 if (!FX_IsDigit(str[cc])) {
2572 return FALSE;
2573 }
2574 year = year * 10 + str[cc] - '0';
2575 cc++;
2576 i++;
2577 }
2578 } else if (dwSymbol == FXBSTR_ID(0, 0, 'w', '1')) {
2579 cc += 1;
2580 } else if (dwSymbol == FXBSTR_ID(0, 0, 'W', '2')) {
2581 cc += 2;
2582 }
2583 }
2584 if (cc < len) {
2585 return FALSE;
2586 }
2587 CFX_Unitime ut;
2588 ut.Set(year, month, day);
2589 datetime = datetime + ut;
2590 return cc;
2591 }
FX_ResolveZone(uint8_t & wHour,uint8_t & wMinute,FX_TIMEZONE tzDiff,IFX_Locale * pLocale)2592 static void FX_ResolveZone(uint8_t& wHour,
2593 uint8_t& wMinute,
2594 FX_TIMEZONE tzDiff,
2595 IFX_Locale* pLocale) {
2596 int32_t iMinuteDiff = wHour * 60 + wMinute;
2597 FX_TIMEZONE tzLocale;
2598 pLocale->GetTimeZone(tzLocale);
2599 iMinuteDiff += tzLocale.tzHour * 60 +
2600 (tzLocale.tzHour < 0 ? -tzLocale.tzMinute : tzLocale.tzMinute);
2601 iMinuteDiff -= tzDiff.tzHour * 60 +
2602 (tzDiff.tzHour < 0 ? -tzDiff.tzMinute : tzDiff.tzMinute);
2603 while (iMinuteDiff > 1440) {
2604 iMinuteDiff -= 1440;
2605 }
2606 while (iMinuteDiff < 0) {
2607 iMinuteDiff += 1440;
2608 }
2609 wHour = iMinuteDiff / 60;
2610 wMinute = iMinuteDiff % 60;
2611 }
FX_ParseLocaleTime(const CFX_WideString & wsTime,const CFX_WideString & wsTimePattern,IFX_Locale * pLocale,CFX_Unitime & datetime,int32_t & cc)2612 static FX_BOOL FX_ParseLocaleTime(const CFX_WideString& wsTime,
2613 const CFX_WideString& wsTimePattern,
2614 IFX_Locale* pLocale,
2615 CFX_Unitime& datetime,
2616 int32_t& cc) {
2617 uint8_t hour = 0;
2618 uint8_t minute = 0;
2619 uint8_t second = 0;
2620 FX_WORD millisecond = 0;
2621 int32_t ccf = 0;
2622 const FX_WCHAR* str = (const FX_WCHAR*)wsTime;
2623 int len = wsTime.GetLength();
2624 const FX_WCHAR* strf = (const FX_WCHAR*)wsTimePattern;
2625 int lenf = wsTimePattern.GetLength();
2626 FX_BOOL bHasA = FALSE;
2627 FX_BOOL bPM = FALSE;
2628 while (cc < len && ccf < lenf) {
2629 if (strf[ccf] == '\'') {
2630 CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
2631 int32_t iLiteralLen = wsLiteral.GetLength();
2632 if (cc + iLiteralLen > len ||
2633 FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) {
2634 return FALSE;
2635 }
2636 cc += iLiteralLen;
2637 ccf++;
2638 continue;
2639 } else if (FX_Local_Find(gs_wsTimeSymbols, strf[ccf]) == -1) {
2640 if (strf[ccf] != str[cc]) {
2641 return FALSE;
2642 }
2643 cc++;
2644 ccf++;
2645 continue;
2646 }
2647 FX_DWORD dwSymbolNum = 1;
2648 FX_DWORD dwSymbol = strf[ccf++];
2649 while (ccf < lenf && strf[ccf] == dwSymbol) {
2650 ccf++;
2651 dwSymbolNum++;
2652 }
2653 dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
2654 if (dwSymbol == FXBSTR_ID(0, 0, 'k', '1') ||
2655 dwSymbol == FXBSTR_ID(0, 0, 'H', '1') ||
2656 dwSymbol == FXBSTR_ID(0, 0, 'h', '1') ||
2657 dwSymbol == FXBSTR_ID(0, 0, 'K', '1')) {
2658 if (!FX_IsDigit(str[cc])) {
2659 return FALSE;
2660 }
2661 hour = str[cc++] - '0';
2662 if (cc < len && FX_IsDigit(str[cc])) {
2663 hour = hour * 10 + str[cc++] - '0';
2664 }
2665 if (dwSymbol == FXBSTR_ID(0, 0, 'K', '1') && hour == 24) {
2666 hour = 0;
2667 }
2668 } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '2') ||
2669 dwSymbol == FXBSTR_ID(0, 0, 'H', '2') ||
2670 dwSymbol == FXBSTR_ID(0, 0, 'h', '2') ||
2671 dwSymbol == FXBSTR_ID(0, 0, 'K', '2')) {
2672 if (!FX_IsDigit(str[cc])) {
2673 return FALSE;
2674 }
2675 hour = str[cc++] - '0';
2676 if (cc >= len) {
2677 return FALSE;
2678 }
2679 if (!FX_IsDigit(str[cc])) {
2680 return FALSE;
2681 }
2682 hour = hour * 10 + str[cc++] - '0';
2683 if (dwSymbol == FXBSTR_ID(0, 0, 'K', '2') && hour == 24) {
2684 hour = 0;
2685 }
2686 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
2687 if (!FX_IsDigit(str[cc])) {
2688 return FALSE;
2689 }
2690 minute = str[cc++] - '0';
2691 if (cc < len && FX_IsDigit(str[cc])) {
2692 minute = minute * 10 + str[cc++] - '0';
2693 }
2694 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
2695 if (!FX_IsDigit(str[cc])) {
2696 return FALSE;
2697 }
2698 minute = str[cc++] - '0';
2699 if (cc >= len) {
2700 return FALSE;
2701 }
2702 if (!FX_IsDigit(str[cc])) {
2703 return FALSE;
2704 }
2705 minute = minute * 10 + str[cc++] - '0';
2706 } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '1')) {
2707 if (!FX_IsDigit(str[cc])) {
2708 return FALSE;
2709 }
2710 second = str[cc++] - '0';
2711 if (cc < len && FX_IsDigit(str[cc])) {
2712 second = second * 10 + str[cc++] - '0';
2713 }
2714 } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '2')) {
2715 if (!FX_IsDigit(str[cc])) {
2716 return FALSE;
2717 }
2718 second = str[cc++] - '0';
2719 if (cc >= len) {
2720 return FALSE;
2721 }
2722 if (!FX_IsDigit(str[cc])) {
2723 return FALSE;
2724 }
2725 second = second * 10 + str[cc++] - '0';
2726 } else if (dwSymbol == FXBSTR_ID(0, 0, 'F', '3')) {
2727 if (cc + 3 >= len) {
2728 return FALSE;
2729 }
2730 int i = 0;
2731 while (i < 3) {
2732 if (!FX_IsDigit(str[cc])) {
2733 return FALSE;
2734 }
2735 millisecond = millisecond * 10 + str[cc++] - '0';
2736 i++;
2737 }
2738 } else if (dwSymbol == FXBSTR_ID(0, 0, 'A', '1')) {
2739 CFX_WideString wsAM;
2740 pLocale->GetMeridiemName(wsAM, TRUE);
2741 CFX_WideString wsPM;
2742 pLocale->GetMeridiemName(wsPM, FALSE);
2743 if ((cc + wsAM.GetLength() <= len) &&
2744 (CFX_WideStringC(str + cc, wsAM.GetLength()) == wsAM)) {
2745 cc += wsAM.GetLength();
2746 bHasA = TRUE;
2747 } else if ((cc + wsPM.GetLength() <= len) &&
2748 (CFX_WideStringC(str + cc, wsPM.GetLength()) == wsPM)) {
2749 cc += wsPM.GetLength();
2750 bHasA = TRUE;
2751 bPM = TRUE;
2752 }
2753 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Z', '1')) {
2754 if (cc + 3 > len) {
2755 continue;
2756 }
2757 FX_DWORD dwHash = str[cc++];
2758 dwHash = (dwHash << 8) | str[cc++];
2759 dwHash = (dwHash << 8) | str[cc++];
2760 if (dwHash == FXBSTR_ID(0, 'G', 'M', 'T')) {
2761 FX_TIMEZONE tzDiff;
2762 tzDiff.tzHour = 0;
2763 tzDiff.tzMinute = 0;
2764 if (cc < len && (str[cc] == '-' || str[cc] == '+')) {
2765 cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff);
2766 }
2767 FX_ResolveZone(hour, minute, tzDiff, pLocale);
2768 } else {
2769 FX_LPCLOCALETIMEZONEINFO pTimeZoneInfo = NULL;
2770 int32_t iStart = 0, iEnd = g_iFXLocaleTimeZoneCount - 1;
2771 do {
2772 int32_t iMid = (iStart + iEnd) / 2;
2773 FX_LPCLOCALETIMEZONEINFO pInfo = g_FXLocaleTimeZoneData + iMid;
2774 if (dwHash == pInfo->uHash) {
2775 pTimeZoneInfo = pInfo;
2776 break;
2777 } else if (dwHash < pInfo->uHash) {
2778 iEnd = iMid - 1;
2779 } else {
2780 iStart = iMid + 1;
2781 }
2782 } while (iStart <= iEnd);
2783 if (pTimeZoneInfo) {
2784 hour += pTimeZoneInfo->iHour;
2785 minute += pTimeZoneInfo->iHour > 0 ? pTimeZoneInfo->iMinute
2786 : -pTimeZoneInfo->iMinute;
2787 }
2788 }
2789 } else if (dwSymbol == FXBSTR_ID(0, 0, 'z', '1')) {
2790 if (str[cc] != 'Z') {
2791 FX_TIMEZONE tzDiff;
2792 cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff);
2793 FX_ResolveZone(hour, minute, tzDiff, pLocale);
2794 } else {
2795 cc++;
2796 }
2797 }
2798 }
2799 if (bHasA) {
2800 if (bPM) {
2801 hour += 12;
2802 if (hour == 24) {
2803 hour = 12;
2804 }
2805 } else {
2806 if (hour == 12) {
2807 hour = 0;
2808 }
2809 }
2810 }
2811 CFX_Unitime ut;
2812 ut.Set(0, 0, 0, hour, minute, second, millisecond);
2813 datetime = datetime + ut;
2814 return cc;
2815 }
ParseDateTime(const CFX_WideString & wsSrcDateTime,const CFX_WideString & wsPattern,FX_DATETIMETYPE eDateTimeType,CFX_Unitime & dtValue)2816 FX_BOOL CFX_FormatString::ParseDateTime(const CFX_WideString& wsSrcDateTime,
2817 const CFX_WideString& wsPattern,
2818 FX_DATETIMETYPE eDateTimeType,
2819 CFX_Unitime& dtValue) {
2820 dtValue.Set(0);
2821 if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) {
2822 return FALSE;
2823 }
2824 CFX_WideString wsDatePattern, wsTimePattern;
2825 IFX_Locale* pLocale = NULL;
2826 FX_DATETIMETYPE eCategory =
2827 GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
2828 if (!pLocale) {
2829 return FALSE;
2830 }
2831 if (eCategory == FX_DATETIMETYPE_Unknown) {
2832 eCategory = eDateTimeType;
2833 }
2834 if (eCategory == FX_DATETIMETYPE_Unknown) {
2835 return FALSE;
2836 }
2837 if (eCategory == FX_DATETIMETYPE_TimeDate) {
2838 int32_t iStart = 0;
2839 if (!FX_ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue,
2840 iStart)) {
2841 return FALSE;
2842 }
2843 if (!FX_ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue,
2844 iStart)) {
2845 return FALSE;
2846 }
2847 } else {
2848 int32_t iStart = 0;
2849 if ((eCategory & FX_DATETIMETYPE_Date) &&
2850 !FX_ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue,
2851 iStart)) {
2852 return FALSE;
2853 }
2854 if ((eCategory & FX_DATETIMETYPE_Time) &&
2855 !FX_ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue,
2856 iStart)) {
2857 return FALSE;
2858 }
2859 }
2860 return TRUE;
2861 }
ParseZero(const CFX_WideString & wsSrcText,const CFX_WideString & wsPattern)2862 FX_BOOL CFX_FormatString::ParseZero(const CFX_WideString& wsSrcText,
2863 const CFX_WideString& wsPattern) {
2864 CFX_WideString wsTextFormat;
2865 GetTextFormat(wsPattern, FX_WSTRC(L"zero"), wsTextFormat);
2866 int32_t iText = 0, iPattern = 0;
2867 const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText;
2868 int32_t iLenText = wsSrcText.GetLength();
2869 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
2870 int32_t iLenPattern = wsTextFormat.GetLength();
2871 while (iPattern < iLenPattern && iText < iLenText) {
2872 if (pStrPattern[iPattern] == '\'') {
2873 CFX_WideString wsLiteral =
2874 FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
2875 int32_t iLiteralLen = wsLiteral.GetLength();
2876 if (iText + iLiteralLen > iLenText ||
2877 FXSYS_wcsncmp(pStrText + iText, (const FX_WCHAR*)wsLiteral,
2878 iLiteralLen)) {
2879 return FALSE;
2880 }
2881 iText += iLiteralLen;
2882 iPattern++;
2883 continue;
2884 } else if (pStrPattern[iPattern] != pStrText[iText]) {
2885 return FALSE;
2886 } else {
2887 iText++;
2888 iPattern++;
2889 }
2890 }
2891 return iPattern == iLenPattern && iText == iLenText;
2892 }
ParseNull(const CFX_WideString & wsSrcText,const CFX_WideString & wsPattern)2893 FX_BOOL CFX_FormatString::ParseNull(const CFX_WideString& wsSrcText,
2894 const CFX_WideString& wsPattern) {
2895 CFX_WideString wsTextFormat;
2896 GetTextFormat(wsPattern, FX_WSTRC(L"null"), wsTextFormat);
2897 int32_t iText = 0, iPattern = 0;
2898 const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText;
2899 int32_t iLenText = wsSrcText.GetLength();
2900 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
2901 int32_t iLenPattern = wsTextFormat.GetLength();
2902 while (iPattern < iLenPattern && iText < iLenText) {
2903 if (pStrPattern[iPattern] == '\'') {
2904 CFX_WideString wsLiteral =
2905 FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
2906 int32_t iLiteralLen = wsLiteral.GetLength();
2907 if (iText + iLiteralLen > iLenText ||
2908 FXSYS_wcsncmp(pStrText + iText, (const FX_WCHAR*)wsLiteral,
2909 iLiteralLen)) {
2910 return FALSE;
2911 }
2912 iText += iLiteralLen;
2913 iPattern++;
2914 continue;
2915 } else if (pStrPattern[iPattern] != pStrText[iText]) {
2916 return FALSE;
2917 } else {
2918 iText++;
2919 iPattern++;
2920 }
2921 }
2922 return iPattern == iLenPattern && iText == iLenText;
2923 }
FormatText(const CFX_WideString & wsSrcText,const CFX_WideString & wsPattern,CFX_WideString & wsOutput)2924 FX_BOOL CFX_FormatString::FormatText(const CFX_WideString& wsSrcText,
2925 const CFX_WideString& wsPattern,
2926 CFX_WideString& wsOutput) {
2927 if (wsPattern.IsEmpty()) {
2928 return FALSE;
2929 }
2930 int32_t iLenText = wsSrcText.GetLength();
2931 if (iLenText == 0) {
2932 return FALSE;
2933 }
2934 CFX_WideString wsTextFormat;
2935 GetTextFormat(wsPattern, FX_WSTRC(L"text"), wsTextFormat);
2936 int32_t iText = 0, iPattern = 0;
2937 const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText;
2938 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
2939 int32_t iLenPattern = wsTextFormat.GetLength();
2940 while (iPattern < iLenPattern) {
2941 switch (pStrPattern[iPattern]) {
2942 case '\'': {
2943 wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
2944 iPattern++;
2945 break;
2946 }
2947 case 'A':
2948 if (iText >= iLenText || !FX_IsAlpha(pStrText[iText])) {
2949 return FALSE;
2950 }
2951 wsOutput += pStrText[iText++];
2952 iPattern++;
2953 break;
2954 case 'X':
2955 if (iText >= iLenText) {
2956 return FALSE;
2957 }
2958 wsOutput += pStrText[iText++];
2959 iPattern++;
2960 break;
2961 case 'O':
2962 case '0':
2963 if (iText >= iLenText ||
2964 (!FX_IsDigit(pStrText[iText]) && !FX_IsAlpha(pStrText[iText]))) {
2965 return FALSE;
2966 }
2967 wsOutput += pStrText[iText++];
2968 iPattern++;
2969 break;
2970 case '9':
2971 if (iText >= iLenText || !FX_IsDigit(pStrText[iText])) {
2972 return FALSE;
2973 }
2974 wsOutput += pStrText[iText++];
2975 iPattern++;
2976 break;
2977 default:
2978 wsOutput += pStrPattern[iPattern++];
2979 break;
2980 }
2981 }
2982 return iText == iLenText;
2983 }
FX_GetNumTrailingLimit(const CFX_WideString & wsFormat,int iDotPos,FX_BOOL & bTrimTailZeros)2984 static int32_t FX_GetNumTrailingLimit(const CFX_WideString& wsFormat,
2985 int iDotPos,
2986 FX_BOOL& bTrimTailZeros) {
2987 if (iDotPos < 0) {
2988 return 0;
2989 }
2990 int32_t iCount = wsFormat.GetLength();
2991 int32_t iTreading = 0;
2992 for (iDotPos++; iDotPos < iCount; iDotPos++) {
2993 FX_WCHAR wc = wsFormat[iDotPos];
2994 if (wc == L'z' || wc == L'9' || wc == 'Z') {
2995 iTreading++;
2996 bTrimTailZeros = (wc == L'9' ? FALSE : TRUE);
2997 }
2998 }
2999 return iTreading;
3000 }
FormatStrNum(const CFX_WideStringC & wsInputNum,const CFX_WideString & wsPattern,CFX_WideString & wsOutput)3001 FX_BOOL CFX_FormatString::FormatStrNum(const CFX_WideStringC& wsInputNum,
3002 const CFX_WideString& wsPattern,
3003 CFX_WideString& wsOutput) {
3004 if (wsInputNum.IsEmpty() || wsPattern.IsEmpty()) {
3005 return FALSE;
3006 }
3007 int32_t dot_index_f = -1;
3008 FX_DWORD dwNumStyle = 0;
3009 CFX_WideString wsNumFormat;
3010 IFX_Locale* pLocale =
3011 GetNumericFormat(wsPattern, dot_index_f, dwNumStyle, wsNumFormat);
3012 if (!pLocale || wsNumFormat.IsEmpty()) {
3013 return FALSE;
3014 }
3015 int32_t cc = 0, ccf = 0;
3016 const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat;
3017 int lenf = wsNumFormat.GetLength();
3018 CFX_WideString wsSrcNum = wsInputNum;
3019 wsSrcNum.TrimLeft('0');
3020 if (wsSrcNum.IsEmpty() || wsSrcNum[0] == '.') {
3021 wsSrcNum.Insert(0, '0');
3022 }
3023 CFX_Decimal decimal = CFX_Decimal(wsSrcNum);
3024 if (dwNumStyle & FX_NUMSTYLE_Percent) {
3025 decimal = decimal * CFX_Decimal(100);
3026 wsSrcNum = decimal;
3027 }
3028 int32_t exponent = 0;
3029 if (dwNumStyle & FX_NUMSTYLE_Exponent) {
3030 int fixed_count = 0;
3031 while (ccf < dot_index_f) {
3032 switch (strf[ccf]) {
3033 case '\'':
3034 FX_GetLiteralText(strf, ccf, dot_index_f);
3035 break;
3036 case '9':
3037 case 'z':
3038 case 'Z':
3039 fixed_count++;
3040 break;
3041 }
3042 ccf++;
3043 }
3044 int threshold = 1;
3045 while (fixed_count > 1) {
3046 threshold *= 10;
3047 fixed_count--;
3048 }
3049 if (decimal != CFX_Decimal(0)) {
3050 if (decimal < CFX_Decimal(threshold)) {
3051 decimal = decimal * CFX_Decimal(10);
3052 exponent = -1;
3053 while (decimal < CFX_Decimal(threshold)) {
3054 decimal = decimal * CFX_Decimal(10);
3055 exponent -= 1;
3056 }
3057 } else if (decimal > CFX_Decimal(threshold)) {
3058 threshold *= 10;
3059 while (decimal > CFX_Decimal(threshold)) {
3060 decimal = decimal / CFX_Decimal(10);
3061 exponent += 1;
3062 }
3063 }
3064 }
3065 }
3066 FX_BOOL bTrimTailZeros = FALSE;
3067 int32_t iTreading =
3068 FX_GetNumTrailingLimit(wsNumFormat, dot_index_f, bTrimTailZeros);
3069 int32_t scale = decimal.GetScale();
3070 if (iTreading < scale) {
3071 decimal.SetScale(iTreading);
3072 wsSrcNum = decimal;
3073 }
3074 if (bTrimTailZeros && scale > 0 && iTreading > 0) {
3075 wsSrcNum.TrimRight(L"0");
3076 wsSrcNum.TrimRight(L".");
3077 }
3078 CFX_WideString wsGroupSymbol;
3079 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
3080 FX_BOOL bNeg = FALSE;
3081 if (wsSrcNum[0] == '-') {
3082 bNeg = TRUE;
3083 wsSrcNum.Delete(0, 1);
3084 }
3085 FX_BOOL bAddNeg = FALSE;
3086 const FX_WCHAR* str = (const FX_WCHAR*)wsSrcNum;
3087 int len = wsSrcNum.GetLength();
3088 int dot_index = wsSrcNum.Find('.');
3089 if (dot_index == -1) {
3090 dot_index = len;
3091 }
3092 ccf = dot_index_f - 1;
3093 cc = dot_index - 1;
3094 while (ccf >= 0) {
3095 switch (strf[ccf]) {
3096 case '9':
3097 if (cc >= 0) {
3098 if (!FX_IsDigit(str[cc])) {
3099 return FALSE;
3100 }
3101 wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
3102 cc--;
3103 } else {
3104 wsOutput = CFX_WideStringC(L'0') + wsOutput;
3105 }
3106 ccf--;
3107 break;
3108 case 'z':
3109 if (cc >= 0) {
3110 if (!FX_IsDigit(str[cc])) {
3111 return FALSE;
3112 }
3113 if (str[0] != '0') {
3114 wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
3115 }
3116 cc--;
3117 }
3118 ccf--;
3119 break;
3120 case 'Z':
3121 if (cc >= 0) {
3122 if (!FX_IsDigit(str[cc])) {
3123 return FALSE;
3124 }
3125 if (str[0] == '0') {
3126 wsOutput = CFX_WideStringC(L' ') + wsOutput;
3127 } else {
3128 wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
3129 }
3130 cc--;
3131 } else {
3132 wsOutput = CFX_WideStringC(L' ') + wsOutput;
3133 }
3134 ccf--;
3135 break;
3136 case 'S':
3137 if (bNeg) {
3138 CFX_WideString wsMinusSymbol;
3139 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
3140 wsOutput = wsMinusSymbol + wsOutput;
3141 bAddNeg = TRUE;
3142 } else {
3143 wsOutput = CFX_WideStringC(L' ') + wsOutput;
3144 }
3145 ccf--;
3146 break;
3147 case 's':
3148 if (bNeg) {
3149 CFX_WideString wsMinusSymbol;
3150 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
3151 wsOutput = wsMinusSymbol + wsOutput;
3152 bAddNeg = TRUE;
3153 }
3154 ccf--;
3155 break;
3156 case 'E': {
3157 CFX_WideString wsExp;
3158 wsExp.Format(L"E%+d", exponent);
3159 wsOutput = wsExp + wsOutput;
3160 }
3161 ccf--;
3162 break;
3163 case '$': {
3164 CFX_WideString wsSymbol;
3165 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
3166 wsOutput = wsSymbol + wsOutput;
3167 }
3168 ccf--;
3169 break;
3170 case 'r':
3171 if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
3172 if (bNeg) {
3173 wsOutput = L"CR" + wsOutput;
3174 }
3175 ccf -= 2;
3176 bAddNeg = TRUE;
3177 }
3178 break;
3179 case 'R':
3180 if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
3181 if (bNeg) {
3182 wsOutput = L"CR" + wsOutput;
3183 } else {
3184 wsOutput = L" " + wsOutput;
3185 }
3186 ccf -= 2;
3187 bAddNeg = TRUE;
3188 }
3189 break;
3190 case 'b':
3191 if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
3192 if (bNeg) {
3193 wsOutput = L"db" + wsOutput;
3194 }
3195 ccf -= 2;
3196 bAddNeg = TRUE;
3197 }
3198 break;
3199 case 'B':
3200 if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
3201 if (bNeg) {
3202 wsOutput = L"DB" + wsOutput;
3203 } else {
3204 wsOutput = L" " + wsOutput;
3205 }
3206 ccf -= 2;
3207 bAddNeg = TRUE;
3208 }
3209 break;
3210 case '%': {
3211 CFX_WideString wsSymbol;
3212 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
3213 wsOutput = wsSymbol + wsOutput;
3214 }
3215 ccf--;
3216 break;
3217 case ',':
3218 if (cc >= 0) {
3219 wsOutput = wsGroupSymbol + wsOutput;
3220 }
3221 ccf--;
3222 break;
3223 case '(':
3224 if (bNeg) {
3225 wsOutput = L"(" + wsOutput;
3226 } else {
3227 wsOutput = L" " + wsOutput;
3228 }
3229 bAddNeg = TRUE;
3230 ccf--;
3231 break;
3232 case ')':
3233 if (bNeg) {
3234 wsOutput = L")" + wsOutput;
3235 } else {
3236 wsOutput = L" " + wsOutput;
3237 }
3238 ccf--;
3239 break;
3240 case '\'':
3241 wsOutput = FX_GetLiteralTextReverse(strf, ccf) + wsOutput;
3242 ccf--;
3243 break;
3244 default:
3245 wsOutput = CFX_WideStringC(strf[ccf]) + wsOutput;
3246 ccf--;
3247 }
3248 }
3249 if (cc >= 0) {
3250 int nPos = dot_index % 3;
3251 wsOutput.Empty();
3252 for (int32_t i = 0; i < dot_index; i++) {
3253 if (i % 3 == nPos && i != 0) {
3254 wsOutput += wsGroupSymbol;
3255 }
3256 wsOutput += wsSrcNum[i];
3257 }
3258 if (dot_index < len) {
3259 CFX_WideString wsSymbol;
3260 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsSymbol);
3261 wsOutput += wsSymbol;
3262 wsOutput += wsSrcNum.Right(len - dot_index - 1);
3263 }
3264 if (bNeg) {
3265 CFX_WideString wsMinusymbol;
3266 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
3267 wsOutput = wsMinusymbol + wsOutput;
3268 }
3269 return FALSE;
3270 }
3271 if (dot_index_f == wsNumFormat.GetLength()) {
3272 if (!bAddNeg && bNeg) {
3273 CFX_WideString wsMinusymbol;
3274 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
3275 wsOutput = wsMinusymbol + wsOutput;
3276 }
3277 return TRUE;
3278 }
3279 CFX_WideString wsDotSymbol;
3280 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
3281 if (strf[dot_index_f] == 'V') {
3282 wsOutput += wsDotSymbol;
3283 } else if (strf[dot_index_f] == '.') {
3284 if (dot_index < len) {
3285 wsOutput += wsDotSymbol;
3286 } else {
3287 if (strf[dot_index_f + 1] == '9' || strf[dot_index_f + 1] == 'Z') {
3288 wsOutput += wsDotSymbol;
3289 }
3290 }
3291 }
3292 ccf = dot_index_f + 1;
3293 cc = dot_index + 1;
3294 while (ccf < lenf) {
3295 switch (strf[ccf]) {
3296 case '\'':
3297 wsOutput += FX_GetLiteralText(strf, ccf, lenf);
3298 ccf++;
3299 break;
3300 case '9':
3301 if (cc < len) {
3302 if (!FX_IsDigit(str[cc])) {
3303 return FALSE;
3304 }
3305 wsOutput += str[cc];
3306 cc++;
3307 } else {
3308 wsOutput += L'0';
3309 }
3310 ccf++;
3311 break;
3312 case 'z':
3313 if (cc < len) {
3314 if (!FX_IsDigit(str[cc])) {
3315 return FALSE;
3316 }
3317 wsOutput += str[cc];
3318 cc++;
3319 }
3320 ccf++;
3321 break;
3322 case 'Z':
3323 if (cc < len) {
3324 if (!FX_IsDigit(str[cc])) {
3325 return FALSE;
3326 }
3327 wsOutput += str[cc];
3328 cc++;
3329 } else {
3330 wsOutput += L'0';
3331 }
3332 ccf++;
3333 break;
3334 case 'E': {
3335 CFX_WideString wsExp;
3336 wsExp.Format(L"E%+d", exponent);
3337 wsOutput += wsExp;
3338 }
3339 ccf++;
3340 break;
3341 case '$': {
3342 CFX_WideString wsSymbol;
3343 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
3344 wsOutput += wsSymbol;
3345 }
3346 ccf++;
3347 break;
3348 case 'c':
3349 if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
3350 if (bNeg) {
3351 wsOutput += L"CR";
3352 }
3353 ccf += 2;
3354 bAddNeg = TRUE;
3355 }
3356 break;
3357 case 'C':
3358 if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
3359 if (bNeg) {
3360 wsOutput += L"CR";
3361 } else {
3362 wsOutput += L" ";
3363 }
3364 ccf += 2;
3365 bAddNeg = TRUE;
3366 }
3367 break;
3368 case 'd':
3369 if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
3370 if (bNeg) {
3371 wsOutput += L"db";
3372 }
3373 ccf += 2;
3374 bAddNeg = TRUE;
3375 }
3376 break;
3377 case 'D':
3378 if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
3379 if (bNeg) {
3380 wsOutput += L"DB";
3381 } else {
3382 wsOutput += L" ";
3383 }
3384 ccf += 2;
3385 bAddNeg = TRUE;
3386 }
3387 break;
3388 case '%': {
3389 CFX_WideString wsSymbol;
3390 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
3391 wsOutput += wsSymbol;
3392 }
3393 ccf++;
3394 break;
3395 case '8': {
3396 while (ccf < lenf && strf[ccf] == '8') {
3397 ccf++;
3398 }
3399 while (cc < len && FX_IsDigit(str[cc])) {
3400 wsOutput += str[cc];
3401 cc++;
3402 }
3403 } break;
3404 case ',':
3405 wsOutput += wsGroupSymbol;
3406 ccf++;
3407 break;
3408 case '(':
3409 if (bNeg) {
3410 wsOutput += '(';
3411 } else {
3412 wsOutput += ' ';
3413 }
3414 bAddNeg = TRUE;
3415 ccf++;
3416 break;
3417 case ')':
3418 if (bNeg) {
3419 wsOutput += ')';
3420 } else {
3421 wsOutput += ' ';
3422 }
3423 ccf++;
3424 break;
3425 default:
3426 ccf++;
3427 }
3428 }
3429 if (!bAddNeg && bNeg) {
3430 CFX_WideString wsMinusymbol;
3431 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
3432 wsOutput =
3433 wsMinusymbol + wsOutput[0] + wsOutput.Mid(1, wsOutput.GetLength() - 1);
3434 }
3435 return TRUE;
3436 }
FormatLCNumeric(CFX_LCNumeric & lcNum,const CFX_WideString & wsPattern,CFX_WideString & wsOutput)3437 FX_BOOL CFX_FormatString::FormatLCNumeric(CFX_LCNumeric& lcNum,
3438 const CFX_WideString& wsPattern,
3439 CFX_WideString& wsOutput) {
3440 int32_t dot_index_f = -1;
3441 FX_DWORD dwNumStyle = 0;
3442 CFX_WideString wsNumFormat;
3443 IFX_Locale* pLocale =
3444 GetNumericFormat(wsPattern, dot_index_f, dwNumStyle, wsNumFormat);
3445 if (!pLocale || wsNumFormat.IsEmpty()) {
3446 return FALSE;
3447 }
3448 int32_t cc = 0, ccf = 0;
3449 const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat;
3450 int lenf = wsNumFormat.GetLength();
3451 double dbOrgRaw = lcNum.GetDouble();
3452 double dbRetValue = dbOrgRaw;
3453 if (dwNumStyle & FX_NUMSTYLE_Percent) {
3454 dbRetValue *= 100;
3455 }
3456 int32_t exponent = 0;
3457 if (dwNumStyle & FX_NUMSTYLE_Exponent) {
3458 int fixed_count = 0;
3459 while (ccf < dot_index_f) {
3460 switch (strf[ccf]) {
3461 case '\'':
3462 FX_GetLiteralText(strf, ccf, dot_index_f);
3463 break;
3464 case '9':
3465 case 'z':
3466 case 'Z':
3467 fixed_count++;
3468 break;
3469 }
3470 ccf++;
3471 }
3472 int threshold = 1;
3473 while (fixed_count > 1) {
3474 threshold *= 10;
3475 fixed_count--;
3476 }
3477 if (dbRetValue != 0) {
3478 if (dbRetValue < threshold) {
3479 dbRetValue *= 10;
3480 exponent = -1;
3481 while (dbRetValue < threshold) {
3482 dbRetValue *= 10;
3483 exponent -= 1;
3484 }
3485 } else if (dbRetValue > threshold) {
3486 threshold *= 10;
3487 while (dbRetValue > threshold) {
3488 dbRetValue /= 10;
3489 exponent += 1;
3490 }
3491 }
3492 }
3493 }
3494 if (dwNumStyle & (FX_NUMSTYLE_Percent | FX_NUMSTYLE_Exponent)) {
3495 lcNum = CFX_LCNumeric(dbRetValue);
3496 }
3497 FX_BOOL bTrimTailZeros = FALSE;
3498 int32_t iTreading =
3499 FX_GetNumTrailingLimit(wsNumFormat, dot_index_f, bTrimTailZeros);
3500 CFX_WideString wsNumeric = lcNum.ToString(iTreading, bTrimTailZeros);
3501 if (wsNumeric.IsEmpty()) {
3502 return FALSE;
3503 }
3504 CFX_WideString wsGroupSymbol;
3505 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
3506 FX_BOOL bNeg = FALSE;
3507 if (wsNumeric[0] == '-') {
3508 bNeg = TRUE;
3509 wsNumeric.Delete(0, 1);
3510 }
3511 FX_BOOL bAddNeg = FALSE;
3512 const FX_WCHAR* str = (const FX_WCHAR*)wsNumeric;
3513 int len = wsNumeric.GetLength();
3514 int dot_index = wsNumeric.Find('.');
3515 if (dot_index == -1) {
3516 dot_index = len;
3517 }
3518 ccf = dot_index_f - 1;
3519 cc = dot_index - 1;
3520 while (ccf >= 0) {
3521 switch (strf[ccf]) {
3522 case '9':
3523 if (cc >= 0) {
3524 wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
3525 cc--;
3526 } else {
3527 wsOutput = CFX_WideStringC(L'0') + wsOutput;
3528 }
3529 ccf--;
3530 break;
3531 case 'z':
3532 if (cc >= 0) {
3533 if (lcNum.m_Integral != 0) {
3534 wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
3535 }
3536 cc--;
3537 }
3538 ccf--;
3539 break;
3540 case 'Z':
3541 if (cc >= 0) {
3542 if (lcNum.m_Integral == 0) {
3543 wsOutput = CFX_WideStringC(L' ') + wsOutput;
3544 } else {
3545 wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
3546 }
3547 cc--;
3548 } else {
3549 wsOutput = CFX_WideStringC(L' ') + wsOutput;
3550 }
3551 ccf--;
3552 break;
3553 case 'S':
3554 if (bNeg) {
3555 CFX_WideString wsMinusSymbol;
3556 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
3557 wsOutput = wsMinusSymbol + wsOutput;
3558 bAddNeg = TRUE;
3559 } else {
3560 wsOutput = CFX_WideStringC(L' ') + wsOutput;
3561 }
3562 ccf--;
3563 break;
3564 case 's':
3565 if (bNeg) {
3566 CFX_WideString wsMinusSymbol;
3567 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
3568 wsOutput = wsMinusSymbol + wsOutput;
3569 bAddNeg = TRUE;
3570 }
3571 ccf--;
3572 break;
3573 case 'E': {
3574 CFX_WideString wsExp;
3575 wsExp.Format(L"E%+d", exponent);
3576 wsOutput = wsExp + wsOutput;
3577 }
3578 ccf--;
3579 break;
3580 case '$': {
3581 CFX_WideString wsSymbol;
3582 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
3583 wsOutput = wsSymbol + wsOutput;
3584 }
3585 ccf--;
3586 break;
3587 case 'r':
3588 if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
3589 if (bNeg) {
3590 wsOutput = L"CR" + wsOutput;
3591 }
3592 ccf -= 2;
3593 bAddNeg = TRUE;
3594 }
3595 break;
3596 case 'R':
3597 if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
3598 if (bNeg) {
3599 wsOutput = L"CR" + wsOutput;
3600 } else {
3601 wsOutput = L" " + wsOutput;
3602 }
3603 ccf -= 2;
3604 bAddNeg = TRUE;
3605 }
3606 break;
3607 case 'b':
3608 if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
3609 if (bNeg) {
3610 wsOutput = L"db" + wsOutput;
3611 }
3612 ccf -= 2;
3613 bAddNeg = TRUE;
3614 }
3615 break;
3616 case 'B':
3617 if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
3618 if (bNeg) {
3619 wsOutput = L"DB" + wsOutput;
3620 } else {
3621 wsOutput = L" " + wsOutput;
3622 }
3623 ccf -= 2;
3624 bAddNeg = TRUE;
3625 }
3626 break;
3627 case '%': {
3628 CFX_WideString wsSymbol;
3629 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
3630 wsOutput = wsSymbol + wsOutput;
3631 }
3632 ccf--;
3633 break;
3634 case ',':
3635 if (cc >= 0) {
3636 wsOutput = wsGroupSymbol + wsOutput;
3637 }
3638 ccf--;
3639 break;
3640 case '(':
3641 if (bNeg) {
3642 wsOutput = L"(" + wsOutput;
3643 } else {
3644 wsOutput = L" " + wsOutput;
3645 }
3646 bAddNeg = TRUE;
3647 ccf--;
3648 break;
3649 case ')':
3650 if (bNeg) {
3651 wsOutput = L")" + wsOutput;
3652 } else {
3653 wsOutput = L" " + wsOutput;
3654 }
3655 ccf--;
3656 break;
3657 case '\'':
3658 wsOutput = FX_GetLiteralTextReverse(strf, ccf) + wsOutput;
3659 ccf--;
3660 break;
3661 default:
3662 wsOutput = CFX_WideStringC(strf[ccf]) + wsOutput;
3663 ccf--;
3664 }
3665 }
3666 if (cc >= 0) {
3667 int nPos = dot_index % 3;
3668 wsOutput.Empty();
3669 for (int32_t i = 0; i < dot_index; i++) {
3670 if (i % 3 == nPos && i != 0) {
3671 wsOutput += wsGroupSymbol;
3672 }
3673 wsOutput += wsNumeric[i];
3674 }
3675 if (dot_index < len) {
3676 CFX_WideString wsSymbol;
3677 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsSymbol);
3678 wsOutput += wsSymbol;
3679 wsOutput += wsNumeric.Right(len - dot_index - 1);
3680 }
3681 if (bNeg) {
3682 CFX_WideString wsMinusymbol;
3683 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
3684 wsOutput = wsMinusymbol + wsOutput;
3685 }
3686 return FALSE;
3687 }
3688 if (dot_index_f == wsNumFormat.GetLength()) {
3689 if (!bAddNeg && bNeg) {
3690 CFX_WideString wsMinusymbol;
3691 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
3692 wsOutput = wsMinusymbol + wsOutput;
3693 }
3694 return TRUE;
3695 }
3696 CFX_WideString wsDotSymbol;
3697 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
3698 if (strf[dot_index_f] == 'V') {
3699 wsOutput += wsDotSymbol;
3700 } else if (strf[dot_index_f] == '.') {
3701 if (dot_index < len) {
3702 wsOutput += wsDotSymbol;
3703 } else {
3704 if (strf[dot_index_f + 1] == '9' || strf[dot_index_f + 1] == 'Z') {
3705 wsOutput += wsDotSymbol;
3706 }
3707 }
3708 }
3709 ccf = dot_index_f + 1;
3710 cc = dot_index + 1;
3711 while (ccf < lenf) {
3712 switch (strf[ccf]) {
3713 case '\'':
3714 wsOutput += FX_GetLiteralText(strf, ccf, lenf);
3715 ccf++;
3716 break;
3717 case '9':
3718 if (cc < len) {
3719 wsOutput += str[cc];
3720 cc++;
3721 } else {
3722 wsOutput += L'0';
3723 }
3724 ccf++;
3725 break;
3726 case 'z':
3727 if (cc < len) {
3728 wsOutput += str[cc];
3729 cc++;
3730 }
3731 ccf++;
3732 break;
3733 case 'Z':
3734 if (cc < len) {
3735 wsOutput += str[cc];
3736 cc++;
3737 } else {
3738 wsOutput += L'0';
3739 }
3740 ccf++;
3741 break;
3742 case 'E': {
3743 CFX_WideString wsExp;
3744 wsExp.Format(L"E%+d", exponent);
3745 wsOutput += wsExp;
3746 }
3747 ccf++;
3748 break;
3749 case '$': {
3750 CFX_WideString wsSymbol;
3751 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
3752 wsOutput += wsSymbol;
3753 }
3754 ccf++;
3755 break;
3756 case 'c':
3757 if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
3758 if (bNeg) {
3759 wsOutput += L"CR";
3760 }
3761 ccf += 2;
3762 bAddNeg = TRUE;
3763 }
3764 break;
3765 case 'C':
3766 if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
3767 if (bNeg) {
3768 wsOutput += L"CR";
3769 } else {
3770 wsOutput += L" ";
3771 }
3772 ccf += 2;
3773 bAddNeg = TRUE;
3774 }
3775 break;
3776 case 'd':
3777 if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
3778 if (bNeg) {
3779 wsOutput += L"db";
3780 }
3781 ccf += 2;
3782 bAddNeg = TRUE;
3783 }
3784 break;
3785 case 'D':
3786 if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
3787 if (bNeg) {
3788 wsOutput += L"DB";
3789 } else {
3790 wsOutput += L" ";
3791 }
3792 ccf += 2;
3793 bAddNeg = TRUE;
3794 }
3795 break;
3796 case '%': {
3797 CFX_WideString wsSymbol;
3798 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
3799 wsOutput += wsSymbol;
3800 }
3801 ccf++;
3802 break;
3803 case '8': {
3804 while (ccf < lenf && strf[ccf] == '8') {
3805 ccf++;
3806 }
3807 while (cc < len && FX_IsDigit(str[cc])) {
3808 wsOutput += str[cc];
3809 cc++;
3810 }
3811 } break;
3812 case ',':
3813 wsOutput += wsGroupSymbol;
3814 ccf++;
3815 break;
3816 case '(':
3817 if (bNeg) {
3818 wsOutput += '(';
3819 } else {
3820 wsOutput += ' ';
3821 }
3822 bAddNeg = TRUE;
3823 ccf++;
3824 break;
3825 case ')':
3826 if (bNeg) {
3827 wsOutput += ')';
3828 } else {
3829 wsOutput += ' ';
3830 }
3831 ccf++;
3832 break;
3833 default:
3834 ccf++;
3835 }
3836 }
3837 if (!bAddNeg && bNeg) {
3838 CFX_WideString wsMinusymbol;
3839 pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
3840 wsOutput =
3841 wsOutput[0] + wsMinusymbol + wsOutput.Mid(1, wsOutput.GetLength() - 1);
3842 }
3843 return TRUE;
3844 }
FormatNum(const CFX_WideString & wsSrcNum,const CFX_WideString & wsPattern,CFX_WideString & wsOutput)3845 FX_BOOL CFX_FormatString::FormatNum(const CFX_WideString& wsSrcNum,
3846 const CFX_WideString& wsPattern,
3847 CFX_WideString& wsOutput) {
3848 if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) {
3849 return FALSE;
3850 }
3851 return FormatStrNum(wsSrcNum, wsPattern, wsOutput);
3852 }
FormatNum(FX_FLOAT fNum,const CFX_WideString & wsPattern,CFX_WideString & wsOutput)3853 FX_BOOL CFX_FormatString::FormatNum(FX_FLOAT fNum,
3854 const CFX_WideString& wsPattern,
3855 CFX_WideString& wsOutput) {
3856 if (wsPattern.IsEmpty()) {
3857 return FALSE;
3858 }
3859 CFX_LCNumeric lcNum(fNum);
3860 return FormatLCNumeric(lcNum, wsPattern, wsOutput);
3861 }
FX_DateFromCanonical(const CFX_WideString & wsDate,CFX_Unitime & datetime)3862 FX_BOOL FX_DateFromCanonical(const CFX_WideString& wsDate,
3863 CFX_Unitime& datetime) {
3864 int32_t year = 1900;
3865 int32_t month = 1;
3866 int32_t day = 1;
3867 FX_WORD wYear = 0;
3868 int cc_start = 0, cc = 0;
3869 const FX_WCHAR* str = (const FX_WCHAR*)wsDate;
3870 int len = wsDate.GetLength();
3871 if (len > 10) {
3872 return FALSE;
3873 }
3874 while (cc < len && cc < 4) {
3875 if (!FX_IsDigit(str[cc])) {
3876 return FALSE;
3877 }
3878 wYear = wYear * 10 + str[cc++] - '0';
3879 }
3880 year = wYear;
3881 if (cc < 4 || wYear < 1900) {
3882 return FALSE;
3883 }
3884 if (cc < len) {
3885 if (str[cc] == '-') {
3886 cc++;
3887 }
3888 cc_start = cc;
3889 uint8_t tmpM = 0;
3890 while (cc < len && cc < cc_start + 2) {
3891 if (!FX_IsDigit(str[cc])) {
3892 return FALSE;
3893 }
3894 tmpM = tmpM * 10 + str[cc++] - '0';
3895 }
3896 month = tmpM;
3897 if (cc == cc_start + 1 || tmpM > 12 || tmpM < 1) {
3898 return FALSE;
3899 }
3900 if (cc < len) {
3901 if (str[cc] == '-') {
3902 cc++;
3903 }
3904 uint8_t tmpD = 0;
3905 cc_start = cc;
3906 while (cc < len && cc < cc_start + 2) {
3907 if (!FX_IsDigit(str[cc])) {
3908 return FALSE;
3909 }
3910 tmpD = tmpD * 10 + str[cc++] - '0';
3911 }
3912 day = tmpD;
3913 if (tmpD < 1) {
3914 return FALSE;
3915 }
3916 if ((tmpM == 1 || tmpM == 3 || tmpM == 5 || tmpM == 7 || tmpM == 8 ||
3917 tmpM == 10 || tmpM == 12) &&
3918 tmpD > 31) {
3919 return FALSE;
3920 }
3921 if ((tmpM == 4 || tmpM == 6 || tmpM == 9 || tmpM == 11) && tmpD > 30) {
3922 return FALSE;
3923 }
3924 FX_BOOL iLeapYear;
3925 if ((wYear % 4 == 0 && wYear % 100 != 0) || wYear % 400 == 0) {
3926 iLeapYear = TRUE;
3927 } else {
3928 iLeapYear = FALSE;
3929 }
3930 if ((iLeapYear && tmpM == 2 && tmpD > 29) ||
3931 (!iLeapYear && tmpM == 2 && tmpD > 28)) {
3932 return FALSE;
3933 }
3934 }
3935 }
3936 CFX_Unitime ut;
3937 ut.Set(year, month, day);
3938 datetime = datetime + ut;
3939 return TRUE;
3940 }
FX_TimeFromCanonical(const CFX_WideStringC & wsTime,CFX_Unitime & datetime,IFX_Locale * pLocale)3941 FX_BOOL FX_TimeFromCanonical(const CFX_WideStringC& wsTime,
3942 CFX_Unitime& datetime,
3943 IFX_Locale* pLocale) {
3944 if (wsTime.GetLength() == 0) {
3945 return FALSE;
3946 }
3947 uint8_t hour = 0;
3948 uint8_t minute = 0;
3949 uint8_t second = 0;
3950 FX_WORD millisecond = 0;
3951 int cc_start = 0, cc = cc_start;
3952 const FX_WCHAR* str = (const FX_WCHAR*)wsTime.GetPtr();
3953 int len = wsTime.GetLength();
3954 while (cc < len && cc < 2) {
3955 if (!FX_IsDigit(str[cc])) {
3956 return FALSE;
3957 }
3958 hour = hour * 10 + str[cc++] - '0';
3959 }
3960 if (cc < 2 || hour >= 24) {
3961 return FALSE;
3962 }
3963 if (cc < len) {
3964 if (str[cc] == ':') {
3965 cc++;
3966 }
3967 cc_start = cc;
3968 while (cc < len && cc < cc_start + 2) {
3969 if (!FX_IsDigit(str[cc])) {
3970 return FALSE;
3971 }
3972 minute = minute * 10 + str[cc++] - '0';
3973 }
3974 if (cc == cc_start + 1 || minute >= 60) {
3975 return FALSE;
3976 }
3977 if (cc < len) {
3978 if (str[cc] == ':') {
3979 cc++;
3980 }
3981 cc_start = cc;
3982 while (cc < len && cc < cc_start + 2) {
3983 if (!FX_IsDigit(str[cc])) {
3984 return FALSE;
3985 }
3986 second = second * 10 + str[cc++] - '0';
3987 }
3988 if (cc == cc_start + 1 || second >= 60) {
3989 return FALSE;
3990 }
3991 if (cc < len) {
3992 if (str[cc] == '.') {
3993 cc++;
3994 cc_start = cc;
3995 while (cc < len && cc < cc_start + 3) {
3996 if (!FX_IsDigit(str[cc])) {
3997 return FALSE;
3998 }
3999 millisecond = millisecond * 10 + str[cc++] - '0';
4000 }
4001 if (cc < cc_start + 3 || millisecond >= 1000) {
4002 return FALSE;
4003 }
4004 }
4005 if (cc < len) {
4006 FX_TIMEZONE tzDiff;
4007 tzDiff.tzHour = 0;
4008 tzDiff.tzMinute = 0;
4009 if (str[cc] != 'Z') {
4010 cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff);
4011 }
4012 FX_ResolveZone(hour, minute, tzDiff, pLocale);
4013 }
4014 }
4015 }
4016 }
4017 CFX_Unitime ut;
4018 ut.Set(0, 0, 0, hour, minute, second, millisecond);
4019 datetime = datetime + ut;
4020 return TRUE;
4021 }
FX_GetSolarMonthDays(FX_WORD year,FX_WORD month)4022 static FX_WORD FX_GetSolarMonthDays(FX_WORD year, FX_WORD month) {
4023 if (month % 2) {
4024 return 31;
4025 } else if (month == 2) {
4026 return FX_IsLeapYear(year) ? 29 : 28;
4027 }
4028 return 30;
4029 }
FX_GetWeekDay(FX_WORD year,FX_WORD month,FX_WORD day)4030 static FX_WORD FX_GetWeekDay(FX_WORD year, FX_WORD month, FX_WORD day) {
4031 FX_WORD g_month_day[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
4032 FX_WORD nDays =
4033 (year - 1) % 7 + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
4034 nDays += g_month_day[month - 1] + day;
4035 if (FX_IsLeapYear(year) && month > 2) {
4036 nDays++;
4037 }
4038 return nDays % 7;
4039 }
FX_GetWeekOfMonth(FX_WORD year,FX_WORD month,FX_WORD day)4040 static FX_WORD FX_GetWeekOfMonth(FX_WORD year, FX_WORD month, FX_WORD day) {
4041 FX_WORD week_day = FX_GetWeekDay(year, month, 1);
4042 FX_WORD week_index = 0;
4043 week_index += day / 7;
4044 day = day % 7;
4045 if (week_day + day > 7) {
4046 week_index++;
4047 }
4048 return week_index;
4049 }
FX_GetWeekOfYear(FX_WORD year,FX_WORD month,FX_WORD day)4050 static FX_WORD FX_GetWeekOfYear(FX_WORD year, FX_WORD month, FX_WORD day) {
4051 FX_WORD nDays = 0;
4052 for (FX_WORD i = 1; i < month; i++) {
4053 nDays += FX_GetSolarMonthDays(year, i);
4054 }
4055 nDays += day;
4056 FX_WORD week_day = FX_GetWeekDay(year, 1, 1);
4057 FX_WORD week_index = 1;
4058 week_index += nDays / 7;
4059 nDays = nDays % 7;
4060 if (week_day + nDays > 7) {
4061 week_index++;
4062 }
4063 return week_index;
4064 }
FX_DateFormat(const CFX_WideString & wsDatePattern,IFX_Locale * pLocale,const CFX_Unitime & datetime,CFX_WideString & wsResult)4065 static FX_BOOL FX_DateFormat(const CFX_WideString& wsDatePattern,
4066 IFX_Locale* pLocale,
4067 const CFX_Unitime& datetime,
4068 CFX_WideString& wsResult) {
4069 FX_BOOL bRet = TRUE;
4070 int32_t year = datetime.GetYear();
4071 uint8_t month = datetime.GetMonth();
4072 uint8_t day = datetime.GetDay();
4073 int32_t ccf = 0;
4074 const FX_WCHAR* strf = (const FX_WCHAR*)wsDatePattern;
4075 int32_t lenf = wsDatePattern.GetLength();
4076 while (ccf < lenf) {
4077 if (strf[ccf] == '\'') {
4078 wsResult += FX_GetLiteralText(strf, ccf, lenf);
4079 ccf++;
4080 continue;
4081 } else if (FX_Local_Find(gs_wsDateSymbols, strf[ccf]) < 0) {
4082 wsResult += strf[ccf++];
4083 continue;
4084 }
4085 FX_DWORD dwSymbolNum = 1;
4086 FX_DWORD dwSymbol = strf[ccf++];
4087 while (ccf < lenf && strf[ccf] == dwSymbol) {
4088 ccf++;
4089 dwSymbolNum++;
4090 }
4091 dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
4092 if (dwSymbol == FXBSTR_ID(0, 0, 'D', '1')) {
4093 CFX_WideString wsDay;
4094 wsDay.Format(L"%d", day);
4095 wsResult += wsDay;
4096 } else if (dwSymbol == FXBSTR_ID(0, 0, 'D', '2')) {
4097 CFX_WideString wsDay;
4098 wsDay.Format(L"%02d", day);
4099 wsResult += wsDay;
4100 } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '1')) {
4101 FX_WORD nDays = 0;
4102 for (int i = 1; i < month; i++) {
4103 nDays += FX_GetSolarMonthDays(year, i);
4104 }
4105 nDays += day;
4106 CFX_WideString wsDays;
4107 wsDays.Format(L"%d", nDays);
4108 wsResult += wsDays;
4109 } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '3')) {
4110 FX_WORD nDays = 0;
4111 for (int i = 1; i < month; i++) {
4112 nDays += FX_GetSolarMonthDays(year, i);
4113 }
4114 nDays += day;
4115 CFX_WideString wsDays;
4116 wsDays.Format(L"%03d", nDays);
4117 wsResult += wsDays;
4118 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
4119 CFX_WideString wsMonth;
4120 wsMonth.Format(L"%d", month);
4121 wsResult += wsMonth;
4122 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
4123 CFX_WideString wsMonth;
4124 wsMonth.Format(L"%02d", month);
4125 wsResult += wsMonth;
4126 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '3')) {
4127 CFX_WideString wsTemp;
4128 pLocale->GetMonthName(month - 1, wsTemp, TRUE);
4129 wsResult += wsTemp;
4130 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '4')) {
4131 CFX_WideString wsTemp;
4132 pLocale->GetMonthName(month - 1, wsTemp, FALSE);
4133 wsResult += wsTemp;
4134 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '1')) {
4135 FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
4136 CFX_WideString wsWeekDay;
4137 wsWeekDay.Format(L"%d", wWeekDay + 1);
4138 wsResult += wsWeekDay;
4139 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '3')) {
4140 FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
4141 CFX_WideString wsTemp;
4142 pLocale->GetDayName(wWeekDay, wsTemp, TRUE);
4143 wsResult += wsTemp;
4144 } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '4')) {
4145 FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
4146 if (pLocale) {
4147 CFX_WideString wsTemp;
4148 pLocale->GetDayName(wWeekDay, wsTemp, FALSE);
4149 wsResult += wsTemp;
4150 }
4151 } else if (dwSymbol == FXBSTR_ID(0, 0, 'e', '1')) {
4152 FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
4153 CFX_WideString wsWeekDay;
4154 wsWeekDay.Format(L"%d", wWeekDay ? wWeekDay : 7);
4155 wsResult += wsWeekDay;
4156 } else if (dwSymbol == FXBSTR_ID(0, 0, 'G', '1')) {
4157 CFX_WideString wsTemp;
4158 pLocale->GetEraName(wsTemp, year < 0);
4159 wsResult += wsTemp;
4160 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '2')) {
4161 CFX_WideString wsYear;
4162 wsYear.Format(L"%02d", year % 100);
4163 wsResult += wsYear;
4164 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '4')) {
4165 CFX_WideString wsYear;
4166 wsYear.Format(L"%d", year);
4167 wsResult += wsYear;
4168 } else if (dwSymbol == FXBSTR_ID(0, 0, 'w', '1')) {
4169 FX_WORD week_index = FX_GetWeekOfMonth(year, month, day);
4170 CFX_WideString wsWeekInMonth;
4171 wsWeekInMonth.Format(L"%d", week_index);
4172 wsResult += wsWeekInMonth;
4173 } else if (dwSymbol == FXBSTR_ID(0, 0, 'W', '2')) {
4174 FX_WORD week_index = FX_GetWeekOfYear(year, month, day);
4175 CFX_WideString wsWeekInYear;
4176 wsWeekInYear.Format(L"%02d", week_index);
4177 wsResult += wsWeekInYear;
4178 }
4179 }
4180 return bRet;
4181 }
FX_TimeFormat(const CFX_WideString & wsTimePattern,IFX_Locale * pLocale,const CFX_Unitime & datetime,CFX_WideString & wsResult)4182 static FX_BOOL FX_TimeFormat(const CFX_WideString& wsTimePattern,
4183 IFX_Locale* pLocale,
4184 const CFX_Unitime& datetime,
4185 CFX_WideString& wsResult) {
4186 FX_BOOL bGMT = FALSE;
4187 FX_BOOL bRet = TRUE;
4188 uint8_t hour = datetime.GetHour();
4189 uint8_t minute = datetime.GetMinute();
4190 uint8_t second = datetime.GetSecond();
4191 FX_WORD millisecond = datetime.GetMillisecond();
4192 int32_t ccf = 0;
4193 const FX_WCHAR* strf = (const FX_WCHAR*)wsTimePattern;
4194 int32_t lenf = wsTimePattern.GetLength();
4195 FX_WORD wHour = hour;
4196 FX_BOOL bPM = FALSE;
4197 if (wsTimePattern.Find('A') != -1) {
4198 if (wHour >= 12) {
4199 bPM = TRUE;
4200 }
4201 }
4202 while (ccf < lenf) {
4203 if (strf[ccf] == '\'') {
4204 wsResult += FX_GetLiteralText(strf, ccf, lenf);
4205 ccf++;
4206 continue;
4207 } else if (FX_Local_Find(gs_wsTimeSymbols, strf[ccf]) < 0) {
4208 wsResult += strf[ccf++];
4209 continue;
4210 }
4211 FX_DWORD dwSymbolNum = 1;
4212 FX_DWORD dwSymbol = strf[ccf++];
4213 while (ccf < lenf && strf[ccf] == dwSymbol) {
4214 ccf++;
4215 dwSymbolNum++;
4216 }
4217 dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
4218 if (dwSymbol == FXBSTR_ID(0, 0, 'h', '1')) {
4219 if (wHour > 12) {
4220 wHour -= 12;
4221 }
4222 CFX_WideString wsHour;
4223 wsHour.Format(L"%d", wHour == 0 ? 12 : wHour);
4224 wsResult += wsHour;
4225 } else if (dwSymbol == FXBSTR_ID(0, 0, 'h', '2')) {
4226 if (wHour > 12) {
4227 wHour -= 12;
4228 }
4229 CFX_WideString wsHour;
4230 wsHour.Format(L"%02d", wHour == 0 ? 12 : wHour);
4231 wsResult += wsHour;
4232 } else if (dwSymbol == FXBSTR_ID(0, 0, 'K', '1')) {
4233 CFX_WideString wsHour;
4234 wsHour.Format(L"%d", wHour == 0 ? 24 : wHour);
4235 wsResult += wsHour;
4236 } else if (dwSymbol == FXBSTR_ID(0, 0, 'K', '2')) {
4237 CFX_WideString wsHour;
4238 wsHour.Format(L"%02d", wHour == 0 ? 24 : wHour);
4239 wsResult += wsHour;
4240 } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '1')) {
4241 if (wHour > 12) {
4242 wHour -= 12;
4243 }
4244 CFX_WideString wsHour;
4245 wsHour.Format(L"%d", wHour);
4246 wsResult += wsHour;
4247 } else if (dwSymbol == FXBSTR_ID(0, 0, 'H', '1')) {
4248 CFX_WideString wsHour;
4249 wsHour.Format(L"%d", wHour);
4250 wsResult += wsHour;
4251 } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '2')) {
4252 if (wHour > 12) {
4253 wHour -= 12;
4254 }
4255 CFX_WideString wsHour;
4256 wsHour.Format(L"%02d", wHour);
4257 wsResult += wsHour;
4258 } else if (dwSymbol == FXBSTR_ID(0, 0, 'H', '2')) {
4259 CFX_WideString wsHour;
4260 wsHour.Format(L"%02d", wHour);
4261 wsResult += wsHour;
4262 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
4263 CFX_WideString wsMinute;
4264 wsMinute.Format(L"%d", minute);
4265 wsResult += wsMinute;
4266 } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
4267 CFX_WideString wsMinute;
4268 wsMinute.Format(L"%02d", minute);
4269 wsResult += wsMinute;
4270 } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '1')) {
4271 CFX_WideString wsSecond;
4272 wsSecond.Format(L"%d", second);
4273 wsResult += wsSecond;
4274 } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '2')) {
4275 CFX_WideString wsSecond;
4276 wsSecond.Format(L"%02d", second);
4277 wsResult += wsSecond;
4278 } else if (dwSymbol == FXBSTR_ID(0, 0, 'F', '3')) {
4279 CFX_WideString wsMilliseconds;
4280 wsMilliseconds.Format(L"%03d", millisecond);
4281 wsResult += wsMilliseconds;
4282 } else if (dwSymbol == FXBSTR_ID(0, 0, 'A', '1')) {
4283 CFX_WideString wsMeridiem;
4284 pLocale->GetMeridiemName(wsMeridiem, !bPM);
4285 wsResult += wsMeridiem;
4286 } else if (dwSymbol == FXBSTR_ID(0, 0, 'Z', '1')) {
4287 wsResult += FX_WSTRC(L"GMT");
4288 FX_TIMEZONE tz;
4289 pLocale->GetTimeZone(tz);
4290 if (!bGMT && (tz.tzHour != 0 || tz.tzMinute != 0)) {
4291 if (tz.tzHour < 0) {
4292 wsResult += FX_WSTRC(L"-");
4293 } else {
4294 wsResult += FX_WSTRC(L"+");
4295 }
4296 CFX_WideString wsTimezone;
4297 wsTimezone.Format(L"%02d:%02d", FXSYS_abs(tz.tzHour), tz.tzMinute);
4298 wsResult += wsTimezone;
4299 }
4300 } else if (dwSymbol == FXBSTR_ID(0, 0, 'z', '1')) {
4301 FX_TIMEZONE tz;
4302 pLocale->GetTimeZone(tz);
4303 if (!bGMT && tz.tzHour != 0 && tz.tzMinute != 0) {
4304 if (tz.tzHour < 0) {
4305 wsResult += FX_WSTRC(L"-");
4306 } else {
4307 wsResult += FX_WSTRC(L"+");
4308 }
4309 CFX_WideString wsTimezone;
4310 wsTimezone.Format(L"%02d:%02d", FXSYS_abs(tz.tzHour), tz.tzMinute);
4311 wsResult += wsTimezone;
4312 }
4313 }
4314 }
4315 return bRet;
4316 }
FX_FormatDateTime(const CFX_Unitime & dt,const CFX_WideString & wsDatePattern,const CFX_WideString & wsTimePattern,FX_BOOL bDateFirst,IFX_Locale * pLocale,CFX_WideString & wsOutput)4317 static FX_BOOL FX_FormatDateTime(const CFX_Unitime& dt,
4318 const CFX_WideString& wsDatePattern,
4319 const CFX_WideString& wsTimePattern,
4320 FX_BOOL bDateFirst,
4321 IFX_Locale* pLocale,
4322 CFX_WideString& wsOutput) {
4323 FX_BOOL bRet = TRUE;
4324 CFX_WideString wsDateOut, wsTimeOut;
4325 if (!wsDatePattern.IsEmpty()) {
4326 bRet &= FX_DateFormat(wsDatePattern, pLocale, dt, wsDateOut);
4327 }
4328 if (!wsTimePattern.IsEmpty()) {
4329 bRet &= FX_TimeFormat(wsTimePattern, pLocale, dt, wsTimeOut);
4330 }
4331 wsOutput = bDateFirst ? wsDateOut + wsTimeOut : wsTimeOut + wsDateOut;
4332 return bRet;
4333 }
FormatDateTime(const CFX_WideString & wsSrcDateTime,const CFX_WideString & wsPattern,CFX_WideString & wsOutput)4334 FX_BOOL CFX_FormatString::FormatDateTime(const CFX_WideString& wsSrcDateTime,
4335 const CFX_WideString& wsPattern,
4336 CFX_WideString& wsOutput) {
4337 if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) {
4338 return FALSE;
4339 }
4340 CFX_WideString wsDatePattern, wsTimePattern;
4341 IFX_Locale* pLocale = NULL;
4342 FX_DATETIMETYPE eCategory =
4343 GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
4344 if (pLocale == NULL || eCategory == FX_DATETIMETYPE_Unknown) {
4345 return FALSE;
4346 }
4347 CFX_Unitime dt(0);
4348 int32_t iT = wsSrcDateTime.Find(L"T");
4349 if (iT < 0) {
4350 if (eCategory == FX_DATETIMETYPE_Date) {
4351 FX_DateFromCanonical(wsSrcDateTime, dt);
4352 } else if (eCategory == FX_DATETIMETYPE_Time) {
4353 FX_TimeFromCanonical(wsSrcDateTime, dt, pLocale);
4354 }
4355 } else {
4356 FX_DateFromCanonical(wsSrcDateTime.Left(iT), dt);
4357 FX_TimeFromCanonical(
4358 wsSrcDateTime.Right(wsSrcDateTime.GetLength() - iT - 1), dt, pLocale);
4359 }
4360 return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern,
4361 eCategory != FX_DATETIMETYPE_TimeDate, pLocale,
4362 wsOutput);
4363 }
FormatDateTime(const CFX_WideString & wsSrcDateTime,const CFX_WideString & wsPattern,CFX_WideString & wsOutput,FX_DATETIMETYPE eDateTimeType)4364 FX_BOOL CFX_FormatString::FormatDateTime(const CFX_WideString& wsSrcDateTime,
4365 const CFX_WideString& wsPattern,
4366 CFX_WideString& wsOutput,
4367 FX_DATETIMETYPE eDateTimeType) {
4368 if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) {
4369 return FALSE;
4370 }
4371 CFX_WideString wsDatePattern, wsTimePattern;
4372 IFX_Locale* pLocale = NULL;
4373 FX_DATETIMETYPE eCategory =
4374 GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
4375 if (!pLocale) {
4376 return FALSE;
4377 }
4378 if (eCategory == FX_DATETIMETYPE_Unknown) {
4379 if (eDateTimeType == FX_DATETIMETYPE_Time) {
4380 wsTimePattern = wsDatePattern;
4381 wsDatePattern.Empty();
4382 }
4383 eCategory = eDateTimeType;
4384 }
4385 if (eCategory == FX_DATETIMETYPE_Unknown) {
4386 return FALSE;
4387 }
4388 CFX_Unitime dt(0);
4389 int32_t iT = wsSrcDateTime.Find(L"T");
4390 if (iT < 0) {
4391 if (eCategory == FX_DATETIMETYPE_Date &&
4392 FX_DateFromCanonical(wsSrcDateTime, dt)) {
4393 return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, TRUE, pLocale,
4394 wsOutput);
4395 } else if (eCategory == FX_DATETIMETYPE_Time &&
4396 FX_TimeFromCanonical(wsSrcDateTime, dt, pLocale)) {
4397 return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, TRUE, pLocale,
4398 wsOutput);
4399 }
4400 } else {
4401 CFX_WideStringC wsSrcDate((const FX_WCHAR*)wsSrcDateTime, iT);
4402 CFX_WideStringC wsSrcTime((const FX_WCHAR*)wsSrcDateTime + iT + 1,
4403 wsSrcDateTime.GetLength() - iT - 1);
4404 if (wsSrcDate.IsEmpty() || wsSrcTime.IsEmpty()) {
4405 return FALSE;
4406 }
4407 if (FX_DateFromCanonical(wsSrcDate, dt) &&
4408 FX_TimeFromCanonical(wsSrcTime, dt, pLocale)) {
4409 return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern,
4410 eCategory != FX_DATETIMETYPE_TimeDate, pLocale,
4411 wsOutput);
4412 }
4413 }
4414 return FALSE;
4415 }
FormatDateTime(const CFX_Unitime & dt,const CFX_WideString & wsPattern,CFX_WideString & wsOutput)4416 FX_BOOL CFX_FormatString::FormatDateTime(const CFX_Unitime& dt,
4417 const CFX_WideString& wsPattern,
4418 CFX_WideString& wsOutput) {
4419 if (wsPattern.IsEmpty()) {
4420 return FALSE;
4421 }
4422 CFX_WideString wsDatePattern, wsTimePattern;
4423 IFX_Locale* pLocale = NULL;
4424 FX_DATETIMETYPE eCategory =
4425 GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
4426 if (!pLocale) {
4427 return FALSE;
4428 }
4429 return FX_FormatDateTime(dt, wsPattern, wsTimePattern,
4430 eCategory != FX_DATETIMETYPE_TimeDate, pLocale,
4431 wsOutput);
4432 }
FormatZero(const CFX_WideString & wsPattern,CFX_WideString & wsOutput)4433 FX_BOOL CFX_FormatString::FormatZero(const CFX_WideString& wsPattern,
4434 CFX_WideString& wsOutput) {
4435 if (wsPattern.IsEmpty()) {
4436 return FALSE;
4437 }
4438 CFX_WideString wsTextFormat;
4439 GetTextFormat(wsPattern, FX_WSTRC(L"zero"), wsTextFormat);
4440 int32_t iPattern = 0;
4441 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
4442 int32_t iLenPattern = wsTextFormat.GetLength();
4443 while (iPattern < iLenPattern) {
4444 if (pStrPattern[iPattern] == '\'') {
4445 wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
4446 iPattern++;
4447 continue;
4448 } else {
4449 wsOutput += pStrPattern[iPattern++];
4450 continue;
4451 }
4452 }
4453 return TRUE;
4454 }
FormatNull(const CFX_WideString & wsPattern,CFX_WideString & wsOutput)4455 FX_BOOL CFX_FormatString::FormatNull(const CFX_WideString& wsPattern,
4456 CFX_WideString& wsOutput) {
4457 if (wsPattern.IsEmpty()) {
4458 return FALSE;
4459 }
4460 CFX_WideString wsTextFormat;
4461 GetTextFormat(wsPattern, FX_WSTRC(L"null"), wsTextFormat);
4462 int32_t iPattern = 0;
4463 const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
4464 int32_t iLenPattern = wsTextFormat.GetLength();
4465 while (iPattern < iLenPattern) {
4466 if (pStrPattern[iPattern] == '\'') {
4467 wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
4468 iPattern++;
4469 continue;
4470 } else {
4471 wsOutput += pStrPattern[iPattern++];
4472 continue;
4473 }
4474 }
4475 return TRUE;
4476 }
GetPatternLocale(const CFX_WideStringC & wsLocale)4477 IFX_Locale* CFX_FormatString::GetPatternLocale(
4478 const CFX_WideStringC& wsLocale) {
4479 if (m_bUseLCID) {
4480 }
4481 return m_pLocaleMgr->GetLocaleByName(wsLocale);
4482 }
4483 #define FXMATH_DECIMAL_SCALELIMIT 0x1c
4484 #define FXMATH_DECIMAL_NEGMASK (0x80000000L)
4485 #define FXMATH_DECIMAL_FORCEBOOL(x) (!(!(x)))
4486 #define FXMATH_DECIMAL_MAKEFLAGS(NEG, SCALE) \
4487 (((SCALE) << 0x10) | ((NEG) ? FXMATH_DECIMAL_NEGMASK : 0))
4488 #define FXMATH_DECIMAL_FLAGS2NEG(FLAGS) \
4489 FXMATH_DECIMAL_FORCEBOOL((FLAGS)&FXMATH_DECIMAL_NEGMASK)
4490 #define FXMATH_DECIMAL_FLAGS2SCALE(FLAGS) \
4491 ((uint8_t)(((FLAGS) & ~FXMATH_DECIMAL_NEGMASK) >> 0x10))
4492 #define FXMATH_DECIMAL_RSHIFT32BIT(x) ((x) >> 0x10 >> 0x10)
4493 #define FXMATH_DECIMAL_LSHIFT32BIT(x) ((x) << 0x10 << 0x10)
fxmath_decimal_helper_div10(uint64_t & phi,uint64_t & pmid,uint64_t & plo)4494 static inline uint8_t fxmath_decimal_helper_div10(uint64_t& phi,
4495 uint64_t& pmid,
4496 uint64_t& plo) {
4497 uint8_t retVal;
4498 pmid += FXMATH_DECIMAL_LSHIFT32BIT(phi % 0xA);
4499 phi /= 0xA;
4500 plo += FXMATH_DECIMAL_LSHIFT32BIT(pmid % 0xA);
4501 pmid /= 0xA;
4502 retVal = plo % 0xA;
4503 plo /= 0xA;
4504 return retVal;
4505 }
fxmath_decimal_helper_div10_any(uint64_t nums[],uint8_t numcount)4506 static inline uint8_t fxmath_decimal_helper_div10_any(uint64_t nums[],
4507 uint8_t numcount) {
4508 uint8_t retVal = 0;
4509 for (int i = numcount - 1; i > 0; i--) {
4510 nums[i - 1] += FXMATH_DECIMAL_LSHIFT32BIT(nums[i] % 0xA);
4511 nums[i] /= 0xA;
4512 }
4513 if (numcount) {
4514 retVal = nums[0] % 0xA;
4515 nums[0] /= 0xA;
4516 }
4517 return retVal;
4518 }
fxmath_decimal_helper_mul10(uint64_t & phi,uint64_t & pmid,uint64_t & plo)4519 static inline void fxmath_decimal_helper_mul10(uint64_t& phi,
4520 uint64_t& pmid,
4521 uint64_t& plo) {
4522 plo *= 0xA;
4523 pmid = pmid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(plo);
4524 plo = (uint32_t)plo;
4525 phi = phi * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(pmid);
4526 pmid = (uint32_t)pmid;
4527 }
fxmath_decimal_helper_mul10_any(uint64_t nums[],uint8_t numcount)4528 static inline void fxmath_decimal_helper_mul10_any(uint64_t nums[],
4529 uint8_t numcount) {
4530 nums[0] *= 0xA;
4531 for (int i = 1; i < numcount; i++) {
4532 nums[i] = nums[i] * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(nums[i - 1]);
4533 nums[i - 1] = (uint32_t)nums[i - 1];
4534 }
4535 }
fxmath_decimal_helper_normalize(uint64_t & phi,uint64_t & pmid,uint64_t & plo)4536 static inline void fxmath_decimal_helper_normalize(uint64_t& phi,
4537 uint64_t& pmid,
4538 uint64_t& plo) {
4539 phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid);
4540 pmid = (uint32_t)pmid;
4541 pmid += FXMATH_DECIMAL_RSHIFT32BIT(plo);
4542 plo = (uint32_t)plo;
4543 phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid);
4544 pmid = (uint32_t)pmid;
4545 }
fxmath_decimal_helper_normalize_any(uint64_t nums[],uint8_t len)4546 static inline void fxmath_decimal_helper_normalize_any(uint64_t nums[],
4547 uint8_t len) {
4548 {
4549 for (int i = len - 2; i > 0; i--) {
4550 nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]);
4551 nums[i] = (uint32_t)nums[i];
4552 }
4553 }
4554 {
4555 for (int i = 0; i < len - 1; i++) {
4556 nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]);
4557 nums[i] = (uint32_t)nums[i];
4558 }
4559 }
4560 }
fxmath_decimal_helper_raw_compare(uint32_t hi1,uint32_t mid1,uint32_t lo1,uint32_t hi2,uint32_t mid2,uint32_t lo2)4561 static inline int8_t fxmath_decimal_helper_raw_compare(uint32_t hi1,
4562 uint32_t mid1,
4563 uint32_t lo1,
4564 uint32_t hi2,
4565 uint32_t mid2,
4566 uint32_t lo2) {
4567 int8_t retVal = 0;
4568 if (!retVal) {
4569 retVal += (hi1 > hi2 ? 1 : (hi1 < hi2 ? -1 : 0));
4570 }
4571 if (!retVal) {
4572 retVal += (mid1 > mid2 ? 1 : (mid1 < mid2 ? -1 : 0));
4573 }
4574 if (!retVal) {
4575 retVal += (lo1 > lo2 ? 1 : (lo1 < lo2 ? -1 : 0));
4576 }
4577 return retVal;
4578 }
fxmath_decimal_helper_raw_compare_any(uint64_t a[],uint8_t al,uint64_t b[],uint8_t bl)4579 static inline int8_t fxmath_decimal_helper_raw_compare_any(uint64_t a[],
4580 uint8_t al,
4581 uint64_t b[],
4582 uint8_t bl) {
4583 int8_t retVal = 0;
4584 for (int i = std::max(al - 1, bl - 1); i >= 0; i--) {
4585 uint64_t l = (i >= al ? 0 : a[i]), r = (i >= bl ? 0 : b[i]);
4586 retVal += (l > r ? 1 : (l < r ? -1 : 0));
4587 if (retVal) {
4588 return retVal;
4589 }
4590 }
4591 return retVal;
4592 }
fxmath_decimal_helper_dec_any(uint64_t a[],uint8_t al)4593 static inline void fxmath_decimal_helper_dec_any(uint64_t a[], uint8_t al) {
4594 for (int i = 0; i < al; i++) {
4595 if (a[i]--) {
4596 return;
4597 }
4598 }
4599 }
fxmath_decimal_helper_inc_any(uint64_t a[],uint8_t al)4600 static inline void fxmath_decimal_helper_inc_any(uint64_t a[], uint8_t al) {
4601 for (int i = 0; i < al; i++) {
4602 a[i]++;
4603 if ((uint32_t)a[i] == a[i]) {
4604 return;
4605 }
4606 a[i] = 0;
4607 }
4608 }
fxmath_decimal_helper_raw_mul(uint64_t a[],uint8_t al,uint64_t b[],uint8_t bl,uint64_t c[],uint8_t cl)4609 static inline void fxmath_decimal_helper_raw_mul(uint64_t a[],
4610 uint8_t al,
4611 uint64_t b[],
4612 uint8_t bl,
4613 uint64_t c[],
4614 uint8_t cl) {
4615 assert(al + bl <= cl);
4616 {
4617 for (int i = 0; i < cl; i++) {
4618 c[i] = 0;
4619 }
4620 }
4621 {
4622 for (int i = 0; i < al; i++) {
4623 for (int j = 0; j < bl; j++) {
4624 uint64_t m = (uint64_t)a[i] * b[j];
4625 c[i + j] += (uint32_t)m;
4626 c[i + j + 1] += FXMATH_DECIMAL_RSHIFT32BIT(m);
4627 }
4628 }
4629 }
4630 {
4631 for (int i = 0; i < cl - 1; i++) {
4632 c[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(c[i]);
4633 c[i] = (uint32_t)c[i];
4634 }
4635 }
4636 {
4637 for (int i = 0; i < cl; i++) {
4638 c[i] = (uint32_t)c[i];
4639 }
4640 }
4641 }
fxmath_decimal_helper_raw_div(uint64_t a[],uint8_t al,uint64_t b[],uint8_t bl,uint64_t c[],uint8_t cl)4642 static inline void fxmath_decimal_helper_raw_div(uint64_t a[],
4643 uint8_t al,
4644 uint64_t b[],
4645 uint8_t bl,
4646 uint64_t c[],
4647 uint8_t cl) {
4648 int i;
4649 for (i = 0; i < cl; i++) {
4650 c[i] = 0;
4651 }
4652 uint64_t left[16] = {0}, right[16] = {0};
4653 left[0] = 0;
4654 for (i = 0; i < al; i++) {
4655 right[i] = a[i];
4656 }
4657 uint64_t tmp[16];
4658 while (fxmath_decimal_helper_raw_compare_any(left, al, right, al) <= 0) {
4659 uint64_t cur[16];
4660 for (i = 0; i < al; i++) {
4661 cur[i] = left[i] + right[i];
4662 }
4663 for (i = al - 1; i >= 0; i--) {
4664 if (i) {
4665 cur[i - 1] += FXMATH_DECIMAL_LSHIFT32BIT(cur[i] % 2);
4666 }
4667 cur[i] /= 2;
4668 }
4669 fxmath_decimal_helper_raw_mul(cur, al, b, bl, tmp, 16);
4670 switch (fxmath_decimal_helper_raw_compare_any(tmp, 16, a, al)) {
4671 case -1:
4672 for (i = 0; i < 16; i++) {
4673 left[i] = cur[i];
4674 }
4675 left[0]++;
4676 fxmath_decimal_helper_normalize_any(left, al);
4677 break;
4678 case 1:
4679 for (i = 0; i < 16; i++) {
4680 right[i] = cur[i];
4681 }
4682 fxmath_decimal_helper_dec_any(right, al);
4683 break;
4684 case 0:
4685 for (i = 0; i < std::min(al, cl); i++) {
4686 c[i] = cur[i];
4687 }
4688 return;
4689 }
4690 }
4691 for (i = 0; i < std::min(al, cl); i++) {
4692 c[i] = left[i];
4693 }
4694 }
fxmath_decimal_helper_outofrange(uint64_t a[],uint8_t al,uint8_t goal)4695 static inline FX_BOOL fxmath_decimal_helper_outofrange(uint64_t a[],
4696 uint8_t al,
4697 uint8_t goal) {
4698 for (int i = goal; i < al; i++) {
4699 if (a[i]) {
4700 return TRUE;
4701 }
4702 }
4703 return FALSE;
4704 }
fxmath_decimal_helper_shrinkintorange(uint64_t a[],uint8_t al,uint8_t goal,uint8_t & scale)4705 static inline void fxmath_decimal_helper_shrinkintorange(uint64_t a[],
4706 uint8_t al,
4707 uint8_t goal,
4708 uint8_t& scale) {
4709 FX_BOOL bRoundUp = FALSE;
4710 while (scale != 0 && (scale > FXMATH_DECIMAL_SCALELIMIT ||
4711 fxmath_decimal_helper_outofrange(a, al, goal))) {
4712 bRoundUp = fxmath_decimal_helper_div10_any(a, al) >= 5;
4713 scale--;
4714 }
4715 if (bRoundUp) {
4716 fxmath_decimal_helper_normalize_any(a, goal);
4717 fxmath_decimal_helper_inc_any(a, goal);
4718 }
4719 }
fxmath_decimal_helper_truncate(uint64_t & phi,uint64_t & pmid,uint64_t & plo,uint8_t & scale,uint8_t minscale=0)4720 static inline void fxmath_decimal_helper_truncate(uint64_t& phi,
4721 uint64_t& pmid,
4722 uint64_t& plo,
4723 uint8_t& scale,
4724 uint8_t minscale = 0) {
4725 while (scale > minscale) {
4726 uint64_t thi = phi, tmid = pmid, tlo = plo;
4727 if (fxmath_decimal_helper_div10(thi, tmid, tlo) != 0) {
4728 break;
4729 }
4730 phi = thi, pmid = tmid, plo = tlo;
4731 scale--;
4732 }
4733 }
CFX_Decimal()4734 CFX_Decimal::CFX_Decimal() {
4735 m_uLo = m_uMid = m_uHi = m_uFlags = 0;
4736 }
CFX_Decimal(uint64_t val)4737 CFX_Decimal::CFX_Decimal(uint64_t val) {
4738 m_uLo = (uint32_t)val;
4739 m_uMid = (uint32_t)FXMATH_DECIMAL_RSHIFT32BIT(val);
4740 m_uHi = 0;
4741 m_uFlags = 0;
4742 }
CFX_Decimal(uint32_t val)4743 CFX_Decimal::CFX_Decimal(uint32_t val) {
4744 m_uLo = (uint32_t)val;
4745 m_uMid = m_uHi = 0;
4746 m_uFlags = 0;
4747 }
CFX_Decimal(uint32_t lo,uint32_t mid,uint32_t hi,FX_BOOL neg,uint8_t scale)4748 CFX_Decimal::CFX_Decimal(uint32_t lo,
4749 uint32_t mid,
4750 uint32_t hi,
4751 FX_BOOL neg,
4752 uint8_t scale) {
4753 scale = (scale > FXMATH_DECIMAL_SCALELIMIT ? 0 : scale);
4754 m_uLo = lo;
4755 m_uMid = mid;
4756 m_uHi = hi;
4757 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(neg && IsNotZero(), scale);
4758 }
CFX_Decimal(int32_t val)4759 CFX_Decimal::CFX_Decimal(int32_t val) {
4760 if (val >= 0) {
4761 *this = CFX_Decimal((uint32_t)val);
4762 } else {
4763 *this = CFX_Decimal((uint32_t)-val);
4764 SetNegate();
4765 }
4766 }
CFX_Decimal(int64_t val)4767 CFX_Decimal::CFX_Decimal(int64_t val) {
4768 if (val >= 0) {
4769 *this = CFX_Decimal((uint64_t)val);
4770 } else {
4771 *this = CFX_Decimal((uint64_t)-val);
4772 SetNegate();
4773 }
4774 }
CFX_Decimal(FX_FLOAT val,uint8_t scale)4775 CFX_Decimal::CFX_Decimal(FX_FLOAT val, uint8_t scale) {
4776 FX_FLOAT newval = fabs(val);
4777 uint64_t phi, pmid, plo;
4778 plo = (uint64_t)newval;
4779 pmid = (uint64_t)(newval / 1e32);
4780 phi = (uint64_t)(newval / 1e64);
4781 newval = FXSYS_fmod(newval, 1.0f);
4782 for (uint8_t iter = 0; iter < scale; iter++) {
4783 fxmath_decimal_helper_mul10(phi, pmid, plo);
4784 newval *= 10;
4785 plo += (uint64_t)newval;
4786 newval = FXSYS_fmod(newval, 1.0f);
4787 }
4788 plo += FXSYS_round(newval);
4789 fxmath_decimal_helper_normalize(phi, pmid, plo);
4790 m_uHi = (uint32_t)phi;
4791 m_uMid = (uint32_t)pmid;
4792 m_uLo = (uint32_t)plo;
4793 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(val < 0 && IsNotZero(), scale);
4794 }
CFX_Decimal(const CFX_WideStringC & strObj)4795 CFX_Decimal::CFX_Decimal(const CFX_WideStringC& strObj) {
4796 const FX_WCHAR* str = strObj.GetPtr();
4797 const FX_WCHAR* strBound = str + strObj.GetLength();
4798 FX_BOOL pointmet = 0;
4799 FX_BOOL negmet = 0;
4800 uint8_t scale = 0;
4801 m_uHi = m_uMid = m_uLo = 0;
4802 while (str != strBound && *str == ' ') {
4803 str++;
4804 }
4805 if (str != strBound && *str == '-') {
4806 negmet = 1;
4807 str++;
4808 } else if (str != strBound && *str == '+') {
4809 str++;
4810 }
4811 while (str != strBound && ((*str >= '0' && *str <= '9') || *str == '.') &&
4812 scale < FXMATH_DECIMAL_SCALELIMIT) {
4813 if (*str == '.') {
4814 if (pointmet) {
4815 goto cont;
4816 }
4817 pointmet = 1;
4818 } else {
4819 m_uHi = m_uHi * 0xA + FXMATH_DECIMAL_RSHIFT32BIT((uint64_t)m_uMid * 0xA);
4820 m_uMid = m_uMid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT((uint64_t)m_uLo * 0xA);
4821 m_uLo = m_uLo * 0xA + (*str - '0');
4822 if (pointmet) {
4823 scale++;
4824 }
4825 }
4826 cont:
4827 str++;
4828 }
4829 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(negmet && IsNotZero(), scale);
4830 }
CFX_Decimal(const CFX_ByteStringC & strObj)4831 CFX_Decimal::CFX_Decimal(const CFX_ByteStringC& strObj) {
4832 CFX_WideString wstrObj;
4833 wstrObj.ConvertFrom(strObj);
4834 *this = CFX_Decimal(wstrObj);
4835 }
operator CFX_WideString() const4836 CFX_Decimal::operator CFX_WideString() const {
4837 CFX_WideString retString;
4838 CFX_WideString tmpbuf;
4839 uint64_t phi = m_uHi, pmid = m_uMid, plo = m_uLo;
4840 while (phi || pmid || plo) {
4841 tmpbuf += fxmath_decimal_helper_div10(phi, pmid, plo) + '0';
4842 }
4843 uint8_t outputlen = (uint8_t)tmpbuf.GetLength();
4844 uint8_t scale = (uint8_t)FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
4845 while (scale >= outputlen) {
4846 tmpbuf += '0';
4847 outputlen++;
4848 }
4849 if (FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero()) {
4850 retString += '-';
4851 }
4852 for (uint8_t idx = 0; idx < outputlen; idx++) {
4853 if (idx == (outputlen - scale) && scale != 0) {
4854 retString += '.';
4855 }
4856 retString += tmpbuf[outputlen - 1 - idx];
4857 }
4858 return retString;
4859 }
operator double() const4860 CFX_Decimal::operator double() const {
4861 double pow = (double)(1 << 16) * (1 << 16);
4862 double base =
4863 ((double)m_uHi) * pow * pow + ((double)m_uMid) * pow + ((double)m_uLo);
4864 int8_t scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
4865 FX_BOOL bNeg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags);
4866 return (bNeg ? -1 : 1) * base * ::pow(10.0, -scale);
4867 }
SetScale(uint8_t newscale)4868 void CFX_Decimal::SetScale(uint8_t newscale) {
4869 uint8_t oldscale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
4870 if (newscale > oldscale) {
4871 uint64_t phi = m_uHi, pmid = m_uMid, plo = m_uLo;
4872 for (uint8_t iter = 0; iter < newscale - oldscale; iter++) {
4873 fxmath_decimal_helper_mul10(phi, pmid, plo);
4874 }
4875 m_uHi = (uint32_t)phi;
4876 m_uMid = (uint32_t)pmid;
4877 m_uLo = (uint32_t)plo;
4878 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(
4879 FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale);
4880 } else if (newscale < oldscale) {
4881 uint64_t phi, pmid, plo;
4882 phi = 0, pmid = 0, plo = 5;
4883 {
4884 for (uint8_t iter = 0; iter < oldscale - newscale - 1; iter++) {
4885 fxmath_decimal_helper_mul10(phi, pmid, plo);
4886 }
4887 }
4888 phi += m_uHi;
4889 pmid += m_uMid;
4890 plo += m_uLo;
4891 fxmath_decimal_helper_normalize(phi, pmid, plo);
4892 {
4893 for (uint8_t iter = 0; iter < oldscale - newscale; iter++) {
4894 fxmath_decimal_helper_div10(phi, pmid, plo);
4895 }
4896 }
4897 m_uHi = (uint32_t)phi;
4898 m_uMid = (uint32_t)pmid;
4899 m_uLo = (uint32_t)plo;
4900 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(
4901 FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale);
4902 }
4903 }
GetScale()4904 uint8_t CFX_Decimal::GetScale() {
4905 uint8_t oldscale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
4906 return oldscale;
4907 }
SetAbs()4908 void CFX_Decimal::SetAbs() {
4909 m_uFlags &= ~FXMATH_DECIMAL_NEGMASK;
4910 }
SetNegate()4911 void CFX_Decimal::SetNegate() {
4912 if (IsNotZero()) {
4913 m_uFlags ^= FXMATH_DECIMAL_NEGMASK;
4914 }
4915 }
FloorOrCeil(FX_BOOL bFloor)4916 void CFX_Decimal::FloorOrCeil(FX_BOOL bFloor) {
4917 uint64_t nums[3] = {m_uLo, m_uMid, m_uHi};
4918 FX_BOOL bDataLoss = FALSE;
4919 for (int i = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); i > 0; i--) {
4920 bDataLoss = fxmath_decimal_helper_div10_any(nums, 3) || bDataLoss;
4921 }
4922 if (bDataLoss && (bFloor ? FXMATH_DECIMAL_FLAGS2NEG(m_uFlags)
4923 : !FXMATH_DECIMAL_FLAGS2NEG(m_uFlags))) {
4924 fxmath_decimal_helper_inc_any(nums, 3);
4925 }
4926 m_uHi = (uint32_t)nums[2];
4927 m_uMid = (uint32_t)nums[1];
4928 m_uLo = (uint32_t)nums[0];
4929 m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(
4930 FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), 0);
4931 }
SetFloor()4932 void CFX_Decimal::SetFloor() {
4933 FloorOrCeil(TRUE);
4934 }
SetCeiling()4935 void CFX_Decimal::SetCeiling() {
4936 FloorOrCeil(FALSE);
4937 }
SetTruncate()4938 void CFX_Decimal::SetTruncate() {
4939 FloorOrCeil(!FXMATH_DECIMAL_FLAGS2NEG(m_uFlags));
4940 }
Swap(CFX_Decimal & val)4941 void CFX_Decimal::Swap(CFX_Decimal& val) {
4942 uint32_t tmp;
4943 tmp = m_uHi;
4944 m_uHi = val.m_uHi;
4945 val.m_uHi = tmp;
4946 tmp = m_uMid;
4947 m_uMid = val.m_uMid;
4948 val.m_uMid = tmp;
4949 tmp = m_uLo;
4950 m_uLo = val.m_uLo;
4951 val.m_uLo = tmp;
4952 tmp = m_uFlags;
4953 m_uFlags = val.m_uFlags;
4954 val.m_uFlags = tmp;
4955 }
Compare(const CFX_Decimal & val) const4956 int8_t CFX_Decimal::Compare(const CFX_Decimal& val) const {
4957 CFX_Decimal lhs = *this, rhs = val;
4958 int8_t retVal = 0;
4959 if (FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) !=
4960 FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)) {
4961 uint8_t scale = std::min(FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags),
4962 FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags));
4963 lhs.SetScale(scale);
4964 rhs.SetScale(scale);
4965 }
4966 retVal = -(FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) -
4967 FXMATH_DECIMAL_FLAGS2NEG(rhs.m_uFlags));
4968 if (retVal) {
4969 return retVal;
4970 }
4971 retVal = fxmath_decimal_helper_raw_compare(lhs.m_uHi, lhs.m_uMid, lhs.m_uLo,
4972 rhs.m_uHi, rhs.m_uMid, rhs.m_uLo);
4973 return (FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) ? -retVal : retVal);
4974 }
AddOrMinus(const CFX_Decimal & val,FX_BOOL isAdding) const4975 CFX_Decimal CFX_Decimal::AddOrMinus(const CFX_Decimal& val,
4976 FX_BOOL isAdding) const {
4977 CFX_Decimal lhs = *this, rhs = val;
4978 if (FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) !=
4979 FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)) {
4980 uint8_t scale = std::max(FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags),
4981 FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags));
4982 lhs.SetScale(scale);
4983 rhs.SetScale(scale);
4984 }
4985 if (!isAdding) {
4986 rhs.SetNegate();
4987 }
4988 FX_BOOL doRawAdd = (FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) ==
4989 FXMATH_DECIMAL_FLAGS2NEG(rhs.m_uFlags));
4990 if (doRawAdd) {
4991 uint64_t phi = lhs.m_uHi, pmid = lhs.m_uMid, plo = lhs.m_uLo;
4992 phi += rhs.m_uHi;
4993 pmid += rhs.m_uMid;
4994 plo += rhs.m_uLo;
4995 fxmath_decimal_helper_normalize(phi, pmid, plo);
4996 if (FXMATH_DECIMAL_RSHIFT32BIT(phi) &&
4997 FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) != 0) {
4998 fxmath_decimal_helper_div10(phi, pmid, plo);
4999 lhs.m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(
5000 FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags),
5001 FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) - 1);
5002 }
5003 lhs.m_uHi = (uint32_t)phi;
5004 lhs.m_uMid = (uint32_t)pmid;
5005 lhs.m_uLo = (uint32_t)plo;
5006 return lhs;
5007 } else {
5008 if (fxmath_decimal_helper_raw_compare(lhs.m_uHi, lhs.m_uMid, lhs.m_uLo,
5009 rhs.m_uHi, rhs.m_uMid,
5010 rhs.m_uLo) < 0) {
5011 lhs.Swap(rhs);
5012 }
5013 lhs.m_uHi -= rhs.m_uHi;
5014 if (lhs.m_uMid < rhs.m_uMid) {
5015 lhs.m_uHi--;
5016 }
5017 lhs.m_uMid -= rhs.m_uMid;
5018 if (lhs.m_uLo < rhs.m_uLo) {
5019 if (!lhs.m_uMid) {
5020 lhs.m_uHi--;
5021 }
5022 lhs.m_uMid--;
5023 }
5024 lhs.m_uLo -= rhs.m_uLo;
5025 return lhs;
5026 }
5027 }
Multiply(const CFX_Decimal & val) const5028 CFX_Decimal CFX_Decimal::Multiply(const CFX_Decimal& val) const {
5029 uint64_t a[3] = {m_uLo, m_uMid, m_uHi},
5030 b[3] = {val.m_uLo, val.m_uMid, val.m_uHi};
5031 uint64_t c[6];
5032 fxmath_decimal_helper_raw_mul(a, 3, b, 3, c, 6);
5033 FX_BOOL neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^
5034 FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags);
5035 uint8_t scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) +
5036 FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags);
5037 fxmath_decimal_helper_shrinkintorange(c, 6, 3, scale);
5038 return CFX_Decimal((uint32_t)c[0], (uint32_t)c[1], (uint32_t)c[2], neg,
5039 scale);
5040 }
Divide(const CFX_Decimal & val) const5041 CFX_Decimal CFX_Decimal::Divide(const CFX_Decimal& val) const {
5042 if (!val.IsNotZero()) {
5043 return CFX_Decimal();
5044 }
5045 FX_BOOL neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^
5046 FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags);
5047 uint64_t a[7] = {m_uLo, m_uMid, m_uHi},
5048 b[3] = {val.m_uLo, val.m_uMid, val.m_uHi}, c[7] = {0};
5049 uint8_t scale = 0;
5050 if (FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) <
5051 FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags)) {
5052 for (int i = FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags) -
5053 FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
5054 i > 0; i--) {
5055 fxmath_decimal_helper_mul10_any(a, 7);
5056 }
5057 } else {
5058 scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) -
5059 FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags);
5060 }
5061 uint8_t minscale = scale;
5062 if (!IsNotZero()) {
5063 return CFX_Decimal(0, 0, 0, 0, minscale);
5064 }
5065 while (!a[6]) {
5066 fxmath_decimal_helper_mul10_any(a, 7);
5067 scale++;
5068 }
5069 fxmath_decimal_helper_div10_any(a, 7);
5070 scale--;
5071 fxmath_decimal_helper_raw_div(a, 6, b, 3, c, 7);
5072 fxmath_decimal_helper_shrinkintorange(c, 6, 3, scale);
5073 fxmath_decimal_helper_truncate(c[2], c[1], c[0], scale, minscale);
5074 return CFX_Decimal((uint32_t)c[0], (uint32_t)c[1], (uint32_t)c[2], neg,
5075 scale);
5076 }
Modulus(const CFX_Decimal & val) const5077 CFX_Decimal CFX_Decimal::Modulus(const CFX_Decimal& val) const {
5078 CFX_Decimal lhs = *this, rhs_abs = val;
5079 rhs_abs.SetAbs();
5080 if (!rhs_abs.IsNotZero()) {
5081 return *this;
5082 }
5083 while (TRUE) {
5084 CFX_Decimal lhs_abs = lhs;
5085 lhs_abs.SetAbs();
5086 if (lhs_abs < rhs_abs) {
5087 break;
5088 }
5089 CFX_Decimal quot = lhs / rhs_abs;
5090 quot.SetTruncate();
5091 lhs = lhs - quot * rhs_abs;
5092 }
5093 return lhs;
5094 }
operator ==(const CFX_Decimal & val) const5095 FX_BOOL CFX_Decimal::operator==(const CFX_Decimal& val) const {
5096 return Compare(val) == 0;
5097 }
operator <=(const CFX_Decimal & val) const5098 FX_BOOL CFX_Decimal::operator<=(const CFX_Decimal& val) const {
5099 return Compare(val) <= 0;
5100 }
operator >=(const CFX_Decimal & val) const5101 FX_BOOL CFX_Decimal::operator>=(const CFX_Decimal& val) const {
5102 return Compare(val) >= 0;
5103 }
operator !=(const CFX_Decimal & val) const5104 FX_BOOL CFX_Decimal::operator!=(const CFX_Decimal& val) const {
5105 return Compare(val) != 0;
5106 }
operator <(const CFX_Decimal & val) const5107 FX_BOOL CFX_Decimal::operator<(const CFX_Decimal& val) const {
5108 return Compare(val) < 0;
5109 }
operator >(const CFX_Decimal & val) const5110 FX_BOOL CFX_Decimal::operator>(const CFX_Decimal& val) const {
5111 return Compare(val) > 0;
5112 }
operator +(const CFX_Decimal & val) const5113 CFX_Decimal CFX_Decimal::operator+(const CFX_Decimal& val) const {
5114 return AddOrMinus(val, TRUE);
5115 }
operator -(const CFX_Decimal & val) const5116 CFX_Decimal CFX_Decimal::operator-(const CFX_Decimal& val) const {
5117 return AddOrMinus(val, FALSE);
5118 }
operator *(const CFX_Decimal & val) const5119 CFX_Decimal CFX_Decimal::operator*(const CFX_Decimal& val) const {
5120 return Multiply(val);
5121 }
operator /(const CFX_Decimal & val) const5122 CFX_Decimal CFX_Decimal::operator/(const CFX_Decimal& val) const {
5123 return Divide(val);
5124 }
operator %(const CFX_Decimal & val) const5125 CFX_Decimal CFX_Decimal::operator%(const CFX_Decimal& val) const {
5126 return Modulus(val);
5127 }
5128