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