• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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};
CXFA_LocaleValue()36 CXFA_LocaleValue::CXFA_LocaleValue() {
37   m_dwType = XFA_VT_NULL;
38   m_bValid = true;
39   m_pLocaleMgr = nullptr;
40 }
CXFA_LocaleValue(const CXFA_LocaleValue & value)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 }
CXFA_LocaleValue(uint32_t dwType,CXFA_LocaleMgr * pLocaleMgr)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 }
CXFA_LocaleValue(uint32_t dwType,const CFX_WideString & wsValue,CXFA_LocaleMgr * pLocaleMgr)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 }
CXFA_LocaleValue(uint32_t dwType,const CFX_WideString & wsValue,const CFX_WideString & wsFormat,IFX_Locale * pLocale,CXFA_LocaleMgr * pLocaleMgr)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 }
operator =(const CXFA_LocaleValue & value)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 }
~CXFA_LocaleValue()78 CXFA_LocaleValue::~CXFA_LocaleValue() {}
XFA_ValugeCategory(FX_LOCALECATEGORY eCategory,uint32_t dwValueType)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 
ValidateValue(const CFX_WideString & wsValue,const CFX_WideString & wsPattern,IFX_Locale * pLocale,CFX_WideString * pMatchFormat)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 
GetValue() const196 CFX_WideString CXFA_LocaleValue::GetValue() const {
197   return m_wsValue;
198 }
GetType() const199 uint32_t CXFA_LocaleValue::GetType() const {
200   return m_dwType;
201 }
SetValue(const CFX_WideString & wsValue,uint32_t dwType)202 void CXFA_LocaleValue::SetValue(const CFX_WideString& wsValue,
203                                 uint32_t dwType) {
204   m_wsValue = wsValue;
205   m_dwType = dwType;
206 }
GetText() const207 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 }
GetNum() const213 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 }
GetDoubleNum() const289 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 }
GetDate() const365 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 }
GetTime() const373 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 }
GetDateTime() const383 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 }
SetText(const CFX_WideString & wsText)396 bool CXFA_LocaleValue::SetText(const CFX_WideString& wsText) {
397   m_dwType = XFA_VT_TEXT;
398   m_wsValue = wsText;
399   return true;
400 }
SetText(const CFX_WideString & wsText,const CFX_WideString & wsFormat,IFX_Locale * pLocale)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 }
SetNum(FX_FLOAT fNum)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 }
SetNum(const CFX_WideString & wsNum,const CFX_WideString & wsFormat,IFX_Locale * pLocale)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 }
SetDate(const CFX_Unitime & d)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 }
SetDate(const CFX_WideString & wsDate,const CFX_WideString & wsFormat,IFX_Locale * pLocale)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 }
SetTime(const CFX_Unitime & t)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 }
SetTime(const CFX_WideString & wsTime,const CFX_WideString & wsFormat,IFX_Locale * pLocale)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 }
SetDateTime(const CFX_Unitime & dt)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 }
SetDateTime(const CFX_WideString & wsDateTime,const CFX_WideString & wsFormat,IFX_Locale * pLocale)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 
FormatPatterns(CFX_WideString & wsResult,const CFX_WideString & wsFormat,IFX_Locale * pLocale,XFA_VALUEPICTURE eValueType) const465 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 
FormatSinglePattern(CFX_WideString & wsResult,const CFX_WideString & wsFormat,IFX_Locale * pLocale,XFA_VALUEPICTURE eValueType) const481 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 
XFA_ValueSplitDateTime(const CFX_WideString & wsDateTime,CFX_WideString & wsDate,CFX_WideString & wsTime)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 }
ValidateCanonicalValue(const CFX_WideString & wsValue,uint32_t dwVType)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 }
ValidateCanonicalDate(const CFX_WideString & wsDate,CFX_Unitime & unDate)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 }
ValidateCanonicalTime(const CFX_WideString & wsTime)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 }
ValidateCanonicalDateTime(const CFX_WideString & wsDateTime)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 }
ParsePatternValue(const CFX_WideString & wsValue,const CFX_WideString & wsPattern,IFX_Locale * pLocale)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 
GetNumbericFormat(CFX_WideString & wsFormat,int32_t nIntLen,int32_t nDecLen,bool bSign)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 }
ValidateNumericTemp(CFX_WideString & wsNumeric,CFX_WideString & wsFormat,IFX_Locale * pLocale,int32_t * pos)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