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