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