Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(761)

Side by Side Diff: xfa/src/fgas/localization/fgas_locale.cpp

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

Powered by Google App Engine
This is Rietveld 408576698