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};
CXFA_LocaleValue()33 CXFA_LocaleValue::CXFA_LocaleValue() {
34 m_dwType = XFA_VT_NULL;
35 m_bValid = TRUE;
36 m_pLocaleMgr = NULL;
37 }
CXFA_LocaleValue(const CXFA_LocaleValue & value)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 }
CXFA_LocaleValue(FX_DWORD dwType,CXFA_LocaleMgr * pLocaleMgr)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 }
CXFA_LocaleValue(FX_DWORD dwType,const CFX_WideString & wsValue,CXFA_LocaleMgr * pLocaleMgr)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 }
CXFA_LocaleValue(FX_DWORD dwType,const CFX_WideString & wsValue,const CFX_WideString & wsFormat,IFX_Locale * pLocale,CXFA_LocaleMgr * pLocaleMgr)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 }
operator =(const CXFA_LocaleValue & value)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 }
~CXFA_LocaleValue()75 CXFA_LocaleValue::~CXFA_LocaleValue() {}
XFA_ValugeCategory(FX_LOCALECATEGORY eCategory,FX_DWORD dwValueType)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 }
ValidateValue(const CFX_WideString & wsValue,const CFX_WideString & wsPattern,IFX_Locale * pLocale,CFX_WideString * pMatchFormat)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 }
GetValue() const191 CFX_WideString CXFA_LocaleValue::GetValue() const {
192 return m_wsValue;
193 }
GetType() const194 FX_DWORD CXFA_LocaleValue::GetType() const {
195 return m_dwType;
196 }
SetValue(const CFX_WideString & wsValue,FX_DWORD dwType)197 void CXFA_LocaleValue::SetValue(const CFX_WideString& wsValue,
198 FX_DWORD dwType) {
199 m_wsValue = wsValue;
200 m_dwType = dwType;
201 }
GetText() const202 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 }
GetNum() const208 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 }
GetDoubleNum() const283 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 }
GetDate() const358 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 }
GetTime() const366 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 }
GetDateTime() const375 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 }
SetText(const CFX_WideString & wsText)387 FX_BOOL CXFA_LocaleValue::SetText(const CFX_WideString& wsText) {
388 m_dwType = XFA_VT_TEXT;
389 m_wsValue = wsText;
390 return TRUE;
391 }
SetText(const CFX_WideString & wsText,const CFX_WideString & wsFormat,IFX_Locale * pLocale)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 }
SetNum(FX_FLOAT fNum)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 }
SetNum(const CFX_WideString & wsNum,const CFX_WideString & wsFormat,IFX_Locale * pLocale)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 }
SetDate(const CFX_Unitime & d)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 }
SetDate(const CFX_WideString & wsDate,const CFX_WideString & wsFormat,IFX_Locale * pLocale)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 }
SetTime(const CFX_Unitime & t)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 }
SetTime(const CFX_WideString & wsTime,const CFX_WideString & wsFormat,IFX_Locale * pLocale)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 }
SetDateTime(const CFX_Unitime & dt)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 }
SetDateTime(const CFX_WideString & wsDateTime,const CFX_WideString & wsFormat,IFX_Locale * pLocale)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 }
FormatPatterns(CFX_WideString & wsResult,const CFX_WideString & wsFormat,IFX_Locale * pLocale,XFA_VALUEPICTURE eValueType) const455 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 }
FormatSinglePattern(CFX_WideString & wsResult,const CFX_WideString & wsFormat,IFX_Locale * pLocale,XFA_VALUEPICTURE eValueType) const474 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 }
XFA_ValueSplitDateTime(const CFX_WideString & wsDateTime,CFX_WideString & wsDate,CFX_WideString & wsTime)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 }
ValidateCanonicalValue(const CFX_WideString & wsValue,FX_DWORD dwVType)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 }
ValidateCanonicalDate(const CFX_WideString & wsDate,CFX_Unitime & unDate)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 }
ValidateCanonicalTime(const CFX_WideString & wsTime)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 }
ValidateCanonicalDateTime(const CFX_WideString & wsDateTime)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 }
ParsePatternValue(const CFX_WideString & wsValue,const CFX_WideString & wsPattern,IFX_Locale * pLocale)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 }
GetNumbericFormat(CFX_WideString & wsFormat,int32_t nIntLen,int32_t nDecLen,FX_BOOL bSign)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 }
ValidateNumericTemp(CFX_WideString & wsNumeric,CFX_WideString & wsFormat,IFX_Locale * pLocale,int32_t * pos)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