Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cxfa_localevalue.cpp
Go to the documentation of this file.
1// Copyright 2014 The PDFium Authors
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/cxfa_localevalue.h"
8
9#include <wchar.h>
10
11#include <memory>
12#include <utility>
13#include <vector>
14
15#include "core/fxcrt/cfx_datetime.h"
16#include "core/fxcrt/fx_extension.h"
17#include "third_party/base/check.h"
18#include "third_party/base/containers/span.h"
19#include "xfa/fgas/crt/cfgas_stringformatter.h"
20#include "xfa/fxfa/parser/cxfa_document.h"
21#include "xfa/fxfa/parser/cxfa_localemgr.h"
22#include "xfa/fxfa/parser/xfa_utils.h"
23
24namespace {
25
26CFGAS_StringFormatter::Category ValueCategory(
28 CXFA_LocaleValue::ValueType eValueType) {
30 return eCategory;
31
32 switch (eValueType) {
46 default:
48 }
49}
50
51bool ValueSplitDateTime(const WideString& wsDateTime,
52 WideString& wsDate,
53 WideString& wsTime) {
54 wsDate.clear();
55 wsTime.clear();
56 if (wsDateTime.IsEmpty())
57 return false;
58
59 auto nSplitIndex = wsDateTime.Find('T');
60 if (!nSplitIndex.has_value())
61 nSplitIndex = wsDateTime.Find(' ');
62 if (!nSplitIndex.has_value())
63 return false;
64
65 wsDate = wsDateTime.First(nSplitIndex.value());
66 wsTime = wsDateTime.Last(wsDateTime.GetLength() - nSplitIndex.value() - 1);
67 return true;
68}
69
70class ScopedLocale {
71 CPPGC_STACK_ALLOCATED(); // Raw/Unowned pointers allowed.
72
73 public:
74 ScopedLocale(CXFA_LocaleMgr* pLocaleMgr, GCedLocaleIface* pNewLocale)
75 : m_pLocaleMgr(pLocaleMgr),
76 m_pNewLocale(pNewLocale),
77 m_pOrigLocale(pNewLocale ? m_pLocaleMgr->GetDefLocale() : nullptr) {
78 if (m_pNewLocale)
79 m_pLocaleMgr->SetDefLocale(pNewLocale);
80 }
81
82 ~ScopedLocale() {
83 if (m_pNewLocale)
84 m_pLocaleMgr->SetDefLocale(m_pOrigLocale);
85 }
86
87 ScopedLocale(const ScopedLocale& that) = delete;
88 ScopedLocale& operator=(const ScopedLocale& that) = delete;
89
90 private:
91 UnownedPtr<CXFA_LocaleMgr> const m_pLocaleMgr; // Ok, stack-only.
92 UnownedPtr<GCedLocaleIface> const m_pNewLocale; // Ok, stack-only.
93 UnownedPtr<GCedLocaleIface> const m_pOrigLocale; // Ok, stack-only.
94};
95
96} // namespace
97
99
100CXFA_LocaleValue::CXFA_LocaleValue(ValueType eType, CXFA_LocaleMgr* pLocaleMgr)
102 m_eType(eType),
103 m_bValid(m_eType != ValueType::kNull) {}
104
106 const WideString& wsValue,
107 CXFA_LocaleMgr* pLocaleMgr)
110 m_eType(eType),
111 m_bValid(ValidateCanonicalValue(wsValue, eType)) {}
112
114 const WideString& wsValue,
115 const WideString& wsFormat,
116 GCedLocaleIface* pLocale,
117 CXFA_LocaleMgr* pLocaleMgr)
119 m_eType(eType),
120 m_bValid(ParsePatternValue(wsValue, wsFormat, pLocale)) {}
121
123
125 default;
126
128
129bool CXFA_LocaleValue::ValidateValue(const WideString& wsValue,
130 const WideString& wsPattern,
131 GCedLocaleIface* pLocale,
132 WideString* pMatchFormat) {
133 if (!m_pLocaleMgr)
134 return false;
135
136 ScopedLocale scoped_locale(m_pLocaleMgr, pLocale);
137 std::vector<WideString> wsPatterns =
138 CFGAS_StringFormatter::SplitOnBars(wsPattern);
139
140 WideString wsOutput;
141 bool bRet = false;
142 size_t i = 0;
143 for (; !bRet && i < wsPatterns.size(); i++) {
144 const WideString& wsFormat = wsPatterns[i];
145 auto pFormat = std::make_unique<CFGAS_StringFormatter>(wsFormat);
146 switch (ValueCategory(pFormat->GetCategory(), m_eType)) {
148 bRet = pFormat->ParseNull(wsValue);
149 if (!bRet)
150 bRet = wsValue.IsEmpty();
151 break;
153 bRet = pFormat->ParseZero(wsValue);
154 if (!bRet)
155 bRet = wsValue.EqualsASCII("0");
156 break;
158 WideString fNum;
159 bRet = pFormat->ParseNum(m_pLocaleMgr, wsValue, &fNum);
160 if (!bRet)
161 bRet = pFormat->FormatNum(m_pLocaleMgr, wsValue, &wsOutput);
162 break;
163 }
165 bRet = pFormat->ParseText(wsValue, &wsOutput);
166 wsOutput.clear();
167 if (!bRet)
168 bRet = pFormat->FormatText(wsValue, &wsOutput);
169 break;
171 CFX_DateTime dt;
172 bRet = ValidateCanonicalDate(wsValue, &dt);
173 if (!bRet) {
174 bRet = pFormat->ParseDateTime(
175 m_pLocaleMgr, wsValue, CFGAS_StringFormatter::DateTimeType::kDate,
176 &dt);
177 if (!bRet) {
178 bRet = pFormat->FormatDateTime(
179 m_pLocaleMgr, wsValue,
180 CFGAS_StringFormatter::DateTimeType::kDate, &wsOutput);
181 }
182 }
183 break;
184 }
186 CFX_DateTime dt;
187 bRet = pFormat->ParseDateTime(
188 m_pLocaleMgr, wsValue, CFGAS_StringFormatter::DateTimeType::kTime,
189 &dt);
190 if (!bRet) {
191 bRet = pFormat->FormatDateTime(
192 m_pLocaleMgr, wsValue, CFGAS_StringFormatter::DateTimeType::kTime,
193 &wsOutput);
194 }
195 break;
196 }
198 CFX_DateTime dt;
199 bRet = pFormat->ParseDateTime(
200 m_pLocaleMgr, wsValue,
201 CFGAS_StringFormatter::DateTimeType::kDateTime, &dt);
202 if (!bRet) {
203 bRet = pFormat->FormatDateTime(
204 m_pLocaleMgr, wsValue,
205 CFGAS_StringFormatter::DateTimeType::kDateTime, &wsOutput);
206 }
207 break;
208 }
209 default:
210 bRet = false;
211 break;
212 }
213 }
214 if (bRet && pMatchFormat)
215 *pMatchFormat = wsPatterns[i - 1];
216 return bRet;
217}
218
220 if (!m_bValid || (m_eType != CXFA_LocaleValue::ValueType::kBoolean &&
224 return 0;
225 }
226
227 return wcstod(m_wsValue.c_str(), nullptr);
228}
229
231 if (!m_bValid || m_eType != CXFA_LocaleValue::ValueType::kDate)
232 return CFX_DateTime();
233
234 CFX_DateTime dt;
235 FX_DateFromCanonical(m_wsValue.span(), &dt);
236 return dt;
237}
238
240 if (!m_bValid || m_eType != CXFA_LocaleValue::ValueType::kTime)
241 return CFX_DateTime();
242
243 CFX_DateTime dt;
244 FX_TimeFromCanonical(m_pLocaleMgr->GetDefLocale(), m_wsValue.span(), &dt);
245 return dt;
246}
247
250 m_wsValue = WideString::Format(L"%04d-%02d-%02d", d.GetYear(), d.GetMonth(),
251 d.GetDay());
252 return true;
253}
254
255bool CXFA_LocaleValue::SetTime(const CFX_DateTime& t) {
257 m_wsValue = WideString::Format(L"%02d:%02d:%02d", t.GetHour(), t.GetMinute(),
258 t.GetSecond());
259 if (t.GetMillisecond() > 0)
260 m_wsValue += WideString::Format(L"%:03d", t.GetMillisecond());
261 return true;
262}
263
264bool CXFA_LocaleValue::SetDateTime(const CFX_DateTime& dt) {
266 m_wsValue = WideString::Format(L"%04d-%02d-%02dT%02d:%02d:%02d", dt.GetYear(),
267 dt.GetMonth(), dt.GetDay(), dt.GetHour(),
268 dt.GetMinute(), dt.GetSecond());
269 if (dt.GetMillisecond() > 0)
270 m_wsValue += WideString::Format(L"%:03d", dt.GetMillisecond());
271 return true;
272}
273
274bool CXFA_LocaleValue::FormatPatterns(WideString& wsResult,
275 const WideString& wsFormat,
276 GCedLocaleIface* pLocale,
277 XFA_ValuePicture eValueType) const {
278 wsResult.clear();
279 for (const auto& pattern : CFGAS_StringFormatter::SplitOnBars(wsFormat)) {
280 if (FormatSinglePattern(wsResult, pattern, pLocale, eValueType))
281 return true;
282 }
283 return false;
284}
285
286bool CXFA_LocaleValue::FormatSinglePattern(WideString& wsResult,
287 const WideString& wsFormat,
288 GCedLocaleIface* pLocale,
289 XFA_ValuePicture eValueType) const {
290 if (!m_pLocaleMgr)
291 return false;
292
293 ScopedLocale scoped_locale(m_pLocaleMgr, pLocale);
294 wsResult.clear();
295
296 bool bRet = false;
297 auto pFormat = std::make_unique<CFGAS_StringFormatter>(wsFormat);
299 ValueCategory(pFormat->GetCategory(), m_eType);
300 switch (eCategory) {
302 if (m_wsValue.IsEmpty())
303 bRet = pFormat->FormatNull(&wsResult);
304 break;
306 if (m_wsValue.EqualsASCII("0"))
307 bRet = pFormat->FormatZero(&wsResult);
308 break;
309 case CFGAS_StringFormatter::Category::kNum:
310 bRet = pFormat->FormatNum(m_pLocaleMgr, m_wsValue, &wsResult);
311 break;
312 case CFGAS_StringFormatter::Category::kText:
313 bRet = pFormat->FormatText(m_wsValue, &wsResult);
314 break;
315 case CFGAS_StringFormatter::Category::kDate:
316 bRet = pFormat->FormatDateTime(m_pLocaleMgr, m_wsValue,
317 CFGAS_StringFormatter::DateTimeType::kDate,
318 &wsResult);
319 break;
320 case CFGAS_StringFormatter::Category::kTime:
321 bRet = pFormat->FormatDateTime(m_pLocaleMgr, m_wsValue,
322 CFGAS_StringFormatter::DateTimeType::kTime,
323 &wsResult);
324 break;
325 case CFGAS_StringFormatter::Category::kDateTime:
326 bRet = pFormat->FormatDateTime(
327 m_pLocaleMgr, m_wsValue,
328 CFGAS_StringFormatter::DateTimeType::kDateTime, &wsResult);
329 break;
330 default:
331 wsResult = m_wsValue;
332 bRet = true;
333 }
334 if (!bRet && (eCategory != CFGAS_StringFormatter::Category::kNum ||
335 eValueType != XFA_ValuePicture::kDisplay)) {
336 wsResult = m_wsValue;
337 }
338
339 return bRet;
340}
341
342bool CXFA_LocaleValue::ValidateCanonicalValue(const WideString& wsValue,
343 ValueType eType) {
344 if (wsValue.IsEmpty())
345 return true;
346
347 CFX_DateTime dt;
348 switch (eType) {
349 case ValueType::kDate: {
350 if (ValidateCanonicalDate(wsValue, &dt))
351 return true;
352
353 WideString wsDate;
354 WideString wsTime;
355 if (ValueSplitDateTime(wsValue, wsDate, wsTime) &&
356 ValidateCanonicalDate(wsDate, &dt)) {
357 return true;
358 }
359 return false;
360 }
361 case ValueType::kTime: {
362 if (ValidateCanonicalTime(wsValue))
363 return true;
364
365 WideString wsDate;
366 WideString wsTime;
367 if (ValueSplitDateTime(wsValue, wsDate, wsTime) &&
368 ValidateCanonicalTime(wsTime)) {
369 return true;
370 }
371 return false;
372 }
374 WideString wsDate, wsTime;
375 if (ValueSplitDateTime(wsValue, wsDate, wsTime) &&
376 ValidateCanonicalDate(wsDate, &dt) && ValidateCanonicalTime(wsTime)) {
377 return true;
378 }
379 } break;
380 default: {
381 break;
382 }
383 }
384 return true;
385}
386
387bool CXFA_LocaleValue::ValidateCanonicalDate(const WideString& wsDate,
388 CFX_DateTime* unDate) {
389 static const uint8_t LastDay[12] = {31, 28, 31, 30, 31, 30,
390 31, 31, 30, 31, 30, 31};
391 static const uint16_t wCountY = 4;
392 static const uint16_t wCountM = 2;
393 static const uint16_t wCountD = 2;
394 pdfium::span<const wchar_t> spDate = wsDate.span();
395 if (spDate.size() < wCountY ||
396 spDate.size() > wCountY + wCountM + wCountD + 2) {
397 return false;
398 }
399 const bool bSymbol = wsDate.Contains(0x2D);
400 uint16_t wYear = 0;
401 uint16_t wMonth = 0;
402 uint16_t wDay = 0;
403 size_t nIndex = 0;
404 size_t nStart = 0;
405 while (nIndex < wCountY && spDate[nIndex] != '\0') {
406 if (!FXSYS_IsDecimalDigit(spDate[nIndex]))
407 return false;
408
409 wYear = (spDate[nIndex] - '0') + wYear * 10;
410 nIndex++;
411 }
412 if (bSymbol) {
413 if (nIndex >= spDate.size() || spDate[nIndex] != 0x2D)
414 return false;
415 nIndex++;
416 }
417
418 nStart = nIndex;
419 while (nIndex < spDate.size() && spDate[nIndex] != '\0' &&
420 nIndex - nStart < wCountM) {
421 if (!FXSYS_IsDecimalDigit(spDate[nIndex]))
422 return false;
423
424 wMonth = (spDate[nIndex] - '0') + wMonth * 10;
425 nIndex++;
426 }
427 if (bSymbol) {
428 if (nIndex >= spDate.size() || spDate[nIndex] != 0x2D)
429 return false;
430 nIndex++;
431 }
432
433 nStart = nIndex;
434 while (nIndex < spDate.size() && spDate[nIndex] != '\0' &&
435 nIndex - nStart < wCountD) {
436 if (!FXSYS_IsDecimalDigit(spDate[nIndex]))
437 return false;
438
439 wDay = (spDate[nIndex] - '0') + wDay * 10;
440 nIndex++;
441 }
442 if (nIndex != spDate.size())
443 return false;
444 if (wYear < 1900 || wYear > 2029)
445 return false;
446 if (wMonth < 1 || wMonth > 12)
447 return wMonth == 0 && spDate.size() == wCountY;
448 if (wDay < 1)
449 return wDay == 0 && spDate.size() == wCountY + wCountM;
450 if (wMonth == 2) {
451 if (wYear % 400 == 0 || (wYear % 100 != 0 && wYear % 4 == 0)) {
452 if (wDay > 29)
453 return false;
454 } else if (wDay > 28) {
455 return false;
456 }
457 } else if (wDay > LastDay[wMonth - 1]) {
458 return false;
459 }
460
461 unDate->SetDate(wYear, static_cast<uint8_t>(wMonth),
462 static_cast<uint8_t>(wDay));
463 return true;
464}
465
466bool CXFA_LocaleValue::ValidateCanonicalTime(const WideString& wsTime) {
467 pdfium::span<const wchar_t> spTime = wsTime.span();
468 if (spTime.size() < 2)
469 return false;
470
471 const uint16_t wCountH = 2;
472 const uint16_t wCountM = 2;
473 const uint16_t wCountS = 2;
474 const uint16_t wCountF = 3;
475 const bool bSymbol = wsTime.Contains(':');
476 uint16_t wHour = 0;
477 uint16_t wMinute = 0;
478 uint16_t wSecond = 0;
479 uint16_t wFraction = 0;
480 size_t nIndex = 0;
481 size_t nStart = 0;
482 while (nIndex - nStart < wCountH && spTime[nIndex]) {
483 if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
484 return false;
485 wHour = spTime[nIndex] - '0' + wHour * 10;
486 nIndex++;
487 }
488 if (bSymbol) {
489 if (nIndex < spTime.size() && spTime[nIndex] != ':')
490 return false;
491 nIndex++;
492 }
493
494 nStart = nIndex;
495 while (nIndex < spTime.size() && spTime[nIndex] != '\0' &&
496 nIndex - nStart < wCountM) {
497 if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
498 return false;
499 wMinute = spTime[nIndex] - '0' + wMinute * 10;
500 nIndex++;
501 }
502 if (bSymbol) {
503 if (nIndex >= spTime.size() || spTime[nIndex] != ':')
504 return false;
505 nIndex++;
506 }
507 nStart = nIndex;
508 while (nIndex < spTime.size() && spTime[nIndex] != '\0' &&
509 nIndex - nStart < wCountS) {
510 if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
511 return false;
512 wSecond = spTime[nIndex] - '0' + wSecond * 10;
513 nIndex++;
514 }
515 auto pos = wsTime.Find('.');
516 if (pos.has_value() && pos.value() != 0) {
517 if (nIndex >= spTime.size() || spTime[nIndex] != '.')
518 return false;
519 nIndex++;
520 nStart = nIndex;
521 while (nIndex < spTime.size() && spTime[nIndex] != '\0' &&
522 nIndex - nStart < wCountF) {
523 if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
524 return false;
525 wFraction = spTime[nIndex] - '0' + wFraction * 10;
526 nIndex++;
527 }
528 }
529 if (nIndex < spTime.size()) {
530 if (spTime[nIndex] == 'Z') {
531 nIndex++;
532 } else if (spTime[nIndex] == '-' || spTime[nIndex] == '+') {
533 int16_t nOffsetH = 0;
534 int16_t nOffsetM = 0;
535 nIndex++;
536 nStart = nIndex;
537 while (nIndex < spTime.size() && spTime[nIndex] != '\0' &&
538 nIndex - nStart < wCountH) {
539 if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
540 return false;
541 nOffsetH = spTime[nIndex] - '0' + nOffsetH * 10;
542 nIndex++;
543 }
544 if (bSymbol) {
545 if (nIndex >= spTime.size() || spTime[nIndex] != ':')
546 return false;
547 nIndex++;
548 }
549 nStart = nIndex;
550 while (nIndex < spTime.size() && spTime[nIndex] != '\0' &&
551 nIndex - nStart < wCountM) {
552 if (!FXSYS_IsDecimalDigit(spTime[nIndex]))
553 return false;
554 nOffsetM = spTime[nIndex] - '0' + nOffsetM * 10;
555 nIndex++;
556 }
557 if (nOffsetH > 12 || nOffsetM >= 60)
558 return false;
559 }
560 }
561 return nIndex == spTime.size() && wHour < 24 && wMinute < 60 &&
562 wSecond < 60 && wFraction <= 999;
563}
564
565bool CXFA_LocaleValue::ParsePatternValue(const WideString& wsValue,
566 const WideString& wsPattern,
567 GCedLocaleIface* pLocale) {
568 if (!m_pLocaleMgr)
569 return false;
570
571 std::vector<WideString> wsPatterns =
572 CFGAS_StringFormatter::SplitOnBars(wsPattern);
573
574 ScopedLocale scoped_locale(m_pLocaleMgr, pLocale);
575 bool bRet = false;
576 for (size_t i = 0; !bRet && i < wsPatterns.size(); i++) {
577 const WideString& wsFormat = wsPatterns[i];
578 auto pFormat = std::make_unique<CFGAS_StringFormatter>(wsFormat);
579 switch (ValueCategory(pFormat->GetCategory(), m_eType)) {
581 bRet = pFormat->ParseNull(wsValue);
582 if (bRet)
583 m_wsValue.clear();
584 break;
586 bRet = pFormat->ParseZero(wsValue);
587 if (bRet)
588 m_wsValue = L"0";
589 break;
591 WideString fNum;
592 bRet = pFormat->ParseNum(m_pLocaleMgr, wsValue, &fNum);
593 if (bRet)
594 m_wsValue = std::move(fNum);
595 break;
596 }
597 case CFGAS_StringFormatter::Category::kText:
598 bRet = pFormat->ParseText(wsValue, &m_wsValue);
599 break;
601 CFX_DateTime dt;
602 bRet = ValidateCanonicalDate(wsValue, &dt);
603 if (!bRet) {
604 bRet = pFormat->ParseDateTime(
605 m_pLocaleMgr, wsValue, CFGAS_StringFormatter::DateTimeType::kDate,
606 &dt);
607 }
608 if (bRet)
609 SetDate(dt);
610 break;
611 }
613 CFX_DateTime dt;
614 bRet = pFormat->ParseDateTime(
615 m_pLocaleMgr, wsValue, CFGAS_StringFormatter::DateTimeType::kTime,
616 &dt);
617 if (bRet)
618 SetTime(dt);
619 break;
620 }
622 CFX_DateTime dt;
623 bRet = pFormat->ParseDateTime(
624 m_pLocaleMgr, wsValue,
625 CFGAS_StringFormatter::DateTimeType::kDateTime, &dt);
626 if (bRet)
627 SetDateTime(dt);
628 break;
629 }
630 default:
631 m_wsValue = wsValue;
632 bRet = true;
633 break;
634 }
635 }
636 if (!bRet)
637 m_wsValue = wsValue;
638
639 return bRet;
640}
641
642void CXFA_LocaleValue::GetNumericFormat(WideString& wsFormat,
643 int32_t nIntLen,
644 int32_t nDecLen) {
645 DCHECK(wsFormat.IsEmpty());
646 DCHECK(nIntLen >= -1);
647 DCHECK(nDecLen >= -1);
648
649 int32_t nTotalLen = (nIntLen >= 0 ? nIntLen : 2) + 1 +
650 (nDecLen >= 0 ? nDecLen : 2) + (nDecLen == 0 ? 0 : 1);
651 {
652 // Span's lifetime must end before ReleaseBuffer() below.
653 pdfium::span<wchar_t> lpBuf = wsFormat.GetBuffer(nTotalLen);
654 int32_t nPos = 0;
655 lpBuf[nPos++] = L's';
656
657 if (nIntLen == -1) {
658 lpBuf[nPos++] = L'z';
659 lpBuf[nPos++] = L'*';
660 } else {
661 while (nIntLen) {
662 lpBuf[nPos++] = L'z';
663 nIntLen--;
664 }
665 }
666 if (nDecLen != 0) {
667 lpBuf[nPos++] = L'.';
668 }
669 if (nDecLen == -1) {
670 lpBuf[nPos++] = L'z';
671 lpBuf[nPos++] = L'*';
672 } else {
673 while (nDecLen) {
674 lpBuf[nPos++] = L'z';
675 nDecLen--;
676 }
677 }
678 }
679 wsFormat.ReleaseBuffer(nTotalLen);
680}
681
682bool CXFA_LocaleValue::ValidateNumericTemp(const WideString& wsNumeric,
683 const WideString& wsFormat,
684 GCedLocaleIface* pLocale) {
685 if (wsFormat.IsEmpty() || wsNumeric.IsEmpty())
686 return true;
687
688 pdfium::span<const wchar_t> spNum = wsNumeric.span();
689 pdfium::span<const wchar_t> spFmt = wsFormat.span();
690 size_t n = 0;
691 size_t nf = 0;
692 wchar_t c = spNum[n];
693 wchar_t cf = spFmt[nf];
694 if (cf == L's') {
695 if (c == L'-' || c == L'+')
696 ++n;
697 ++nf;
698 }
699
700 bool bLimit = true;
701 size_t nCount = wsNumeric.GetLength();
702 size_t nCountFmt = wsFormat.GetLength();
703 while (n < nCount && (!bLimit || nf < nCountFmt) &&
704 FXSYS_IsDecimalDigit(c = spNum[n])) {
705 if (bLimit) {
706 if ((cf = spFmt[nf]) == L'*')
707 bLimit = false;
708 else if (cf == L'z')
709 nf++;
710 else
711 return false;
712 }
713 n++;
714 }
715 if (n == nCount)
716 return true;
717 if (nf == nCountFmt)
718 return false;
719
720 while (nf < nCountFmt && (cf = spFmt[nf]) != L'.') {
721 DCHECK(cf == L'z' || cf == L'*');
722 ++nf;
723 }
724
725 WideString wsDecimalSymbol;
726 if (pLocale)
727 wsDecimalSymbol = pLocale->GetDecimalSymbol();
728 else
729 wsDecimalSymbol = WideString(L'.');
730
731 if (spFmt[nf] != L'.')
732 return false;
733 if (wsDecimalSymbol != WideStringView(c) && c != L'.')
734 return false;
735
736 ++nf;
737 ++n;
738 bLimit = true;
739 while (n < nCount && (!bLimit || nf < nCountFmt) &&
740 FXSYS_IsDecimalDigit(spNum[n])) {
741 if (bLimit) {
742 if ((cf = spFmt[nf]) == L'*')
743 bLimit = false;
744 else if (cf == L'z')
745 nf++;
746 else
747 return false;
748 }
749 n++;
750 }
751 return n == nCount;
752}
CFX_DateTime()=default
void SetDate(int32_t year, uint8_t month, uint8_t day)
CXFA_LocaleValue(ValueType eType, CXFA_LocaleMgr *pLocaleMgr)
bool SetDate(const CFX_DateTime &d)
CXFA_LocaleValue(ValueType dwType, const WideString &wsValue, const WideString &wsFormat, GCedLocaleIface *pLocale, CXFA_LocaleMgr *pLocaleMgr)
double GetDoubleNum() const
CFX_DateTime GetTime() const
CFX_DateTime GetDate() const
CXFA_LocaleValue(ValueType eType, const WideString &wsValue, CXFA_LocaleMgr *pLocaleMgr)
bool FormatPatterns(WideString &wsResult, const WideString &wsFormat, GCedLocaleIface *pLocale, XFA_ValuePicture eValueType) const
CXFA_LocaleValue & operator=(const CXFA_LocaleValue &that)
bool ValidateValue(const WideString &wsValue, const WideString &wsPattern, GCedLocaleIface *pLocale, WideString *pMatchFormat)
void GetNumericFormat(WideString &wsFormat, int32_t nIntLen, int32_t nDecLen)
bool ValidateNumericTemp(const WideString &wsNumeric, const WideString &wsFormat, GCedLocaleIface *pLocale)
CXFA_LocaleValue(const CXFA_LocaleValue &that)
virtual WideString GetDecimalSymbol() const =0
WideString(wchar_t ch)
WideString & operator=(WideString &&that) noexcept
bool IsEmpty() const
Definition widestring.h:118
bool EqualsASCII(ByteStringView that) const
Definition widestring.h:216
XFA_ValuePicture
Definition cxfa_node.h:70