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