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