1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "xfa/fxfa/parser/cxfa_localevalue.h" 8 9 #include <vector> 10 11 #include "core/fxcrt/fx_extension.h" 12 #include "third_party/base/ptr_util.h" 13 #include "third_party/base/stl_util.h" 14 #include "xfa/fgas/crt/cfgas_formatstring.h" 15 #include "xfa/fxfa/parser/cxfa_document.h" 16 #include "xfa/fxfa/parser/cxfa_localemgr.h" 17 #include "xfa/fxfa/parser/xfa_utils.h" 18 19 namespace { 20 21 FX_LOCALECATEGORY ValueCategory(FX_LOCALECATEGORY eCategory, 22 uint32_t dwValueType) { 23 if (eCategory != FX_LOCALECATEGORY_Unknown) 24 return eCategory; 25 26 switch (dwValueType) { 27 case XFA_VT_BOOLEAN: 28 case XFA_VT_INTEGER: 29 case XFA_VT_DECIMAL: 30 case XFA_VT_FLOAT: 31 return FX_LOCALECATEGORY_Num; 32 case XFA_VT_TEXT: 33 return FX_LOCALECATEGORY_Text; 34 case XFA_VT_DATE: 35 return FX_LOCALECATEGORY_Date; 36 case XFA_VT_TIME: 37 return FX_LOCALECATEGORY_Time; 38 case XFA_VT_DATETIME: 39 return FX_LOCALECATEGORY_DateTime; 40 } 41 return FX_LOCALECATEGORY_Unknown; 42 } 43 44 bool ValueSplitDateTime(const WideString& wsDateTime, 45 WideString& wsDate, 46 WideString& wsTime) { 47 wsDate = L""; 48 wsTime = L""; 49 if (wsDateTime.IsEmpty()) 50 return false; 51 52 auto nSplitIndex = wsDateTime.Find('T'); 53 if (!nSplitIndex.has_value()) 54 nSplitIndex = wsDateTime.Find(' '); 55 if (!nSplitIndex.has_value()) 56 return false; 57 58 wsDate = wsDateTime.Left(nSplitIndex.value()); 59 wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex.value() - 1); 60 return true; 61 } 62 63 } // namespace 64 65 CXFA_LocaleValue::CXFA_LocaleValue() 66 : m_pLocaleMgr(nullptr), m_dwType(XFA_VT_NULL), m_bValid(true) {} 67 68 CXFA_LocaleValue::CXFA_LocaleValue(const CXFA_LocaleValue& value) 69 : m_pLocaleMgr(value.m_pLocaleMgr), 70 m_wsValue(value.m_wsValue), 71 m_dwType(value.m_dwType), 72 m_bValid(value.m_bValid) {} 73 74 CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType, CXFA_LocaleMgr* pLocaleMgr) 75 : m_pLocaleMgr(pLocaleMgr), 76 m_dwType(dwType), 77 m_bValid(m_dwType != XFA_VT_NULL) {} 78 79 CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType, 80 const WideString& wsValue, 81 CXFA_LocaleMgr* pLocaleMgr) 82 : m_pLocaleMgr(pLocaleMgr), 83 m_wsValue(wsValue), 84 m_dwType(dwType), 85 m_bValid(ValidateCanonicalValue(wsValue, dwType)) {} 86 87 CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType, 88 const WideString& wsValue, 89 const WideString& wsFormat, 90 IFX_Locale* pLocale, 91 CXFA_LocaleMgr* pLocaleMgr) 92 : m_pLocaleMgr(pLocaleMgr), 93 m_dwType(dwType), 94 m_bValid(ParsePatternValue(wsValue, wsFormat, pLocale)) {} 95 96 CXFA_LocaleValue& CXFA_LocaleValue::operator=(const CXFA_LocaleValue& value) { 97 m_wsValue = value.m_wsValue; 98 m_dwType = value.m_dwType; 99 m_bValid = value.m_bValid; 100 m_pLocaleMgr = value.m_pLocaleMgr; 101 return *this; 102 } 103 104 CXFA_LocaleValue::~CXFA_LocaleValue() {} 105 106 bool CXFA_LocaleValue::ValidateValue(const WideString& wsValue, 107 const WideString& wsPattern, 108 IFX_Locale* pLocale, 109 WideString* pMatchFormat) { 110 WideString wsOutput; 111 IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); 112 if (pLocale) 113 m_pLocaleMgr->SetDefLocale(pLocale); 114 115 auto pFormat = pdfium::MakeUnique<CFGAS_FormatString>(m_pLocaleMgr); 116 std::vector<WideString> wsPatterns; 117 pFormat->SplitFormatString(wsPattern, &wsPatterns); 118 119 bool bRet = false; 120 int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns); 121 int32_t i = 0; 122 for (; i < iCount && !bRet; i++) { 123 WideString wsFormat = wsPatterns[i]; 124 switch (ValueCategory(pFormat->GetCategory(wsFormat), m_dwType)) { 125 case FX_LOCALECATEGORY_Null: 126 bRet = pFormat->ParseNull(wsValue, wsFormat); 127 if (!bRet) 128 bRet = wsValue.IsEmpty(); 129 break; 130 case FX_LOCALECATEGORY_Zero: 131 bRet = pFormat->ParseZero(wsValue, wsFormat); 132 if (!bRet) 133 bRet = wsValue == L"0"; 134 break; 135 case FX_LOCALECATEGORY_Num: { 136 WideString fNum; 137 bRet = pFormat->ParseNum(wsValue, wsFormat, &fNum); 138 if (!bRet) 139 bRet = pFormat->FormatNum(wsValue, wsFormat, &wsOutput); 140 break; 141 } 142 case FX_LOCALECATEGORY_Text: 143 bRet = pFormat->ParseText(wsValue, wsFormat, &wsOutput); 144 wsOutput.clear(); 145 if (!bRet) 146 bRet = pFormat->FormatText(wsValue, wsFormat, &wsOutput); 147 break; 148 case FX_LOCALECATEGORY_Date: { 149 CFX_DateTime dt; 150 bRet = ValidateCanonicalDate(wsValue, &dt); 151 if (!bRet) { 152 bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date, 153 &dt); 154 if (!bRet) { 155 bRet = pFormat->FormatDateTime(wsValue, wsFormat, 156 FX_DATETIMETYPE_Date, &wsOutput); 157 } 158 } 159 break; 160 } 161 case FX_LOCALECATEGORY_Time: { 162 CFX_DateTime dt; 163 bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, 164 &dt); 165 if (!bRet) { 166 bRet = pFormat->FormatDateTime(wsValue, wsFormat, 167 FX_DATETIMETYPE_Time, &wsOutput); 168 } 169 break; 170 } 171 case FX_LOCALECATEGORY_DateTime: { 172 CFX_DateTime dt; 173 bRet = pFormat->ParseDateTime(wsValue, wsFormat, 174 FX_DATETIMETYPE_DateTime, &dt); 175 if (!bRet) { 176 bRet = pFormat->FormatDateTime(wsValue, wsFormat, 177 FX_DATETIMETYPE_DateTime, &wsOutput); 178 } 179 break; 180 } 181 default: 182 bRet = false; 183 break; 184 } 185 } 186 if (bRet && pMatchFormat) 187 *pMatchFormat = wsPatterns[i - 1]; 188 if (pLocale) 189 m_pLocaleMgr->SetDefLocale(locale); 190 191 return bRet; 192 } 193 194 double CXFA_LocaleValue::GetDoubleNum() const { 195 if (m_bValid && (m_dwType == XFA_VT_BOOLEAN || m_dwType == XFA_VT_INTEGER || 196 m_dwType == XFA_VT_DECIMAL || m_dwType == XFA_VT_FLOAT)) { 197 int64_t nIntegral = 0; 198 uint32_t dwFractional = 0; 199 int32_t nExponent = 0; 200 int32_t cc = 0; 201 bool bNegative = false; 202 bool bExpSign = false; 203 const wchar_t* str = m_wsValue.c_str(); 204 int len = m_wsValue.GetLength(); 205 while (FXSYS_iswspace(str[cc]) && cc < len) 206 cc++; 207 208 if (cc >= len) 209 return 0; 210 if (str[0] == '+') { 211 cc++; 212 } else if (str[0] == '-') { 213 bNegative = true; 214 cc++; 215 } 216 217 int32_t nIntegralLen = 0; 218 while (cc < len) { 219 if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc]) || 220 nIntegralLen > 17) { 221 break; 222 } 223 nIntegral = nIntegral * 10 + str[cc] - '0'; 224 cc++; 225 nIntegralLen++; 226 } 227 228 nIntegral = bNegative ? -nIntegral : nIntegral; 229 int32_t scale = 0; 230 double fraction = 0.0; 231 if (cc < len && str[cc] == '.') { 232 cc++; 233 while (cc < len) { 234 fraction += XFA_GetFractionalScale(scale) * (str[cc] - '0'); 235 scale++; 236 cc++; 237 if (scale == XFA_GetMaxFractionalScale() || 238 !FXSYS_isDecimalDigit(str[cc])) { 239 break; 240 } 241 } 242 dwFractional = static_cast<uint32_t>(fraction * 4294967296.0); 243 } 244 if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) { 245 cc++; 246 if (cc < len) { 247 if (str[cc] == '+') { 248 cc++; 249 } else if (str[cc] == '-') { 250 bExpSign = true; 251 cc++; 252 } 253 } 254 while (cc < len) { 255 if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc])) 256 break; 257 258 nExponent = nExponent * 10 + str[cc] - '0'; 259 cc++; 260 } 261 nExponent = bExpSign ? -nExponent : nExponent; 262 } 263 264 double dValue = dwFractional / 4294967296.0; 265 dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue); 266 if (nExponent != 0) 267 dValue *= FXSYS_pow(10, static_cast<float>(nExponent)); 268 269 return dValue; 270 } 271 return 0; 272 } 273 274 CFX_DateTime CXFA_LocaleValue::GetDate() const { 275 if (!m_bValid || m_dwType != XFA_VT_DATE) 276 return CFX_DateTime(); 277 278 CFX_DateTime dt; 279 FX_DateFromCanonical(m_wsValue, &dt); 280 return dt; 281 } 282 283 CFX_DateTime CXFA_LocaleValue::GetTime() const { 284 if (!m_bValid || m_dwType != XFA_VT_TIME) 285 return CFX_DateTime(); 286 287 CFX_DateTime dt; 288 FX_TimeFromCanonical(m_wsValue.AsStringView(), &dt, 289 m_pLocaleMgr->GetDefLocale()); 290 return dt; 291 } 292 293 bool CXFA_LocaleValue::SetDate(const CFX_DateTime& d) { 294 m_dwType = XFA_VT_DATE; 295 m_wsValue = WideString::Format(L"%04d-%02d-%02d", d.GetYear(), d.GetMonth(), 296 d.GetDay()); 297 return true; 298 } 299 300 bool CXFA_LocaleValue::SetTime(const CFX_DateTime& t) { 301 m_dwType = XFA_VT_TIME; 302 m_wsValue = WideString::Format(L"%02d:%02d:%02d", t.GetHour(), t.GetMinute(), 303 t.GetSecond()); 304 if (t.GetMillisecond() > 0) 305 m_wsValue += WideString::Format(L"%:03d", t.GetMillisecond()); 306 return true; 307 } 308 309 bool CXFA_LocaleValue::SetDateTime(const CFX_DateTime& dt) { 310 m_dwType = XFA_VT_DATETIME; 311 m_wsValue = WideString::Format(L"%04d-%02d-%02dT%02d:%02d:%02d", dt.GetYear(), 312 dt.GetMonth(), dt.GetDay(), dt.GetHour(), 313 dt.GetMinute(), dt.GetSecond()); 314 if (dt.GetMillisecond() > 0) 315 m_wsValue += WideString::Format(L"%:03d", dt.GetMillisecond()); 316 return true; 317 } 318 319 bool CXFA_LocaleValue::FormatPatterns(WideString& wsResult, 320 const WideString& wsFormat, 321 IFX_Locale* pLocale, 322 XFA_VALUEPICTURE eValueType) const { 323 auto pFormat = pdfium::MakeUnique<CFGAS_FormatString>(m_pLocaleMgr); 324 std::vector<WideString> wsPatterns; 325 pFormat->SplitFormatString(wsFormat, &wsPatterns); 326 wsResult.clear(); 327 int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns); 328 for (int32_t i = 0; i < iCount; i++) { 329 if (FormatSinglePattern(wsResult, wsPatterns[i], pLocale, eValueType)) 330 return true; 331 } 332 return false; 333 } 334 335 bool CXFA_LocaleValue::FormatSinglePattern(WideString& wsResult, 336 const WideString& wsFormat, 337 IFX_Locale* pLocale, 338 XFA_VALUEPICTURE eValueType) const { 339 IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); 340 if (pLocale) 341 m_pLocaleMgr->SetDefLocale(pLocale); 342 343 wsResult.clear(); 344 bool bRet = false; 345 auto pFormat = pdfium::MakeUnique<CFGAS_FormatString>(m_pLocaleMgr); 346 FX_LOCALECATEGORY eCategory = 347 ValueCategory(pFormat->GetCategory(wsFormat), m_dwType); 348 switch (eCategory) { 349 case FX_LOCALECATEGORY_Null: 350 if (m_wsValue.IsEmpty()) 351 bRet = pFormat->FormatNull(wsFormat, &wsResult); 352 break; 353 case FX_LOCALECATEGORY_Zero: 354 if (m_wsValue == L"0") 355 bRet = pFormat->FormatZero(wsFormat, &wsResult); 356 break; 357 case FX_LOCALECATEGORY_Num: 358 bRet = pFormat->FormatNum(m_wsValue, wsFormat, &wsResult); 359 break; 360 case FX_LOCALECATEGORY_Text: 361 bRet = pFormat->FormatText(m_wsValue, wsFormat, &wsResult); 362 break; 363 case FX_LOCALECATEGORY_Date: 364 bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, FX_DATETIMETYPE_Date, 365 &wsResult); 366 break; 367 case FX_LOCALECATEGORY_Time: 368 bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, FX_DATETIMETYPE_Time, 369 &wsResult); 370 break; 371 case FX_LOCALECATEGORY_DateTime: 372 bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, 373 FX_DATETIMETYPE_DateTime, &wsResult); 374 break; 375 default: 376 wsResult = m_wsValue; 377 bRet = true; 378 } 379 if (!bRet && (eCategory != FX_LOCALECATEGORY_Num || 380 eValueType != XFA_VALUEPICTURE_Display)) { 381 wsResult = m_wsValue; 382 } 383 if (pLocale) 384 m_pLocaleMgr->SetDefLocale(locale); 385 386 return bRet; 387 } 388 389 bool CXFA_LocaleValue::ValidateCanonicalValue(const WideString& wsValue, 390 uint32_t dwVType) { 391 if (wsValue.IsEmpty()) 392 return true; 393 394 CFX_DateTime dt; 395 switch (dwVType) { 396 case XFA_VT_DATE: { 397 if (ValidateCanonicalDate(wsValue, &dt)) 398 return true; 399 400 WideString wsDate; 401 WideString wsTime; 402 if (ValueSplitDateTime(wsValue, wsDate, wsTime) && 403 ValidateCanonicalDate(wsDate, &dt)) { 404 return true; 405 } 406 return false; 407 } 408 case XFA_VT_TIME: { 409 if (ValidateCanonicalTime(wsValue)) 410 return true; 411 412 WideString wsDate; 413 WideString wsTime; 414 if (ValueSplitDateTime(wsValue, wsDate, wsTime) && 415 ValidateCanonicalTime(wsTime)) { 416 return true; 417 } 418 return false; 419 } 420 case XFA_VT_DATETIME: { 421 WideString wsDate, wsTime; 422 if (ValueSplitDateTime(wsValue, wsDate, wsTime) && 423 ValidateCanonicalDate(wsDate, &dt) && ValidateCanonicalTime(wsTime)) { 424 return true; 425 } 426 } break; 427 } 428 return true; 429 } 430 431 bool CXFA_LocaleValue::ValidateCanonicalDate(const WideString& wsDate, 432 CFX_DateTime* unDate) { 433 static const uint16_t LastDay[12] = {31, 28, 31, 30, 31, 30, 434 31, 31, 30, 31, 30, 31}; 435 static const uint16_t wCountY = 4; 436 static const uint16_t wCountM = 2; 437 static const uint16_t wCountD = 2; 438 int nLen = wsDate.GetLength(); 439 if (nLen < wCountY || nLen > wCountY + wCountM + wCountD + 2) 440 return false; 441 442 const bool bSymbol = wsDate.Contains(0x2D); 443 uint16_t wYear = 0; 444 uint16_t wMonth = 0; 445 uint16_t wDay = 0; 446 const wchar_t* pDate = wsDate.c_str(); 447 int nIndex = 0; 448 int nStart = 0; 449 while (pDate[nIndex] != '\0' && nIndex < wCountY) { 450 if (!FXSYS_isDecimalDigit(pDate[nIndex])) 451 return false; 452 453 wYear = (pDate[nIndex] - '0') + wYear * 10; 454 nIndex++; 455 } 456 if (bSymbol) { 457 if (pDate[nIndex] != 0x2D) 458 return false; 459 nIndex++; 460 } 461 462 nStart = nIndex; 463 while (pDate[nIndex] != '\0' && nIndex - nStart < wCountM && nIndex < nLen) { 464 if (!FXSYS_isDecimalDigit(pDate[nIndex])) 465 return false; 466 467 wMonth = (pDate[nIndex] - '0') + wMonth * 10; 468 nIndex++; 469 } 470 if (bSymbol) { 471 if (pDate[nIndex] != 0x2D) 472 return false; 473 nIndex++; 474 } 475 476 nStart = nIndex; 477 while (pDate[nIndex] != '\0' && nIndex - nStart < wCountD && nIndex < nLen) { 478 if (!FXSYS_isDecimalDigit(pDate[nIndex])) 479 return false; 480 481 wDay = (pDate[nIndex] - '0') + wDay * 10; 482 nIndex++; 483 } 484 if (nIndex != nLen) 485 return false; 486 if (wYear < 1900 || wYear > 2029) 487 return false; 488 if (wMonth < 1 || wMonth > 12) 489 return wMonth == 0 && nLen == wCountY; 490 if (wDay < 1) 491 return wDay == 0 && (nLen == wCountY + wCountM); 492 if (wMonth == 2) { 493 if (wYear % 400 == 0 || (wYear % 100 != 0 && wYear % 4 == 0)) { 494 if (wDay > 29) 495 return false; 496 } else if (wDay > 28) { 497 return false; 498 } 499 } else if (wDay > LastDay[wMonth - 1]) { 500 return false; 501 } 502 503 unDate->SetDate(wYear, static_cast<uint8_t>(wMonth), 504 static_cast<uint8_t>(wDay)); 505 return true; 506 } 507 508 bool CXFA_LocaleValue::ValidateCanonicalTime(const WideString& wsTime) { 509 int nLen = wsTime.GetLength(); 510 if (nLen < 2) 511 return false; 512 513 const uint16_t wCountH = 2; 514 const uint16_t wCountM = 2; 515 const uint16_t wCountS = 2; 516 const uint16_t wCountF = 3; 517 const bool bSymbol = wsTime.Contains(':'); 518 uint16_t wHour = 0; 519 uint16_t wMinute = 0; 520 uint16_t wSecond = 0; 521 uint16_t wFraction = 0; 522 const wchar_t* pTime = wsTime.c_str(); 523 int nIndex = 0; 524 int nStart = 0; 525 while (nIndex - nStart < wCountH && pTime[nIndex]) { 526 if (!FXSYS_isDecimalDigit(pTime[nIndex])) 527 return false; 528 wHour = pTime[nIndex] - '0' + wHour * 10; 529 nIndex++; 530 } 531 if (bSymbol) { 532 if (nIndex < nLen && pTime[nIndex] != ':') 533 return false; 534 nIndex++; 535 } 536 537 nStart = nIndex; 538 while (nIndex - nStart < wCountM && nIndex < nLen && pTime[nIndex]) { 539 if (!FXSYS_isDecimalDigit(pTime[nIndex])) 540 return false; 541 wMinute = pTime[nIndex] - '0' + wMinute * 10; 542 nIndex++; 543 } 544 if (bSymbol) { 545 if (nIndex < nLen && pTime[nIndex] != ':') 546 return false; 547 nIndex++; 548 } 549 nStart = nIndex; 550 while (nIndex - nStart < wCountS && nIndex < nLen && pTime[nIndex]) { 551 if (!FXSYS_isDecimalDigit(pTime[nIndex])) 552 return false; 553 wSecond = pTime[nIndex] - '0' + wSecond * 10; 554 nIndex++; 555 } 556 auto pos = wsTime.Find('.'); 557 if (pos.has_value() && pos.value() != 0) { 558 if (pTime[nIndex] != '.') 559 return false; 560 nIndex++; 561 nStart = nIndex; 562 while (nIndex - nStart < wCountF && nIndex < nLen && pTime[nIndex]) { 563 if (!FXSYS_isDecimalDigit(pTime[nIndex])) 564 return false; 565 wFraction = pTime[nIndex] - '0' + wFraction * 10; 566 nIndex++; 567 } 568 } 569 if (nIndex < nLen) { 570 if (pTime[nIndex] == 'Z') { 571 nIndex++; 572 } else if (pTime[nIndex] == '-' || pTime[nIndex] == '+') { 573 int16_t nOffsetH = 0; 574 int16_t nOffsetM = 0; 575 nIndex++; 576 nStart = nIndex; 577 while (nIndex - nStart < wCountH && nIndex < nLen && pTime[nIndex]) { 578 if (!FXSYS_isDecimalDigit(pTime[nIndex])) 579 return false; 580 nOffsetH = pTime[nIndex] - '0' + nOffsetH * 10; 581 nIndex++; 582 } 583 if (bSymbol) { 584 if (nIndex < nLen && pTime[nIndex] != ':') 585 return false; 586 nIndex++; 587 } 588 nStart = nIndex; 589 while (nIndex - nStart < wCountM && nIndex < nLen && pTime[nIndex]) { 590 if (!FXSYS_isDecimalDigit(pTime[nIndex])) 591 return false; 592 nOffsetM = pTime[nIndex] - '0' + nOffsetM * 10; 593 nIndex++; 594 } 595 if (nOffsetH > 12 || nOffsetM >= 60) 596 return false; 597 } 598 } 599 return nIndex == nLen && wHour < 24 && wMinute < 60 && wSecond < 60 && 600 wFraction <= 999; 601 } 602 603 bool CXFA_LocaleValue::ParsePatternValue(const WideString& wsValue, 604 const WideString& wsPattern, 605 IFX_Locale* pLocale) { 606 IFX_Locale* locale = m_pLocaleMgr->GetDefLocale(); 607 if (pLocale) 608 m_pLocaleMgr->SetDefLocale(pLocale); 609 610 auto pFormat = pdfium::MakeUnique<CFGAS_FormatString>(m_pLocaleMgr); 611 std::vector<WideString> wsPatterns; 612 pFormat->SplitFormatString(wsPattern, &wsPatterns); 613 bool bRet = false; 614 int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns); 615 for (int32_t i = 0; i < iCount && !bRet; i++) { 616 WideString wsFormat = wsPatterns[i]; 617 switch (ValueCategory(pFormat->GetCategory(wsFormat), m_dwType)) { 618 case FX_LOCALECATEGORY_Null: 619 bRet = pFormat->ParseNull(wsValue, wsFormat); 620 if (bRet) 621 m_wsValue.clear(); 622 break; 623 case FX_LOCALECATEGORY_Zero: 624 bRet = pFormat->ParseZero(wsValue, wsFormat); 625 if (bRet) 626 m_wsValue = L"0"; 627 break; 628 case FX_LOCALECATEGORY_Num: { 629 WideString fNum; 630 bRet = pFormat->ParseNum(wsValue, wsFormat, &fNum); 631 if (bRet) 632 m_wsValue = fNum; 633 break; 634 } 635 case FX_LOCALECATEGORY_Text: 636 bRet = pFormat->ParseText(wsValue, wsFormat, &m_wsValue); 637 break; 638 case FX_LOCALECATEGORY_Date: { 639 CFX_DateTime dt; 640 bRet = ValidateCanonicalDate(wsValue, &dt); 641 if (!bRet) { 642 bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date, 643 &dt); 644 } 645 if (bRet) 646 SetDate(dt); 647 break; 648 } 649 case FX_LOCALECATEGORY_Time: { 650 CFX_DateTime dt; 651 bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, 652 &dt); 653 if (bRet) 654 SetTime(dt); 655 break; 656 } 657 case FX_LOCALECATEGORY_DateTime: { 658 CFX_DateTime dt; 659 bRet = pFormat->ParseDateTime(wsValue, wsFormat, 660 FX_DATETIMETYPE_DateTime, &dt); 661 if (bRet) 662 SetDateTime(dt); 663 break; 664 } 665 default: 666 m_wsValue = wsValue; 667 bRet = true; 668 break; 669 } 670 } 671 if (!bRet) 672 m_wsValue = wsValue; 673 674 if (pLocale) 675 m_pLocaleMgr->SetDefLocale(locale); 676 677 return bRet; 678 } 679 680 void CXFA_LocaleValue::GetNumericFormat(WideString& wsFormat, 681 int32_t nIntLen, 682 int32_t nDecLen) { 683 ASSERT(wsFormat.IsEmpty()); 684 ASSERT(nIntLen >= -1 && nDecLen >= -1); 685 686 int32_t nTotalLen = (nIntLen >= 0 ? nIntLen : 2) + 1 + 687 (nDecLen >= 0 ? nDecLen : 2) + (nDecLen == 0 ? 0 : 1); 688 wchar_t* lpBuf = wsFormat.GetBuffer(nTotalLen); 689 int32_t nPos = 0; 690 lpBuf[nPos++] = L's'; 691 692 if (nIntLen == -1) { 693 lpBuf[nPos++] = L'z'; 694 lpBuf[nPos++] = L'*'; 695 } else { 696 while (nIntLen) { 697 lpBuf[nPos++] = L'z'; 698 nIntLen--; 699 } 700 } 701 if (nDecLen != 0) { 702 lpBuf[nPos++] = L'.'; 703 } 704 if (nDecLen == -1) { 705 lpBuf[nPos++] = L'z'; 706 lpBuf[nPos++] = L'*'; 707 } else { 708 while (nDecLen) { 709 lpBuf[nPos++] = L'z'; 710 nDecLen--; 711 } 712 } 713 wsFormat.ReleaseBuffer(nTotalLen); 714 } 715 716 bool CXFA_LocaleValue::ValidateNumericTemp(const WideString& wsNumeric, 717 const WideString& wsFormat, 718 IFX_Locale* pLocale) { 719 if (wsFormat.IsEmpty() || wsNumeric.IsEmpty()) 720 return true; 721 722 const wchar_t* pNum = wsNumeric.c_str(); 723 const wchar_t* pFmt = wsFormat.c_str(); 724 int32_t n = 0; 725 int32_t nf = 0; 726 wchar_t c = pNum[n]; 727 wchar_t cf = pFmt[nf]; 728 if (cf == L's') { 729 if (c == L'-' || c == L'+') 730 ++n; 731 ++nf; 732 } 733 734 bool bLimit = true; 735 int32_t nCount = wsNumeric.GetLength(); 736 int32_t nCountFmt = wsFormat.GetLength(); 737 while (n < nCount && (bLimit ? nf < nCountFmt : true) && 738 FXSYS_isDecimalDigit(c = pNum[n])) { 739 if (bLimit == true) { 740 if ((cf = pFmt[nf]) == L'*') 741 bLimit = false; 742 else if (cf == L'z') 743 nf++; 744 else 745 return false; 746 } 747 n++; 748 } 749 if (n == nCount) 750 return true; 751 if (nf == nCountFmt) 752 return false; 753 754 while (nf < nCountFmt && (cf = pFmt[nf]) != L'.') { 755 ASSERT(cf == L'z' || cf == L'*'); 756 ++nf; 757 } 758 759 WideString wsDecimalSymbol; 760 if (pLocale) 761 wsDecimalSymbol = pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal); 762 else 763 wsDecimalSymbol = WideString(L'.'); 764 765 if (pFmt[nf] != L'.') 766 return false; 767 if (wsDecimalSymbol != WideStringView(c) && c != L'.') 768 return false; 769 770 ++nf; 771 ++n; 772 bLimit = true; 773 while (n < nCount && (bLimit ? nf < nCountFmt : true) && 774 FXSYS_isDecimalDigit(c = pNum[n])) { 775 if (bLimit == true) { 776 if ((cf = pFmt[nf]) == L'*') 777 bLimit = false; 778 else if (cf == L'z') 779 nf++; 780 else 781 return false; 782 } 783 n++; 784 } 785 return n == nCount; 786 } 787