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