Home | History | Annotate | Download | only in parser
      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/xfa_localevalue.h"
      8 
      9 #include <vector>
     10 
     11 #include "core/fxcrt/fx_ext.h"
     12 #include "third_party/base/ptr_util.h"
     13 #include "third_party/base/stl_util.h"
     14 #include "xfa/fgas/localization/fgas_localeimp.h"
     15 #include "xfa/fxfa/parser/cxfa_document.h"
     16 #include "xfa/fxfa/parser/xfa_localemgr.h"
     17 #include "xfa/fxfa/parser/xfa_object.h"
     18 #include "xfa/fxfa/parser/xfa_utils.h"
     19 
     20 static const FX_DOUBLE fraction_scales[] = {0.1,
     21                                             0.01,
     22                                             0.001,
     23                                             0.0001,
     24                                             0.00001,
     25                                             0.000001,
     26                                             0.0000001,
     27                                             0.00000001,
     28                                             0.000000001,
     29                                             0.0000000001,
     30                                             0.00000000001,
     31                                             0.000000000001,
     32                                             0.0000000000001,
     33                                             0.00000000000001,
     34                                             0.000000000000001,
     35                                             0.0000000000000001};
     36 CXFA_LocaleValue::CXFA_LocaleValue() {
     37   m_dwType = XFA_VT_NULL;
     38   m_bValid = true;
     39   m_pLocaleMgr = nullptr;
     40 }
     41 CXFA_LocaleValue::CXFA_LocaleValue(const CXFA_LocaleValue& value) {
     42   m_dwType = XFA_VT_NULL;
     43   m_bValid = true;
     44   m_pLocaleMgr = nullptr;
     45   *this = value;
     46 }
     47 CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType,
     48                                    CXFA_LocaleMgr* pLocaleMgr) {
     49   m_dwType = dwType;
     50   m_bValid = (m_dwType != XFA_VT_NULL);
     51   m_pLocaleMgr = pLocaleMgr;
     52 }
     53 CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType,
     54                                    const CFX_WideString& wsValue,
     55                                    CXFA_LocaleMgr* pLocaleMgr) {
     56   m_wsValue = wsValue;
     57   m_dwType = dwType;
     58   m_pLocaleMgr = pLocaleMgr;
     59   m_bValid = ValidateCanonicalValue(wsValue, dwType);
     60 }
     61 CXFA_LocaleValue::CXFA_LocaleValue(uint32_t dwType,
     62                                    const CFX_WideString& wsValue,
     63                                    const CFX_WideString& wsFormat,
     64                                    IFX_Locale* pLocale,
     65                                    CXFA_LocaleMgr* pLocaleMgr) {
     66   m_pLocaleMgr = pLocaleMgr;
     67   m_bValid = true;
     68   m_dwType = dwType;
     69   m_bValid = ParsePatternValue(wsValue, wsFormat, pLocale);
     70 }
     71 CXFA_LocaleValue& CXFA_LocaleValue::operator=(const CXFA_LocaleValue& value) {
     72   m_wsValue = value.m_wsValue;
     73   m_dwType = value.m_dwType;
     74   m_bValid = value.m_bValid;
     75   m_pLocaleMgr = value.m_pLocaleMgr;
     76   return *this;
     77 }
     78 CXFA_LocaleValue::~CXFA_LocaleValue() {}
     79 static FX_LOCALECATEGORY XFA_ValugeCategory(FX_LOCALECATEGORY eCategory,
     80                                             uint32_t dwValueType) {
     81   if (eCategory == FX_LOCALECATEGORY_Unknown) {
     82     switch (dwValueType) {
     83       case XFA_VT_BOOLEAN:
     84       case XFA_VT_INTEGER:
     85       case XFA_VT_DECIMAL:
     86       case XFA_VT_FLOAT:
     87         return FX_LOCALECATEGORY_Num;
     88       case XFA_VT_TEXT:
     89         return FX_LOCALECATEGORY_Text;
     90       case XFA_VT_DATE:
     91         return FX_LOCALECATEGORY_Date;
     92       case XFA_VT_TIME:
     93         return FX_LOCALECATEGORY_Time;
     94       case XFA_VT_DATETIME:
     95         return FX_LOCALECATEGORY_DateTime;
     96     }
     97   }
     98   return eCategory;
     99 }
    100 
    101 bool CXFA_LocaleValue::ValidateValue(const CFX_WideString& wsValue,
    102                                      const CFX_WideString& wsPattern,
    103                                      IFX_Locale* pLocale,
    104                                      CFX_WideString* pMatchFormat) {
    105   CFX_WideString wsOutput;
    106   IFX_Locale* locale = m_pLocaleMgr->GetDefLocale();
    107   if (pLocale)
    108     m_pLocaleMgr->SetDefLocale(pLocale);
    109 
    110   auto pFormat = pdfium::MakeUnique<CFX_FormatString>(m_pLocaleMgr, false);
    111   std::vector<CFX_WideString> wsPatterns;
    112   pFormat->SplitFormatString(wsPattern, wsPatterns);
    113 
    114   bool bRet = false;
    115   int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns);
    116   int32_t i = 0;
    117   for (; i < iCount && !bRet; i++) {
    118     CFX_WideString wsFormat = wsPatterns[i];
    119     FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat);
    120     eCategory = XFA_ValugeCategory(eCategory, m_dwType);
    121     switch (eCategory) {
    122       case FX_LOCALECATEGORY_Null:
    123         bRet = pFormat->ParseNull(wsValue, wsFormat);
    124         if (!bRet) {
    125           bRet = wsValue.IsEmpty();
    126         }
    127         break;
    128       case FX_LOCALECATEGORY_Zero:
    129         bRet = pFormat->ParseZero(wsValue, wsFormat);
    130         if (!bRet) {
    131           bRet = wsValue == L"0";
    132         }
    133         break;
    134       case FX_LOCALECATEGORY_Num: {
    135         CFX_WideString fNum;
    136         bRet = pFormat->ParseNum(wsValue, wsFormat, fNum);
    137         if (!bRet) {
    138           bRet = pFormat->FormatNum(wsValue, wsFormat, wsOutput);
    139         }
    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         }
    148         break;
    149       case FX_LOCALECATEGORY_Date: {
    150         CFX_Unitime dt;
    151         bRet = ValidateCanonicalDate(wsValue, dt);
    152         if (!bRet) {
    153           bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date,
    154                                         dt);
    155           if (!bRet) {
    156             bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput,
    157                                            FX_DATETIMETYPE_Date);
    158           }
    159         }
    160         break;
    161       }
    162       case FX_LOCALECATEGORY_Time: {
    163         CFX_Unitime dt;
    164         bRet =
    165             pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, dt);
    166         if (!bRet) {
    167           bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput,
    168                                          FX_DATETIMETYPE_Time);
    169         }
    170         break;
    171       }
    172       case FX_LOCALECATEGORY_DateTime: {
    173         CFX_Unitime dt;
    174         bRet = pFormat->ParseDateTime(wsValue, wsFormat,
    175                                       FX_DATETIMETYPE_DateTime, dt);
    176         if (!bRet) {
    177           bRet = pFormat->FormatDateTime(wsValue, wsFormat, wsOutput,
    178                                          FX_DATETIMETYPE_DateTime);
    179         }
    180         break;
    181       }
    182       default:
    183         bRet = false;
    184         break;
    185     }
    186   }
    187   if (bRet && pMatchFormat)
    188     *pMatchFormat = wsPatterns[i - 1];
    189 
    190   if (pLocale)
    191     m_pLocaleMgr->SetDefLocale(locale);
    192 
    193   return bRet;
    194 }
    195 
    196 CFX_WideString CXFA_LocaleValue::GetValue() const {
    197   return m_wsValue;
    198 }
    199 uint32_t CXFA_LocaleValue::GetType() const {
    200   return m_dwType;
    201 }
    202 void CXFA_LocaleValue::SetValue(const CFX_WideString& wsValue,
    203                                 uint32_t dwType) {
    204   m_wsValue = wsValue;
    205   m_dwType = dwType;
    206 }
    207 CFX_WideString CXFA_LocaleValue::GetText() const {
    208   if (m_bValid && m_dwType == XFA_VT_TEXT) {
    209     return m_wsValue;
    210   }
    211   return CFX_WideString();
    212 }
    213 FX_FLOAT CXFA_LocaleValue::GetNum() const {
    214   if (m_bValid && (m_dwType == XFA_VT_BOOLEAN || m_dwType == XFA_VT_INTEGER ||
    215                    m_dwType == XFA_VT_DECIMAL || m_dwType == XFA_VT_FLOAT)) {
    216     int64_t nIntegral = 0;
    217     uint32_t dwFractional = 0;
    218     int32_t nExponent = 0;
    219     int cc = 0;
    220     bool bNegative = false, bExpSign = false;
    221     const FX_WCHAR* str = m_wsValue.c_str();
    222     int len = m_wsValue.GetLength();
    223     while (FXSYS_iswspace(str[cc]) && cc < len) {
    224       cc++;
    225     }
    226     if (cc >= len) {
    227       return 0;
    228     }
    229     if (str[0] == '+') {
    230       cc++;
    231     } else if (str[0] == '-') {
    232       bNegative = true;
    233       cc++;
    234     }
    235     int nIntegralLen = 0;
    236     while (cc < len) {
    237       if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc]) ||
    238           nIntegralLen > 17) {
    239         break;
    240       }
    241       nIntegral = nIntegral * 10 + str[cc] - '0';
    242       cc++;
    243       nIntegralLen++;
    244     }
    245     nIntegral = bNegative ? -nIntegral : nIntegral;
    246     int scale = 0;
    247     double fraction = 0.0;
    248     if (cc < len && str[cc] == '.') {
    249       cc++;
    250       while (cc < len) {
    251         fraction += fraction_scales[scale] * (str[cc] - '0');
    252         scale++;
    253         cc++;
    254         if (scale == sizeof fraction_scales / sizeof(double) ||
    255             !FXSYS_isDecimalDigit(str[cc])) {
    256           break;
    257         }
    258       }
    259       dwFractional = (uint32_t)(fraction * 4294967296.0);
    260     }
    261     if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) {
    262       cc++;
    263       if (cc < len) {
    264         if (str[cc] == '+') {
    265           cc++;
    266         } else if (str[cc] == '-') {
    267           bExpSign = true;
    268           cc++;
    269         }
    270       }
    271       while (cc < len) {
    272         if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc])) {
    273           break;
    274         }
    275         nExponent = nExponent * 10 + str[cc] - '0';
    276         cc++;
    277       }
    278       nExponent = bExpSign ? -nExponent : nExponent;
    279     }
    280     FX_FLOAT fValue = (FX_FLOAT)(dwFractional / 4294967296.0);
    281     fValue = nIntegral + (nIntegral >= 0 ? fValue : -fValue);
    282     if (nExponent != 0) {
    283       fValue *= FXSYS_pow(10, (FX_FLOAT)nExponent);
    284     }
    285     return fValue;
    286   }
    287   return 0;
    288 }
    289 FX_DOUBLE CXFA_LocaleValue::GetDoubleNum() const {
    290   if (m_bValid && (m_dwType == XFA_VT_BOOLEAN || m_dwType == XFA_VT_INTEGER ||
    291                    m_dwType == XFA_VT_DECIMAL || m_dwType == XFA_VT_FLOAT)) {
    292     int64_t nIntegral = 0;
    293     uint32_t dwFractional = 0;
    294     int32_t nExponent = 0;
    295     int32_t cc = 0;
    296     bool bNegative = false, bExpSign = false;
    297     const FX_WCHAR* str = m_wsValue.c_str();
    298     int len = m_wsValue.GetLength();
    299     while (FXSYS_iswspace(str[cc]) && cc < len) {
    300       cc++;
    301     }
    302     if (cc >= len) {
    303       return 0;
    304     }
    305     if (str[0] == '+') {
    306       cc++;
    307     } else if (str[0] == '-') {
    308       bNegative = true;
    309       cc++;
    310     }
    311     int32_t nIntegralLen = 0;
    312     while (cc < len) {
    313       if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc]) ||
    314           nIntegralLen > 17) {
    315         break;
    316       }
    317       nIntegral = nIntegral * 10 + str[cc] - '0';
    318       cc++;
    319       nIntegralLen++;
    320     }
    321     nIntegral = bNegative ? -nIntegral : nIntegral;
    322     int32_t scale = 0;
    323     FX_DOUBLE fraction = 0.0;
    324     if (cc < len && str[cc] == '.') {
    325       cc++;
    326       while (cc < len) {
    327         fraction += fraction_scales[scale] * (str[cc] - '0');
    328         scale++;
    329         cc++;
    330         if (scale == sizeof fraction_scales / sizeof(FX_DOUBLE) ||
    331             !FXSYS_isDecimalDigit(str[cc])) {
    332           break;
    333         }
    334       }
    335       dwFractional = (uint32_t)(fraction * 4294967296.0);
    336     }
    337     if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) {
    338       cc++;
    339       if (cc < len) {
    340         if (str[cc] == '+') {
    341           cc++;
    342         } else if (str[cc] == '-') {
    343           bExpSign = true;
    344           cc++;
    345         }
    346       }
    347       while (cc < len) {
    348         if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc])) {
    349           break;
    350         }
    351         nExponent = nExponent * 10 + str[cc] - '0';
    352         cc++;
    353       }
    354       nExponent = bExpSign ? -nExponent : nExponent;
    355     }
    356     FX_DOUBLE dValue = (dwFractional / 4294967296.0);
    357     dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue);
    358     if (nExponent != 0) {
    359       dValue *= FXSYS_pow(10, (FX_FLOAT)nExponent);
    360     }
    361     return dValue;
    362   }
    363   return 0;
    364 }
    365 CFX_Unitime CXFA_LocaleValue::GetDate() const {
    366   if (m_bValid && m_dwType == XFA_VT_DATE) {
    367     CFX_Unitime dt;
    368     FX_DateFromCanonical(m_wsValue, dt);
    369     return dt;
    370   }
    371   return CFX_Unitime();
    372 }
    373 CFX_Unitime CXFA_LocaleValue::GetTime() const {
    374   if (m_bValid && m_dwType == XFA_VT_TIME) {
    375     CFX_Unitime dt(0);
    376     ASSERT(m_pLocaleMgr);
    377     FX_TimeFromCanonical(m_wsValue.AsStringC(), dt,
    378                          m_pLocaleMgr->GetDefLocale());
    379     return dt;
    380   }
    381   return CFX_Unitime();
    382 }
    383 CFX_Unitime CXFA_LocaleValue::GetDateTime() const {
    384   if (m_bValid && m_dwType == XFA_VT_DATETIME) {
    385     int32_t index = m_wsValue.Find('T');
    386     CFX_Unitime dt;
    387     FX_DateFromCanonical(m_wsValue.Left(index), dt);
    388     ASSERT(m_pLocaleMgr);
    389     FX_TimeFromCanonical(
    390         m_wsValue.Right(m_wsValue.GetLength() - index - 1).AsStringC(), dt,
    391         m_pLocaleMgr->GetDefLocale());
    392     return dt;
    393   }
    394   return CFX_Unitime();
    395 }
    396 bool CXFA_LocaleValue::SetText(const CFX_WideString& wsText) {
    397   m_dwType = XFA_VT_TEXT;
    398   m_wsValue = wsText;
    399   return true;
    400 }
    401 bool CXFA_LocaleValue::SetText(const CFX_WideString& wsText,
    402                                const CFX_WideString& wsFormat,
    403                                IFX_Locale* pLocale) {
    404   m_dwType = XFA_VT_TEXT;
    405   return m_bValid = ParsePatternValue(wsText, wsFormat, pLocale);
    406 }
    407 bool CXFA_LocaleValue::SetNum(FX_FLOAT fNum) {
    408   m_dwType = XFA_VT_FLOAT;
    409   m_wsValue.Format(L"%.8g", (FX_DOUBLE)fNum);
    410   return true;
    411 }
    412 bool CXFA_LocaleValue::SetNum(const CFX_WideString& wsNum,
    413                               const CFX_WideString& wsFormat,
    414                               IFX_Locale* pLocale) {
    415   m_dwType = XFA_VT_FLOAT;
    416   return m_bValid = ParsePatternValue(wsNum, wsFormat, pLocale);
    417 }
    418 bool CXFA_LocaleValue::SetDate(const CFX_Unitime& d) {
    419   m_dwType = XFA_VT_DATE;
    420   m_wsValue.Format(L"%04d-%02d-%02d", d.GetYear(), d.GetMonth(), d.GetDay());
    421   return true;
    422 }
    423 bool CXFA_LocaleValue::SetDate(const CFX_WideString& wsDate,
    424                                const CFX_WideString& wsFormat,
    425                                IFX_Locale* pLocale) {
    426   m_dwType = XFA_VT_DATE;
    427   return m_bValid = ParsePatternValue(wsDate, wsFormat, pLocale);
    428 }
    429 bool CXFA_LocaleValue::SetTime(const CFX_Unitime& t) {
    430   m_dwType = XFA_VT_TIME;
    431   m_wsValue.Format(L"%02d:%02d:%02d", t.GetHour(), t.GetMinute(),
    432                    t.GetSecond());
    433   if (t.GetMillisecond() > 0) {
    434     CFX_WideString wsTemp;
    435     wsTemp.Format(L"%:03d", t.GetMillisecond());
    436     m_wsValue += wsTemp;
    437   }
    438   return true;
    439 }
    440 bool CXFA_LocaleValue::SetTime(const CFX_WideString& wsTime,
    441                                const CFX_WideString& wsFormat,
    442                                IFX_Locale* pLocale) {
    443   m_dwType = XFA_VT_TIME;
    444   return m_bValid = ParsePatternValue(wsTime, wsFormat, pLocale);
    445 }
    446 bool CXFA_LocaleValue::SetDateTime(const CFX_Unitime& dt) {
    447   m_dwType = XFA_VT_DATETIME;
    448   m_wsValue.Format(L"%04d-%02d-%02dT%02d:%02d:%02d", dt.GetYear(),
    449                    dt.GetMonth(), dt.GetDay(), dt.GetHour(), dt.GetMinute(),
    450                    dt.GetSecond());
    451   if (dt.GetMillisecond() > 0) {
    452     CFX_WideString wsTemp;
    453     wsTemp.Format(L"%:03d", dt.GetMillisecond());
    454     m_wsValue += wsTemp;
    455   }
    456   return true;
    457 }
    458 bool CXFA_LocaleValue::SetDateTime(const CFX_WideString& wsDateTime,
    459                                    const CFX_WideString& wsFormat,
    460                                    IFX_Locale* pLocale) {
    461   m_dwType = XFA_VT_DATETIME;
    462   return m_bValid = ParsePatternValue(wsDateTime, wsFormat, pLocale);
    463 }
    464 
    465 bool CXFA_LocaleValue::FormatPatterns(CFX_WideString& wsResult,
    466                                       const CFX_WideString& wsFormat,
    467                                       IFX_Locale* pLocale,
    468                                       XFA_VALUEPICTURE eValueType) const {
    469   auto pFormat = pdfium::MakeUnique<CFX_FormatString>(m_pLocaleMgr, false);
    470   std::vector<CFX_WideString> wsPatterns;
    471   pFormat->SplitFormatString(wsFormat, wsPatterns);
    472   wsResult.clear();
    473   int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns);
    474   for (int32_t i = 0; i < iCount; i++) {
    475     if (FormatSinglePattern(wsResult, wsPatterns[i], pLocale, eValueType))
    476       return true;
    477   }
    478   return false;
    479 }
    480 
    481 bool CXFA_LocaleValue::FormatSinglePattern(CFX_WideString& wsResult,
    482                                            const CFX_WideString& wsFormat,
    483                                            IFX_Locale* pLocale,
    484                                            XFA_VALUEPICTURE eValueType) const {
    485   IFX_Locale* locale = m_pLocaleMgr->GetDefLocale();
    486   if (pLocale)
    487     m_pLocaleMgr->SetDefLocale(pLocale);
    488 
    489   wsResult.clear();
    490   bool bRet = false;
    491   auto pFormat = pdfium::MakeUnique<CFX_FormatString>(m_pLocaleMgr, false);
    492   FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat);
    493   eCategory = XFA_ValugeCategory(eCategory, m_dwType);
    494   switch (eCategory) {
    495     case FX_LOCALECATEGORY_Null:
    496       if (m_wsValue.IsEmpty()) {
    497         bRet = pFormat->FormatNull(wsFormat, wsResult);
    498       }
    499       break;
    500     case FX_LOCALECATEGORY_Zero:
    501       if (m_wsValue == L"0") {
    502         bRet = pFormat->FormatZero(wsFormat, wsResult);
    503       }
    504       break;
    505     case FX_LOCALECATEGORY_Num:
    506       bRet = pFormat->FormatNum(m_wsValue, wsFormat, wsResult);
    507       break;
    508     case FX_LOCALECATEGORY_Text:
    509       bRet = pFormat->FormatText(m_wsValue, wsFormat, wsResult);
    510       break;
    511     case FX_LOCALECATEGORY_Date:
    512       bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult,
    513                                      FX_DATETIMETYPE_Date);
    514       break;
    515     case FX_LOCALECATEGORY_Time:
    516       bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult,
    517                                      FX_DATETIMETYPE_Time);
    518       break;
    519     case FX_LOCALECATEGORY_DateTime:
    520       bRet = pFormat->FormatDateTime(m_wsValue, wsFormat, wsResult,
    521                                      FX_DATETIMETYPE_DateTime);
    522       break;
    523     default:
    524       wsResult = m_wsValue;
    525       bRet = true;
    526   }
    527   if (!bRet && (eCategory != FX_LOCALECATEGORY_Num ||
    528                 eValueType != XFA_VALUEPICTURE_Display)) {
    529     wsResult = m_wsValue;
    530   }
    531   if (pLocale)
    532     m_pLocaleMgr->SetDefLocale(locale);
    533 
    534   return bRet;
    535 }
    536 
    537 static bool XFA_ValueSplitDateTime(const CFX_WideString& wsDateTime,
    538                                    CFX_WideString& wsDate,
    539                                    CFX_WideString& wsTime) {
    540   wsDate = L"";
    541   wsTime = L"";
    542   if (wsDateTime.IsEmpty()) {
    543     return false;
    544   }
    545   int nSplitIndex = -1;
    546   nSplitIndex = wsDateTime.Find('T');
    547   if (nSplitIndex < 0) {
    548     nSplitIndex = wsDateTime.Find(' ');
    549   }
    550   if (nSplitIndex < 0) {
    551     return false;
    552   }
    553   wsDate = wsDateTime.Left(nSplitIndex);
    554   wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex - 1);
    555   return true;
    556 }
    557 bool CXFA_LocaleValue::ValidateCanonicalValue(const CFX_WideString& wsValue,
    558                                               uint32_t dwVType) {
    559   if (wsValue.IsEmpty()) {
    560     return true;
    561   }
    562   CFX_Unitime dt;
    563   switch (dwVType) {
    564     case XFA_VT_DATE: {
    565       if (ValidateCanonicalDate(wsValue, dt)) {
    566         return true;
    567       }
    568       CFX_WideString wsDate, wsTime;
    569       if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) &&
    570           ValidateCanonicalDate(wsDate, dt)) {
    571         return true;
    572       }
    573       return false;
    574     }
    575     case XFA_VT_TIME: {
    576       if (ValidateCanonicalTime(wsValue)) {
    577         return true;
    578       }
    579       CFX_WideString wsDate, wsTime;
    580       if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) &&
    581           ValidateCanonicalTime(wsTime)) {
    582         return true;
    583       }
    584       return false;
    585     }
    586     case XFA_VT_DATETIME: {
    587       CFX_WideString wsDate, wsTime;
    588       if (XFA_ValueSplitDateTime(wsValue, wsDate, wsTime) &&
    589           ValidateCanonicalDate(wsDate, dt) && ValidateCanonicalTime(wsTime)) {
    590         return true;
    591       }
    592     } break;
    593   }
    594   return true;
    595 }
    596 bool CXFA_LocaleValue::ValidateCanonicalDate(const CFX_WideString& wsDate,
    597                                              CFX_Unitime& unDate) {
    598   const uint16_t LastDay[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    599   const uint16_t wCountY = 4, wCountM = 2, wCountD = 2;
    600   int nLen = wsDate.GetLength();
    601   if (nLen < wCountY || nLen > wCountY + wCountM + wCountD + 2) {
    602     return false;
    603   }
    604   const bool bSymbol = wsDate.Find(0x2D) != -1;
    605   uint16_t wYear = 0;
    606   uint16_t wMonth = 0;
    607   uint16_t wDay = 0;
    608   const FX_WCHAR* pDate = wsDate.c_str();
    609   int nIndex = 0, nStart = 0;
    610   while (pDate[nIndex] != '\0' && nIndex < wCountY) {
    611     if (!FXSYS_isDecimalDigit(pDate[nIndex])) {
    612       return false;
    613     }
    614     wYear = (pDate[nIndex] - '0') + wYear * 10;
    615     nIndex++;
    616   }
    617   if (bSymbol) {
    618     if (pDate[nIndex] != 0x2D) {
    619       return false;
    620     }
    621     nIndex++;
    622   }
    623   nStart = nIndex;
    624   while (pDate[nIndex] != '\0' && nIndex - nStart < wCountM && nIndex < nLen) {
    625     if (!FXSYS_isDecimalDigit(pDate[nIndex])) {
    626       return false;
    627     }
    628     wMonth = (pDate[nIndex] - '0') + wMonth * 10;
    629     nIndex++;
    630   }
    631   if (bSymbol) {
    632     if (pDate[nIndex] != 0x2D) {
    633       return false;
    634     }
    635     nIndex++;
    636   }
    637   nStart = nIndex;
    638   while (pDate[nIndex] != '\0' && nIndex - nStart < wCountD && nIndex < nLen) {
    639     if (!FXSYS_isDecimalDigit(pDate[nIndex])) {
    640       return false;
    641     }
    642     wDay = (pDate[nIndex] - '0') + wDay * 10;
    643     nIndex++;
    644   }
    645   if (nIndex != nLen) {
    646     return false;
    647   }
    648   if (wYear < 1900 || wYear > 2029) {
    649     return false;
    650   }
    651   if (wMonth < 1 || wMonth > 12) {
    652     if (wMonth == 0 && nLen == wCountY) {
    653       return true;
    654     }
    655     return false;
    656   }
    657   if (wDay < 1) {
    658     if (wDay == 0 && (nLen == wCountY + wCountM)) {
    659       return true;
    660     }
    661     return false;
    662   }
    663   if (wMonth == 2) {
    664     if (wYear % 400 == 0 || (wYear % 100 != 0 && wYear % 4 == 0)) {
    665       if (wDay > 29) {
    666         return false;
    667       }
    668     } else {
    669       if (wDay > 28) {
    670         return false;
    671       }
    672     }
    673   } else if (wDay > LastDay[wMonth - 1]) {
    674     return false;
    675   }
    676   CFX_Unitime ut;
    677   ut.Set(wYear, static_cast<uint8_t>(wMonth), static_cast<uint8_t>(wDay));
    678   unDate = unDate + ut;
    679   return true;
    680 }
    681 bool CXFA_LocaleValue::ValidateCanonicalTime(const CFX_WideString& wsTime) {
    682   int nLen = wsTime.GetLength();
    683   if (nLen < 2)
    684     return false;
    685   const uint16_t wCountH = 2;
    686   const uint16_t wCountM = 2;
    687   const uint16_t wCountS = 2;
    688   const uint16_t wCountF = 3;
    689   const bool bSymbol = wsTime.Find(':') != -1;
    690   uint16_t wHour = 0;
    691   uint16_t wMinute = 0;
    692   uint16_t wSecond = 0;
    693   uint16_t wFraction = 0;
    694   const FX_WCHAR* pTime = wsTime.c_str();
    695   int nIndex = 0;
    696   int nStart = 0;
    697   while (nIndex - nStart < wCountH && pTime[nIndex]) {
    698     if (!FXSYS_isDecimalDigit(pTime[nIndex]))
    699       return false;
    700     wHour = pTime[nIndex] - '0' + wHour * 10;
    701     nIndex++;
    702   }
    703   if (bSymbol) {
    704     if (nIndex < nLen && pTime[nIndex] != ':')
    705       return false;
    706     nIndex++;
    707   }
    708   nStart = nIndex;
    709   while (nIndex - nStart < wCountM && nIndex < nLen && pTime[nIndex]) {
    710     if (!FXSYS_isDecimalDigit(pTime[nIndex]))
    711       return false;
    712     wMinute = pTime[nIndex] - '0' + wMinute * 10;
    713     nIndex++;
    714   }
    715   if (bSymbol) {
    716     if (nIndex < nLen && pTime[nIndex] != ':')
    717       return false;
    718     nIndex++;
    719   }
    720   nStart = nIndex;
    721   while (nIndex - nStart < wCountS && nIndex < nLen && pTime[nIndex]) {
    722     if (!FXSYS_isDecimalDigit(pTime[nIndex]))
    723       return false;
    724     wSecond = pTime[nIndex] - '0' + wSecond * 10;
    725     nIndex++;
    726   }
    727   if (wsTime.Find('.') > 0) {
    728     if (pTime[nIndex] != '.')
    729       return false;
    730     nIndex++;
    731     nStart = nIndex;
    732     while (nIndex - nStart < wCountF && nIndex < nLen && pTime[nIndex]) {
    733       if (!FXSYS_isDecimalDigit(pTime[nIndex]))
    734         return false;
    735       wFraction = pTime[nIndex] - '0' + wFraction * 10;
    736       nIndex++;
    737     }
    738   }
    739   if (nIndex < nLen) {
    740     if (pTime[nIndex] == 'Z') {
    741       nIndex++;
    742     } else if (pTime[nIndex] == '-' || pTime[nIndex] == '+') {
    743       int16_t nOffsetH = 0;
    744       int16_t nOffsetM = 0;
    745       nIndex++;
    746       nStart = nIndex;
    747       while (nIndex - nStart < wCountH && nIndex < nLen && pTime[nIndex]) {
    748         if (!FXSYS_isDecimalDigit(pTime[nIndex]))
    749           return false;
    750         nOffsetH = pTime[nIndex] - '0' + nOffsetH * 10;
    751         nIndex++;
    752       }
    753       if (bSymbol) {
    754         if (nIndex < nLen && pTime[nIndex] != ':')
    755           return false;
    756         nIndex++;
    757       }
    758       nStart = nIndex;
    759       while (nIndex - nStart < wCountM && nIndex < nLen && pTime[nIndex]) {
    760         if (!FXSYS_isDecimalDigit(pTime[nIndex]))
    761           return false;
    762         nOffsetM = pTime[nIndex] - '0' + nOffsetM * 10;
    763         nIndex++;
    764       }
    765       if (nOffsetH > 12 || nOffsetM >= 60)
    766         return false;
    767     }
    768   }
    769   return nIndex == nLen && wHour < 24 && wMinute < 60 && wSecond < 60 &&
    770          wFraction <= 999;
    771 }
    772 bool CXFA_LocaleValue::ValidateCanonicalDateTime(
    773     const CFX_WideString& wsDateTime) {
    774   CFX_WideString wsDate, wsTime;
    775   if (wsDateTime.IsEmpty()) {
    776     return false;
    777   }
    778   int nSplitIndex = -1;
    779   nSplitIndex = wsDateTime.Find('T');
    780   if (nSplitIndex < 0) {
    781     nSplitIndex = wsDateTime.Find(' ');
    782   }
    783   if (nSplitIndex < 0) {
    784     return false;
    785   }
    786   wsDate = wsDateTime.Left(nSplitIndex);
    787   wsTime = wsDateTime.Right(wsDateTime.GetLength() - nSplitIndex - 1);
    788   CFX_Unitime dt;
    789   return ValidateCanonicalDate(wsDate, dt) && ValidateCanonicalTime(wsTime);
    790 }
    791 bool CXFA_LocaleValue::ParsePatternValue(const CFX_WideString& wsValue,
    792                                          const CFX_WideString& wsPattern,
    793                                          IFX_Locale* pLocale) {
    794   IFX_Locale* locale = m_pLocaleMgr->GetDefLocale();
    795   if (pLocale)
    796     m_pLocaleMgr->SetDefLocale(pLocale);
    797 
    798   auto pFormat = pdfium::MakeUnique<CFX_FormatString>(m_pLocaleMgr, false);
    799   std::vector<CFX_WideString> wsPatterns;
    800   pFormat->SplitFormatString(wsPattern, wsPatterns);
    801   bool bRet = false;
    802   int32_t iCount = pdfium::CollectionSize<int32_t>(wsPatterns);
    803   for (int32_t i = 0; i < iCount && !bRet; i++) {
    804     CFX_WideString wsFormat = wsPatterns[i];
    805     FX_LOCALECATEGORY eCategory = pFormat->GetCategory(wsFormat);
    806     eCategory = XFA_ValugeCategory(eCategory, m_dwType);
    807     switch (eCategory) {
    808       case FX_LOCALECATEGORY_Null:
    809         bRet = pFormat->ParseNull(wsValue, wsFormat);
    810         if (bRet) {
    811           m_wsValue.clear();
    812         }
    813         break;
    814       case FX_LOCALECATEGORY_Zero:
    815         bRet = pFormat->ParseZero(wsValue, wsFormat);
    816         if (bRet)
    817           m_wsValue = L"0";
    818         break;
    819       case FX_LOCALECATEGORY_Num: {
    820         CFX_WideString fNum;
    821         bRet = pFormat->ParseNum(wsValue, wsFormat, fNum);
    822         if (bRet) {
    823           m_wsValue = fNum;
    824         }
    825         break;
    826       }
    827       case FX_LOCALECATEGORY_Text:
    828         bRet = pFormat->ParseText(wsValue, wsFormat, m_wsValue);
    829         break;
    830       case FX_LOCALECATEGORY_Date: {
    831         CFX_Unitime dt;
    832         bRet = ValidateCanonicalDate(wsValue, dt);
    833         if (!bRet) {
    834           bRet = pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Date,
    835                                         dt);
    836         }
    837         if (bRet) {
    838           SetDate(dt);
    839         }
    840         break;
    841       }
    842       case FX_LOCALECATEGORY_Time: {
    843         CFX_Unitime dt;
    844         bRet =
    845             pFormat->ParseDateTime(wsValue, wsFormat, FX_DATETIMETYPE_Time, dt);
    846         if (bRet) {
    847           SetTime(dt);
    848         }
    849         break;
    850       }
    851       case FX_LOCALECATEGORY_DateTime: {
    852         CFX_Unitime dt;
    853         bRet = pFormat->ParseDateTime(wsValue, wsFormat,
    854                                       FX_DATETIMETYPE_DateTime, dt);
    855         if (bRet) {
    856           SetDateTime(dt);
    857         }
    858         break;
    859       }
    860       default:
    861         m_wsValue = wsValue;
    862         bRet = true;
    863         break;
    864     }
    865   }
    866   if (!bRet)
    867     m_wsValue = wsValue;
    868 
    869   if (pLocale)
    870     m_pLocaleMgr->SetDefLocale(locale);
    871 
    872   return bRet;
    873 }
    874 
    875 void CXFA_LocaleValue::GetNumbericFormat(CFX_WideString& wsFormat,
    876                                          int32_t nIntLen,
    877                                          int32_t nDecLen,
    878                                          bool bSign) {
    879   ASSERT(wsFormat.IsEmpty());
    880   ASSERT(nIntLen >= -1 && nDecLen >= -1);
    881   int32_t nTotalLen = (nIntLen >= 0 ? nIntLen : 2) + (bSign ? 1 : 0) +
    882                       (nDecLen >= 0 ? nDecLen : 2) + (nDecLen == 0 ? 0 : 1);
    883   FX_WCHAR* lpBuf = wsFormat.GetBuffer(nTotalLen);
    884   int32_t nPos = 0;
    885   if (bSign) {
    886     lpBuf[nPos++] = L's';
    887   }
    888   if (nIntLen == -1) {
    889     lpBuf[nPos++] = L'z';
    890     lpBuf[nPos++] = L'*';
    891   } else {
    892     while (nIntLen) {
    893       lpBuf[nPos++] = L'z';
    894       nIntLen--;
    895     }
    896   }
    897   if (nDecLen != 0) {
    898     lpBuf[nPos++] = L'.';
    899   }
    900   if (nDecLen == -1) {
    901     lpBuf[nPos++] = L'z';
    902     lpBuf[nPos++] = L'*';
    903   } else {
    904     while (nDecLen) {
    905       lpBuf[nPos++] = L'z';
    906       nDecLen--;
    907     }
    908   }
    909   wsFormat.ReleaseBuffer(nTotalLen);
    910 }
    911 bool CXFA_LocaleValue::ValidateNumericTemp(CFX_WideString& wsNumeric,
    912                                            CFX_WideString& wsFormat,
    913                                            IFX_Locale* pLocale,
    914                                            int32_t* pos) {
    915   if (wsFormat.IsEmpty() || wsNumeric.IsEmpty()) {
    916     return true;
    917   }
    918   const FX_WCHAR* pNum = wsNumeric.c_str();
    919   const FX_WCHAR* pFmt = wsFormat.c_str();
    920   int32_t n = 0, nf = 0;
    921   FX_WCHAR c = pNum[n];
    922   FX_WCHAR cf = pFmt[nf];
    923   if (cf == L's') {
    924     if (c == L'-' || c == L'+') {
    925       ++n;
    926     }
    927     ++nf;
    928   }
    929   bool bLimit = true;
    930   int32_t nCount = wsNumeric.GetLength();
    931   int32_t nCountFmt = wsFormat.GetLength();
    932   while (n < nCount && (bLimit ? nf < nCountFmt : true) &&
    933          FXSYS_isDecimalDigit(c = pNum[n])) {
    934     if (bLimit == true) {
    935       if ((cf = pFmt[nf]) == L'*') {
    936         bLimit = false;
    937       } else if (cf == L'z') {
    938         nf++;
    939       } else {
    940         return false;
    941       }
    942     }
    943     n++;
    944   }
    945   if (n == nCount) {
    946     return true;
    947   }
    948   if (nf == nCountFmt) {
    949     return false;
    950   }
    951   while (nf < nCountFmt && (cf = pFmt[nf]) != L'.') {
    952     ASSERT(cf == L'z' || cf == L'*');
    953     ++nf;
    954   }
    955   CFX_WideString wsDecimalSymbol;
    956   if (pLocale) {
    957     pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDecimalSymbol);
    958   } else {
    959     wsDecimalSymbol = CFX_WideString(L'.');
    960   }
    961   if (pFmt[nf] != L'.') {
    962     return false;
    963   }
    964   if (wsDecimalSymbol != CFX_WideStringC(c) && c != L'.') {
    965     return false;
    966   }
    967   ++nf;
    968   ++n;
    969   bLimit = true;
    970   while (n < nCount && (bLimit ? nf < nCountFmt : true) &&
    971          FXSYS_isDecimalDigit(c = pNum[n])) {
    972     if (bLimit == true) {
    973       if ((cf = pFmt[nf]) == L'*') {
    974         bLimit = false;
    975       } else if (cf == L'z') {
    976         nf++;
    977       } else {
    978         return false;
    979       }
    980     }
    981     n++;
    982   }
    983   return n == nCount;
    984 }
    985