7#include "xfa/fgas/crt/cfgas_stringformatter.h"
16#include "core/fxcrt/cfx_datetime.h"
17#include "core/fxcrt/fx_extension.h"
18#include "core/fxcrt/fx_safe_types.h"
19#include "third_party/base/containers/contains.h"
20#include "third_party/base/notreached.h"
21#include "xfa/fgas/crt/cfgas_decimal.h"
22#include "xfa/fgas/crt/locale_mgr_iface.h"
28#define FX_NUMSTYLE_Percent 0x01
29#define FX_NUMSTYLE_Exponent 0x02
30#define FX_NUMSTYLE_DotVorv 0x04
34struct LocaleDateTimeSubcategoryWithHash {
39struct LocaleNumberSubcategoryWithHash {
45#define SUBC(a, b, c) a, c
46constexpr LocaleDateTimeSubcategoryWithHash kLocaleDateTimeSubcategoryData[] = {
54constexpr LocaleNumberSubcategoryWithHash kLocaleNumSubcategoryData[] = {
62struct FX_LOCALETIMEZONEINFO {
68constexpr FX_LOCALETIMEZONEINFO kFXLocaleTimeZoneData[] = {
69 {L"CDT", -5, 0}, {L"CST", -6, 0}, {L"EDT", -4, 0}, {L"EST", -5, 0},
70 {L"MDT", -6, 0}, {L"MST", -7, 0}, {L"PDT", -7, 0}, {L"PST", -8, 0},
73constexpr wchar_t kTimeSymbols[] = L"hHkKMSFAzZ";
74constexpr wchar_t kDateSymbols[] = L"DJMEeGgYwW";
75constexpr wchar_t kConstChars[] = L",-:/. ";
77constexpr wchar_t kDateStr[] = L"date";
78constexpr wchar_t kTimeStr[] = L"time";
79constexpr wchar_t kDateTimeStr[] = L"datetime";
80constexpr wchar_t kNumStr[] = L"num";
81constexpr wchar_t kTextStr[] = L"text";
82constexpr wchar_t kZeroStr[] = L"zero";
83constexpr wchar_t kNullStr[] = L"null";
85size_t ParseTimeZone(pdfium::span<
const wchar_t> spStr,
int* tz) {
91 const bool bNegative = (spStr[0] ==
'-');
94 size_t iEnd = iStart + 2;
96 while (iStart < spStr.size() && iStart < iEnd)
97 tz_hour = tz_hour * 10 + FXSYS_DecimalCharToInt(spStr[iStart++]);
99 if (iStart < spStr.size() && spStr[iStart] ==
':')
104 while (iStart < spStr.size() && iStart < iEnd)
105 tz_minute = tz_minute * 10 + FXSYS_DecimalCharToInt(spStr[iStart++]);
107 *tz = tz_hour * 60 + tz_minute;
114int32_t ConvertHex(int32_t iKeyValue,
wchar_t ch) {
120WideString GetLiteralText(pdfium::span<
const wchar_t> spStrPattern,
123 if (*iPattern >= spStrPattern.size() || spStrPattern[*iPattern] !=
'\'')
128 while (*iPattern < spStrPattern.size()) {
129 if (spStrPattern[*iPattern] ==
'\'') {
131 if ((*iPattern + 1 >= spStrPattern.size()) ||
132 ((spStrPattern[*iPattern + 1] !=
'\'') && (iQuote % 2 == 0))) {
137 }
else if (spStrPattern[*iPattern] ==
'\\' &&
138 (*iPattern + 1 < spStrPattern.size()) &&
139 spStrPattern[*iPattern + 1] ==
'u') {
140 int32_t iKeyValue = 0;
142 for (int32_t i = 0; *iPattern < spStrPattern.size() && i < 4; ++i) {
143 wchar_t ch = spStrPattern[(*iPattern)++];
144 iKeyValue = ConvertHex(iKeyValue, ch);
147 wsOutput
+= static_cast<
wchar_t>(iKeyValue & 0x0000FFFF);
151 wsOutput += spStrPattern[(*iPattern)++];
156WideString GetLiteralTextReverse(pdfium::span<
const wchar_t> spStrPattern,
159 if (*iPattern >= spStrPattern.size() || spStrPattern[*iPattern] !=
'\'')
165 while (*iPattern < spStrPattern.size()) {
166 if (spStrPattern[*iPattern] ==
'\'') {
168 if (*iPattern - 1 >= spStrPattern.size() ||
169 ((spStrPattern[*iPattern - 1] !=
'\'') && (iQuote % 2 == 0))) {
174 }
else if (spStrPattern[*iPattern] ==
'\\' &&
175 *iPattern + 1 < spStrPattern.size() &&
176 spStrPattern[*iPattern + 1] ==
'u') {
178 int32_t iKeyValue = 0;
179 size_t iLen = std::min<size_t>(wsOutput.GetLength(), 5);
181 for (; i < iLen; i++) {
182 wchar_t ch = wsOutput[i];
183 iKeyValue = ConvertHex(iKeyValue, ch);
185 if (iKeyValue != 0) {
186 wsOutput.Delete(0, i);
187 wsOutput
= (
wchar_t)(iKeyValue & 0x0000FFFF)
+ wsOutput;
191 wsOutput = spStrPattern[(*iPattern)--] + wsOutput;
196bool GetNumericDotIndex(
const WideString& wsNum,
197 const WideString& wsDotSymbol,
199 pdfium::span<
const wchar_t> spNum = wsNum.span();
200 pdfium::span<
const wchar_t> spDotSymbol = wsDotSymbol.span();
201 for (size_t ccf = 0; ccf < spNum.size(); ++ccf) {
202 if (spNum[ccf] ==
'\'') {
203 GetLiteralText(spNum, &ccf);
206 if (ccf + spDotSymbol.size() <= spNum.size() &&
207 wcsncmp(&spNum[ccf], spDotSymbol.data(), spDotSymbol.size()) == 0) {
212 auto result = wsNum.Find(
'.');
213 *iDotIndex = result.value_or(spNum.size());
214 return result.has_value();
217bool ExtractCountDigits(pdfium::span<
const wchar_t> spStr,
221 for (size_t i = 0; i < count; ++i) {
222 if (*cc >= spStr.size() || !FXSYS_IsDecimalDigit(spStr[*cc]))
224 *value = *value * 10 + FXSYS_DecimalCharToInt(spStr[(*cc)++]);
229bool ExtractCountDigitsWithOptional(pdfium::span<
const wchar_t> spStr,
233 if (!ExtractCountDigits(spStr, count, cc, value))
235 ExtractCountDigits(spStr, 1, cc, value);
239bool ParseLocaleDate(
const WideString& wsDate,
240 const WideString& wsDatePattern,
244 uint32_t year = 1900;
248 pdfium::span<
const wchar_t> spDate = wsDate.span();
249 pdfium::span<
const wchar_t> spDatePattern = wsDatePattern.span();
250 while (*cc < spDate.size() && ccf < spDatePattern.size()) {
251 if (spDatePattern[ccf] ==
'\'') {
252 WideString wsLiteral = GetLiteralText(spDatePattern, &ccf);
253 size_t iLiteralLen = wsLiteral.GetLength();
254 if (*cc + iLiteralLen > spDate.size() ||
255 wcsncmp(spDate.data() + *cc, wsLiteral.c_str(), iLiteralLen) != 0) {
262 if (!pdfium::Contains(kDateSymbols, spDatePattern[ccf])) {
263 if (spDatePattern[ccf] != spDate[*cc])
272 symbol += spDatePattern[ccf++];
273 while (ccf < spDatePattern.size() && spDatePattern[ccf] == symbol
[0
]) {
274 symbol += spDatePattern[ccf++];
278 if (!ExtractCountDigitsWithOptional(spDate, 1, cc, &day))
282 ExtractCountDigits(spDate, 3, cc, &val);
285 if (!ExtractCountDigitsWithOptional(spDate, 1, cc, &month))
288 for (uint16_t i = 0; i < 12; i++) {
289 WideString wsMonthName =
293 if (wcsncmp(wsMonthName
.c_str(), spDate.data() + *cc,
294 wsMonthName.GetLength()) == 0) {
295 *cc += wsMonthName.GetLength();
301 for (uint16_t i = 0; i < 7; i++) {
302 WideString wsDayName =
306 if (wcsncmp(wsDayName
.c_str(), spDate.data() + *cc,
307 wsDayName.GetLength()) == 0) {
308 *cc += wsDayName.GetLength();
313 if (*cc + symbol.GetLength() > spDate.size())
317 if (!ExtractCountDigits(spDate, symbol.GetLength(), cc, &year))
329 *cc += symbol.GetLength();
332 if (*cc < spDate.size())
339void ResolveZone(
int tz_diff_minutes,
343 int32_t iMinuteDiff = *wHour * 60 + *wMinute;
345 iMinuteDiff -= tz_diff_minutes;
351 *wHour = iMinuteDiff / 60;
352 *wMinute = iMinuteDiff % 60;
355bool ParseLocaleTime(
const WideString& wsTime,
356 const WideString& wsTimePattern,
363 uint32_t millisecond = 0;
365 pdfium::span<
const wchar_t> spTime = wsTime.span();
366 pdfium::span<
const wchar_t> spTimePattern = wsTimePattern.span();
369 while (*cc < spTime.size() && ccf < spTimePattern.size()) {
370 if (spTimePattern[ccf] ==
'\'') {
371 WideString wsLiteral = GetLiteralText(spTimePattern, &ccf);
372 size_t iLiteralLen = wsLiteral.GetLength();
373 if (*cc + iLiteralLen > spTime.size() ||
374 wcsncmp(spTime.data() + *cc, wsLiteral.c_str(), iLiteralLen) != 0) {
381 if (!pdfium::Contains(kTimeSymbols, spTimePattern[ccf])) {
382 if (spTimePattern[ccf] != spTime[*cc])
391 symbol += spTimePattern[ccf++];
392 while (ccf < spTimePattern.size() && spTimePattern[ccf] == symbol
[0
])
393 symbol += spTimePattern[ccf++];
397 if (!ExtractCountDigitsWithOptional(spTime, 1, cc, &hour))
404 if (!ExtractCountDigits(spTime, 2, cc, &hour))
410 if (!ExtractCountDigitsWithOptional(spTime, 1, cc, &minute))
414 if (!ExtractCountDigits(spTime, 2, cc, &minute))
418 if (!ExtractCountDigitsWithOptional(spTime, 1, cc, &second))
422 if (!ExtractCountDigits(spTime, 2, cc, &second))
426 if (!ExtractCountDigits(spTime, 3, cc, &millisecond))
431 if (*cc + wsAM.GetLength() <= spTime.size() &&
432 WideStringView(spTime.data() + *cc, wsAM.GetLength()) == wsAM) {
433 *cc += wsAM.GetLength();
435 }
else if (*cc + wsPM.GetLength() <= spTime.size() &&
436 WideStringView(spTime.data() + *cc, wsPM.GetLength()) ==
438 *cc += wsPM.GetLength();
443 if (*cc + 3 > spTime.size())
446 WideString tz(spTime[(*cc)++]);
447 tz += spTime[(*cc)++];
448 tz += spTime[(*cc)++];
450 int tz_diff_minutes = 0;
451 if (*cc < spTime.size() && (spTime[*cc] ==
'-' || spTime[*cc] ==
'+'))
452 *cc += ParseTimeZone(spTime.subspan(*cc), &tz_diff_minutes);
453 ResolveZone(tz_diff_minutes, pLocale, &hour, &minute);
456 for (size_t i = 0; i <
std::size(kFXLocaleTimeZoneData); ++i) {
457 const FX_LOCALETIMEZONEINFO& info = kFXLocaleTimeZoneData[i];
462 minute += info.iHour > 0 ? info.iMinute : -info.iMinute;
467 if (spTime[*cc] !=
'Z') {
468 int tz_diff_minutes = 0;
469 *cc += ParseTimeZone(spTime.subspan(*cc), &tz_diff_minutes);
470 ResolveZone(tz_diff_minutes, pLocale, &hour, &minute);
490size_t GetNumTrailingLimit(
const WideString& wsFormat,
492 bool* bTrimTailZeros) {
493 const pdfium::span<
const wchar_t> spFormat = wsFormat.span();
494 size_t iTrailing = 0;
495 for (++iDotPos; iDotPos < spFormat.size(); ++iDotPos) {
496 wchar_t wc = spFormat[iDotPos];
497 if (wc == L'z' || wc == L'9' || wc ==
'Z') {
499 *bTrimTailZeros = wc != L'9';
505bool IsLeapYear(uint32_t year) {
506 return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
509bool MonthHas30Days(uint32_t month) {
510 return month == 4 || month == 6 || month == 9 || month == 11;
513bool MonthHas31Days(uint32_t month) {
514 return month != 2 && !MonthHas30Days(month);
518uint16_t GetSolarMonthDays(uint16_t year, uint16_t month) {
522 return MonthHas30Days(month) ? 30 : 31;
525uint16_t GetWeekDay(uint16_t year, uint16_t month, uint16_t day) {
526 static const uint8_t kMonthDay[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
528 (year - 1) % 7 + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
529 nDays += kMonthDay[month - 1] + day;
535uint16_t GetWeekOfMonth(uint16_t year, uint16_t month, uint16_t day) {
536 uint16_t week_day = GetWeekDay(year, month, 1);
537 uint16_t week_index = 0;
538 week_index += day / 7;
540 if (week_day + day > 7)
545uint16_t GetWeekOfYear(uint16_t year, uint16_t month, uint16_t day) {
547 for (uint16_t i = 1; i < month; i++)
548 nDays += GetSolarMonthDays(year, i);
551 uint16_t week_day = GetWeekDay(year, 1, 1);
552 uint16_t week_index = 1;
553 week_index += nDays / 7;
555 if (week_day + nDays > 7)
560WideString NumToString(size_t fmt_size, int32_t value) {
562 fmt_size == 1 ? L"%d" : fmt_size == 2 ? L"%02d" : L"%03d"
, value
);
565WideString DateFormat(
const WideString& wsDatePattern,
573 pdfium::span<
const wchar_t> spDatePattern = wsDatePattern.span();
574 while (ccf < spDatePattern.size()) {
575 if (spDatePattern[ccf] ==
'\'') {
576 wsResult += GetLiteralText(spDatePattern, &ccf);
580 if (!pdfium::Contains(kDateSymbols, spDatePattern[ccf])) {
581 wsResult += spDatePattern[ccf++];
586 symbol += spDatePattern[ccf++];
587 while (ccf < spDatePattern.size() && spDatePattern[ccf] == symbol
[0
])
588 symbol += spDatePattern[ccf++];
591 wsResult += NumToString(symbol.GetLength(), day);
594 for (
int i = 1; i < month; i++)
595 nDays += GetSolarMonthDays(year, i);
597 wsResult += NumToString(symbol.GetLength(), nDays);
599 wsResult += NumToString(symbol.GetLength(), month);
603 uint16_t wWeekDay = GetWeekDay(year, month, day);
605 NumToString(1, symbol.EqualsASCII(
"E") ? wWeekDay + 1
606 : (wWeekDay ? wWeekDay : 7));
613 wsResult += NumToString(2, year % 100);
615 wsResult += NumToString(1, year);
617 wsResult += NumToString(1, GetWeekOfMonth(year, month, day));
619 wsResult += NumToString(2, GetWeekOfYear(year, month, day));
625WideString TimeFormat(
const WideString& wsTimePattern,
634 pdfium::span<
const wchar_t> spTimePattern = wsTimePattern.span();
635 uint16_t wHour = hour;
637 if (wsTimePattern.Contains(
'A')) {
642 while (ccf < spTimePattern.size()) {
643 if (spTimePattern[ccf] ==
'\'') {
644 wsResult += GetLiteralText(spTimePattern, &ccf);
648 if (!pdfium::Contains(kTimeSymbols, spTimePattern[ccf])) {
649 wsResult += spTimePattern[ccf++];
655 symbol += spTimePattern[ccf++];
656 while (ccf < spTimePattern.size() && spTimePattern[ccf] == symbol
[0
])
657 symbol += spTimePattern[ccf++];
662 wsResult += NumToString(symbol.GetLength(), wHour == 0 ? 12 : wHour);
664 wsResult += NumToString(symbol.GetLength(), wHour == 0 ? 24 : wHour);
668 wsResult += NumToString(symbol.GetLength(), wHour);
670 wsResult += NumToString(symbol.GetLength(), wHour);
672 wsResult += NumToString(symbol.GetLength(), minute);
674 wsResult += NumToString(symbol.GetLength(), second);
676 wsResult += NumToString(3, millisecond);
683 if (tz_minutes != 0) {
684 wsResult
+= tz_minutes < 0 ? L"-" : L"+";
685 int abs_tz_minutes = abs(tz_minutes);
686 wsResult
+= WideString
::Format(L"%02d:%02d"
, abs_tz_minutes / 60
,
687 abs_tz_minutes % 60
);
694WideString FormatDateTimeInternal(
const CFX_DateTime& dt,
695 const WideString& wsDatePattern,
696 const WideString& wsTimePattern,
699 WideString wsDateOut;
701 wsDateOut
= DateFormat(wsDatePattern, pLocale, dt);
703 WideString wsTimeOut;
705 wsTimeOut
= TimeFormat(wsTimePattern, pLocale, dt);
707 return bDateFirst ? wsDateOut
+ wsTimeOut : wsTimeOut
+ wsDateOut;
730 NOTREACHED_NORETURN();
742 NOTREACHED_NORETURN();
750 if (spDate.size() > 10)
755 if (!ExtractCountDigits(spDate, 4, &cc, &year))
759 if (cc >= spDate.size()) {
764 if (spDate[cc] ==
'-')
768 if (!ExtractCountDigits(spDate, 2, &cc, &month) || month < 1 || month > 12)
771 if (cc >= spDate.size()) {
776 if (spDate[cc] ==
'-')
780 if (!ExtractCountDigits(spDate, 2, &cc, &day))
784 if ((MonthHas31Days(month) && day > 31) ||
785 (MonthHas30Days(month) && day > 30)) {
788 if (month == 2 && day > (IsLeapYear(year) ? 29U : 28U))
796 pdfium::span<
const wchar_t> spTime,
803 if (!ExtractCountDigits(spTime, 2, &cc, &hour) || hour >= 24)
806 if (cc >= spTime.size()) {
811 if (spTime[cc] ==
':')
815 if (!ExtractCountDigits(spTime, 2, &cc, &minute) || minute >= 60)
818 if (cc >= spTime.size()) {
823 if (spTime[cc] ==
':')
827 uint32_t millisecond = 0;
828 if (cc < spTime.size() && spTime[cc] !=
'Z') {
829 if (!ExtractCountDigits(spTime, 2, &cc, &second) || second >= 60)
832 if (cc < spTime.size() && spTime[cc] ==
'.') {
834 if (!ExtractCountDigits(spTime, 3, &cc, &millisecond))
840 while (cc < spTime.size()) {
841 if (spTime[cc] ==
'+' || spTime[cc] ==
'-')
846 if (cc < spTime.size()) {
847 int tz_diff_minutes = 0;
848 if (spTime[cc] !=
'Z')
849 cc += ParseTimeZone(spTime.subspan(cc), &tz_diff_minutes);
850 ResolveZone(tz_diff_minutes, pLocale, &hour, &minute);
864 const WideString& wsFormatString) {
865 std::vector<WideString> wsPatterns;
866 pdfium::span<
const wchar_t> spFormatString = wsFormatString.span();
870 for (; index < spFormatString.size(); ++index) {
871 if (spFormatString[index] ==
'\'') {
873 }
else if (spFormatString[index] == L'|' && !bQuote) {
874 wsPatterns.emplace_back(spFormatString.data() + token, index - token);
878 wsPatterns.emplace_back(spFormatString.data() + token, index - token);
885 bool bBraceOpen =
false;
886 while (ccf < m_spPattern.size()) {
887 if (m_spPattern[ccf] ==
'\'') {
888 GetLiteralText(m_spPattern, &ccf);
889 }
else if (!bBraceOpen &&
890 !pdfium::Contains(kConstChars, m_spPattern[ccf])) {
891 WideString wsCategory(m_spPattern[ccf]);
894 if (ccf >= m_spPattern.size())
896 if (m_spPattern[ccf] ==
'.' || m_spPattern[ccf] ==
'(')
898 if (m_spPattern[ccf] ==
'{') {
902 wsCategory += m_spPattern[ccf];
905 if (wsCategory
== kDateTimeStr)
907 if (wsCategory
== kTextStr)
909 if (wsCategory
== kNumStr)
911 if (wsCategory
== kZeroStr)
913 if (wsCategory
== kNullStr)
915 if (wsCategory
== kDateStr) {
919 }
else if (wsCategory
== kTimeStr) {
924 }
else if (m_spPattern[ccf] ==
'}') {
933 WideStringView wsCategory)
const {
935 bool bBrackOpen =
false;
936 WideString wsPurgePattern;
937 while (ccf < m_spPattern.size()) {
938 if (m_spPattern[ccf] ==
'\'') {
939 size_t iCurChar = ccf;
940 GetLiteralText(m_spPattern, &ccf);
942 WideStringView(m_spPattern.data() + iCurChar, ccf - iCurChar + 1);
943 }
else if (!bBrackOpen &&
944 !pdfium::Contains(kConstChars, m_spPattern[ccf])) {
945 WideString wsSearchCategory(m_spPattern[ccf]);
947 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
'{' &&
948 m_spPattern[ccf] !=
'.' && m_spPattern[ccf] !=
'(') {
949 wsSearchCategory += m_spPattern[ccf];
952 if (wsSearchCategory != wsCategory)
955 while (ccf < m_spPattern.size()) {
956 if (m_spPattern[ccf] ==
'(') {
959 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
')')
961 }
else if (m_spPattern[ccf] ==
'{') {
967 }
else if (m_spPattern[ccf] !=
'}') {
968 wsPurgePattern += m_spPattern[ccf];
973 wsPurgePattern = m_wsPattern;
975 return wsPurgePattern;
982 WideString* wsPurgePattern)
const {
986 bool bFindDot =
false;
987 bool bBrackOpen =
false;
988 while (ccf < m_spPattern.size()) {
989 if (m_spPattern[ccf] ==
'\'') {
990 size_t iCurChar = ccf;
991 GetLiteralText(m_spPattern, &ccf);
993 WideStringView(m_spPattern.data() + iCurChar, ccf - iCurChar + 1);
994 }
else if (!bBrackOpen &&
995 !pdfium::Contains(kConstChars, m_spPattern[ccf])) {
996 WideString wsCategory(m_spPattern[ccf]);
998 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
'{' &&
999 m_spPattern[ccf] !=
'.' && m_spPattern[ccf] !=
'(') {
1000 wsCategory += m_spPattern[ccf];
1008 while (ccf < m_spPattern.size()) {
1009 if (m_spPattern[ccf] ==
'{') {
1013 if (m_spPattern[ccf] ==
'(') {
1016 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
')')
1017 wsLCID += m_spPattern[ccf++];
1020 }
else if (m_spPattern[ccf] ==
'.') {
1021 WideString wsSubCategory;
1023 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
'(' &&
1024 m_spPattern[ccf] !=
'{') {
1025 wsSubCategory += m_spPattern[ccf++];
1027 uint32_t dwSubHash = FX_HashCode_GetW(wsSubCategory.AsStringView());
1030 for (
const auto& data : kLocaleNumSubcategoryData) {
1031 if (data.uHash == dwSubHash) {
1032 eSubCategory = data.eSubCategory;
1040 auto result = wsSubCategory.Find(
'.');
1041 if (result.has_value() && result.value() != 0) {
1043 *iDotIndex = wsPurgePattern->GetLength() + result.value();
1047 *wsPurgePattern
+= wsSubCategory;
1054 }
else if (m_spPattern[ccf] ==
'E') {
1056 *wsPurgePattern += m_spPattern[ccf];
1057 }
else if (m_spPattern[ccf] ==
'%') {
1059 *wsPurgePattern += m_spPattern[ccf];
1060 }
else if (m_spPattern[ccf] !=
'}') {
1061 *wsPurgePattern += m_spPattern[ccf];
1063 if (!bFindDot && ccf < m_spPattern.size() &&
1064 (m_spPattern[ccf] ==
'.' || m_spPattern[ccf] ==
'V' ||
1065 m_spPattern[ccf] ==
'v')) {
1067 *iDotIndex = wsPurgePattern->GetLength() - 1;
1073 *iDotIndex = wsPurgePattern->GetLength();
1080 WideString* wsValue)
const {
1082 if (wsSrcText.IsEmpty() || m_spPattern.empty())
1085 WideString wsTextFormat = GetTextFormat(L"text");
1089 pdfium::span<
const wchar_t> spSrcText = wsSrcText.span();
1090 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
1093 size_t iPattern = 0;
1094 while (iPattern < spTextFormat.size() && iText < spSrcText.size()) {
1095 switch (spTextFormat[iPattern]) {
1097 WideString wsLiteral = GetLiteralText(spTextFormat, &iPattern);
1098 size_t iLiteralLen = wsLiteral.GetLength();
1099 if (iText + iLiteralLen > spSrcText.size() ||
1100 wcsncmp(spSrcText.data() + iText, wsLiteral.c_str(), iLiteralLen) !=
1102 *wsValue
= wsSrcText;
1105 iText += iLiteralLen;
1110 if (FXSYS_iswalpha(spSrcText[iText])) {
1111 *wsValue += spSrcText[iText];
1117 *wsValue += spSrcText[iText];
1123 if (FXSYS_IsDecimalDigit(spSrcText[iText]) ||
1124 FXSYS_iswalpha(spSrcText[iText])) {
1125 *wsValue += spSrcText[iText];
1131 if (FXSYS_IsDecimalDigit(spSrcText[iText])) {
1132 *wsValue += spSrcText[iText];
1138 if (spTextFormat[iPattern] != spSrcText[iText]) {
1139 *wsValue
= wsSrcText;
1147 return iPattern == spTextFormat.size() && iText == spSrcText.size();
1151 const WideString& wsSrcNum,
1152 WideString* wsValue)
const {
1154 if (wsSrcNum.IsEmpty() || m_spPattern.empty())
1157 size_t dot_index_f = m_spPattern.size();
1158 uint32_t dwFormatStyle = 0;
1159 WideString wsNumFormat;
1161 GetNumericFormat(pLocaleMgr, &dot_index_f, &dwFormatStyle, &wsNumFormat);
1165 int32_t iExponent = 0;
1169 size_t iGroupLen = wsGroupSymbol.GetLength();
1170 size_t iMinusLen = wsMinus.GetLength();
1172 pdfium::span<
const wchar_t> spSrcNum = wsSrcNum.span();
1173 pdfium::span<
const wchar_t> spNumFormat = wsNumFormat.span();
1175 bool bHavePercentSymbol =
false;
1177 bool bReverseParse =
false;
1178 size_t dot_index = 0;
1182 if (!GetNumericDotIndex(wsSrcNum, wsDotSymbol, &dot_index) &&
1184 bReverseParse =
true;
1194 size_t cc = dot_index - 1;
1195 size_t ccf = dot_index_f - 1;
1196 while (ccf < spNumFormat.size() && cc < spSrcNum.size()) {
1197 switch (spNumFormat[ccf]) {
1199 WideString wsLiteral = GetLiteralTextReverse(spNumFormat, &ccf);
1200 size_t iLiteralLen = wsLiteral.GetLength();
1201 cc -= iLiteralLen - 1;
1202 if (cc >= spSrcNum.size() ||
1203 wcsncmp(spSrcNum.data() + cc, wsLiteral.c_str(), iLiteralLen) !=
1212 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
1215 wsValue->InsertAtFront(spSrcNum[cc]);
1221 if (spNumFormat[ccf] ==
'z' || spSrcNum[cc] !=
' ') {
1222 if (FXSYS_IsDecimalDigit(spSrcNum[cc])) {
1223 wsValue->InsertAtFront(spSrcNum[cc]);
1233 if (spSrcNum[cc] ==
'+' ||
1234 (spNumFormat[ccf] ==
'S' && spSrcNum[cc] ==
' ')) {
1237 cc -= iMinusLen - 1;
1238 if (cc >= spSrcNum.size() ||
1239 wcsncmp(spSrcNum.data() + cc, wsMinus.c_str(), iMinusLen) != 0) {
1249 bool bExpSign =
false;
1250 while (cc < spSrcNum.size()) {
1251 if (spSrcNum[cc] ==
'E' || spSrcNum[cc] ==
'e')
1253 if (FXSYS_IsDecimalDigit(spSrcNum[cc])) {
1254 if (iExponent >
std::numeric_limits<
int>::max() / 10)
1256 iExponent = iExponent + FXSYS_DecimalCharToInt(spSrcNum[cc]) * 10;
1260 if (spSrcNum[cc] ==
'+') {
1264 if (cc - iMinusLen + 1 <= spSrcNum.size() &&
1265 wcsncmp(spSrcNum.data() + (cc - iMinusLen + 1), wsMinus.c_str(),
1275 iExponent = bExpSign ? -iExponent : iExponent;
1281 size_t iSymbolLen = wsSymbol.GetLength();
1282 cc -= iSymbolLen - 1;
1283 if (cc >= spSrcNum.size() ||
1284 wcsncmp(spSrcNum.data() + cc, wsSymbol.c_str(), iSymbolLen) != 0) {
1293 if (ccf - 1 < spNumFormat.size() &&
1294 ((spNumFormat[ccf] ==
'R' && spNumFormat[ccf - 1] ==
'C') ||
1295 (spNumFormat[ccf] ==
'r' && spNumFormat[ccf - 1] ==
'c'))) {
1296 if (spNumFormat[ccf] ==
'R' && spSrcNum[cc] ==
' ') {
1298 }
else if (spSrcNum[cc] ==
'R' && cc - 1 < spSrcNum.size() &&
1299 spSrcNum[cc - 1] ==
'C') {
1310 if (ccf - 1 < spNumFormat.size() &&
1311 ((spNumFormat[ccf] ==
'B' && spNumFormat[ccf - 1] ==
'D') ||
1312 (spNumFormat[ccf] ==
'b' && spNumFormat[ccf - 1] ==
'd'))) {
1313 if (spNumFormat[ccf] ==
'B' && spSrcNum[cc] ==
' ') {
1315 }
else if (spSrcNum[cc] ==
'B' && cc - 1 < spSrcNum.size() &&
1316 spSrcNum[cc - 1] ==
'D') {
1327 size_t iSymbolLen = wsSymbol.GetLength();
1328 cc -= iSymbolLen - 1;
1329 if (cc >= spSrcNum.size() ||
1330 wcsncmp(spSrcNum.data() + cc, wsSymbol.c_str(), iSymbolLen) != 0) {
1335 bHavePercentSymbol =
true;
1344 if (cc < spSrcNum.size()) {
1345 cc -= iGroupLen - 1;
1346 if (cc < spSrcNum.size() &&
1347 wcsncmp(spSrcNum.data() + cc, wsGroupSymbol.c_str(), iGroupLen) ==
1351 cc += iGroupLen - 1;
1359 if (spSrcNum[cc] == spNumFormat[ccf])
1361 else if (spSrcNum[cc] != L' ')
1368 if (spNumFormat[ccf] != spSrcNum[cc])
1375 if (cc < spSrcNum.size()) {
1376 if (spSrcNum[cc] ==
'-') {
1380 if (cc < spSrcNum.size())
1386 if (!bReverseParse) {
1387 cc = (dot_index == spSrcNum.size()) ? spSrcNum.size() : dot_index + 1;
1388 for (ccf = dot_index_f + 1;
1389 cc < spSrcNum.size() && ccf < spNumFormat.size(); ++ccf) {
1390 switch (spNumFormat[ccf]) {
1392 WideString wsLiteral = GetLiteralText(spNumFormat, &ccf);
1393 size_t iLiteralLen = wsLiteral.GetLength();
1394 if (cc + iLiteralLen > spSrcNum.size() ||
1395 wcsncmp(spSrcNum.data() + cc, wsLiteral.c_str(), iLiteralLen) !=
1403 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
1406 *wsValue += spSrcNum[cc];
1411 if (spNumFormat[ccf] ==
'z' || spSrcNum[cc] !=
' ') {
1412 if (FXSYS_IsDecimalDigit(spSrcNum[cc])) {
1413 *wsValue += spSrcNum[cc];
1422 if (spSrcNum[cc] ==
'+' ||
1423 (spNumFormat[ccf] ==
'S' && spSrcNum[cc] ==
' ')) {
1426 if (cc + iMinusLen > spSrcNum.size() ||
1427 wcsncmp(spSrcNum.data() + cc, wsMinus.c_str(), iMinusLen) !=
1436 if (cc >= spSrcNum.size() ||
1437 (spSrcNum[cc] !=
'E' && spSrcNum[cc] !=
'e')) {
1441 bool bExpSign =
false;
1443 if (cc < spSrcNum.size()) {
1444 if (spSrcNum[cc] ==
'+') {
1446 }
else if (spSrcNum[cc] ==
'-') {
1451 while (cc < spSrcNum.size()) {
1452 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
1454 int digit = FXSYS_DecimalCharToInt(spSrcNum[cc]);
1455 if (iExponent > (
std::numeric_limits<
int>::max() - digit) / 10)
1457 iExponent = iExponent * 10 + digit;
1460 iExponent = bExpSign ? -iExponent : iExponent;
1465 size_t iSymbolLen = wsSymbol.GetLength();
1466 if (cc + iSymbolLen > spSrcNum.size() ||
1467 wcsncmp(spSrcNum.data() + cc, wsSymbol.c_str(), iSymbolLen) !=
1476 if (ccf + 1 < spNumFormat.size() &&
1477 ((spNumFormat[ccf] ==
'C' && spNumFormat[ccf + 1] ==
'R') ||
1478 (spNumFormat[ccf] ==
'c' && spNumFormat[ccf + 1] ==
'r'))) {
1479 if (spNumFormat[ccf] ==
'C' && spSrcNum[cc] ==
' ') {
1481 }
else if (spSrcNum[cc] ==
'C' && cc + 1 < spSrcNum.size() &&
1482 spSrcNum[cc + 1] ==
'R') {
1491 if (ccf + 1 < spNumFormat.size() &&
1492 ((spNumFormat[ccf] ==
'D' && spNumFormat[ccf + 1] ==
'B') ||
1493 (spNumFormat[ccf] ==
'd' && spNumFormat[ccf + 1] ==
'b'))) {
1494 if (spNumFormat[ccf] ==
'D' && spSrcNum[cc] ==
' ') {
1496 }
else if (spSrcNum[cc] ==
'D' && cc + 1 < spSrcNum.size() &&
1497 spSrcNum[cc + 1] ==
'B') {
1510 size_t iSymbolLen = wsSymbol.GetLength();
1511 if (cc + iSymbolLen <= spSrcNum.size() &&
1512 wcsncmp(spSrcNum.data() + cc, wsSymbol.c_str(), iSymbolLen) ==
1516 bHavePercentSymbol =
true;
1519 while (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'8')
1522 while (cc < spSrcNum.size() && FXSYS_IsDecimalDigit(spSrcNum[cc])) {
1523 *wsValue += spSrcNum[cc];
1528 if (cc + iGroupLen <= spSrcNum.size() &&
1529 wcsncmp(spSrcNum.data() + cc, wsGroupSymbol.c_str(), iGroupLen) ==
1537 if (spSrcNum[cc] == spNumFormat[ccf])
1539 else if (spSrcNum[cc] != L' ')
1545 if (spNumFormat[ccf] != spSrcNum[cc])
1551 if (cc != spSrcNum.size())
1554 if (iExponent || bHavePercentSymbol) {
1558 if (bHavePercentSymbol)
1563 wsValue->InsertAtFront(L'-');
1571 WideString* wsDatePattern,
1572 WideString* wsTimePattern)
const {
1574 WideString wsTempPattern;
1578 bool bBraceOpen =
false;
1579 while (ccf < m_spPattern.size()) {
1580 if (m_spPattern[ccf] ==
'\'') {
1581 size_t iCurChar = ccf;
1582 GetLiteralText(m_spPattern, &ccf);
1584 WideStringView(m_spPattern.data() + iCurChar, ccf - iCurChar + 1);
1585 }
else if (!bBraceOpen && eDateTimeType != DateTimeType::kDateTime &&
1586 !pdfium::Contains(kConstChars, m_spPattern[ccf])) {
1587 WideString wsCategory(m_spPattern[ccf]);
1589 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
'{' &&
1590 m_spPattern[ccf] !=
'.' && m_spPattern[ccf] !=
'(') {
1591 if (m_spPattern[ccf] ==
'T') {
1592 *wsDatePattern = m_wsPattern.First(ccf);
1593 *wsTimePattern = m_wsPattern.Last(m_wsPattern.GetLength() - ccf);
1594 wsTimePattern->SetAt(0,
' ');
1599 wsCategory += m_spPattern[ccf];
1602 if (!HasDate(eDateTimeType) && wsCategory
.EqualsASCII(
"date")) {
1603 eDateTimeType = AddDateToDatelessType(eDateTimeType);
1605 }
else if (!HasTime(eDateTimeType) && wsCategory
.EqualsASCII(
"time")) {
1606 eDateTimeType = AddTimeToTimelessType(eDateTimeType);
1614 while (ccf < m_spPattern.size()) {
1615 if (m_spPattern[ccf] ==
'{') {
1619 if (m_spPattern[ccf] ==
'(') {
1622 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
')')
1623 wsLCID += m_spPattern[ccf++];
1626 }
else if (m_spPattern[ccf] ==
'.') {
1627 WideString wsSubCategory;
1629 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
'(' &&
1630 m_spPattern[ccf] !=
'{')
1631 wsSubCategory += m_spPattern[ccf++];
1633 uint32_t dwSubHash = FX_HashCode_GetW(wsSubCategory.AsStringView());
1636 for (
const auto& data : kLocaleDateTimeSubcategoryData) {
1637 if (data.uHash == dwSubHash) {
1638 eSubCategory = data.eSubCategory;
1645 switch (eCategory) {
1667 }
else if (m_spPattern[ccf] ==
'}') {
1671 *wsTimePattern =
std::move(wsTempPattern);
1673 *wsDatePattern =
std::move(wsTempPattern);
1678 wsTempPattern += m_spPattern[ccf];
1685 *wsDatePattern
+= wsTempPattern;
1687 *wsTimePattern
+= wsTempPattern;
1693 *wsDatePattern = m_wsPattern;
1695 return eDateTimeType;
1699 const WideString& wsSrcDateTime,
1703 if (wsSrcDateTime.IsEmpty() || m_spPattern.empty())
1707 WideString wsDatePattern;
1708 WideString wsTimePattern;
1710 GetDateTimeFormat(pLocaleMgr, &pLocale, &wsDatePattern, &wsTimePattern);
1715 eCategory = eDateTimeType;
1718 switch (eCategory) {
1719 case DateTimeType::kDate:
1720 return ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue,
1722 case DateTimeType::kTime:
1723 return ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue,
1725 case DateTimeType::kDateTime:
1726 return ParseLocaleDate(wsSrcDateTime, wsTimePattern, pLocale, dtValue,
1728 ParseLocaleTime(wsSrcDateTime, wsDatePattern, pLocale, dtValue,
1730 case DateTimeType::kTimeDate:
1731 return ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue,
1733 ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue,
1741 WideString wsTextFormat = GetTextFormat(L"zero");
1742 pdfium::span<
const wchar_t> spSrcText = wsSrcText.span();
1743 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
1746 size_t iPattern = 0;
1747 while (iPattern < spTextFormat.size() && iText < spSrcText.size()) {
1748 if (spTextFormat[iPattern] ==
'\'') {
1749 WideString wsLiteral = GetLiteralText(spTextFormat, &iPattern);
1750 size_t iLiteralLen = wsLiteral.GetLength();
1751 if (iText + iLiteralLen > spSrcText.size() ||
1752 wcsncmp(spSrcText.data() + iText, wsLiteral.c_str(), iLiteralLen)) {
1755 iText += iLiteralLen;
1759 if (spTextFormat[iPattern] != spSrcText[iText])
1765 return iPattern == spTextFormat.size() && iText == spSrcText.size();
1769 WideString wsTextFormat = GetTextFormat(L"null");
1770 pdfium::span<
const wchar_t> spSrcText = wsSrcText.span();
1771 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
1774 size_t iPattern = 0;
1775 while (iPattern < spTextFormat.size() && iText < spSrcText.size()) {
1776 if (spTextFormat[iPattern] ==
'\'') {
1777 WideString wsLiteral = GetLiteralText(spTextFormat, &iPattern);
1778 size_t iLiteralLen = wsLiteral.GetLength();
1779 if (iText + iLiteralLen > spSrcText.size() ||
1780 wcsncmp(spSrcText.data() + iText, wsLiteral.c_str(), iLiteralLen)) {
1783 iText += iLiteralLen;
1787 if (spTextFormat[iPattern] != spSrcText[iText])
1793 return iPattern == spTextFormat.size() && iText == spSrcText.size();
1797 WideString* wsOutput)
const {
1798 if (wsSrcText.IsEmpty() || m_spPattern.empty())
1801 WideString wsTextFormat = GetTextFormat(L"text");
1802 pdfium::span<
const wchar_t> spSrcText = wsSrcText.span();
1803 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
1806 size_t iPattern = 0;
1807 while (iPattern < spTextFormat.size()) {
1808 switch (spTextFormat[iPattern]) {
1810 *wsOutput += GetLiteralText(spTextFormat, &iPattern);
1815 if (iText >= spSrcText.size() || !FXSYS_iswalpha(spSrcText[iText]))
1818 *wsOutput += spSrcText[iText++];
1822 if (iText >= spSrcText.size())
1825 *wsOutput += spSrcText[iText++];
1830 if (iText >= spSrcText.size() ||
1831 (!FXSYS_IsDecimalDigit(spSrcText[iText]) &&
1832 !FXSYS_iswalpha(spSrcText[iText]))) {
1835 *wsOutput += spSrcText[iText++];
1839 if (iText >= spSrcText.size() ||
1840 !FXSYS_IsDecimalDigit(spSrcText[iText]))
1843 *wsOutput += spSrcText[iText++];
1847 *wsOutput += spTextFormat[iPattern++];
1851 return iText == spSrcText.size();
1855 const WideString& wsInputNum,
1856 WideString* wsOutput)
const {
1857 if (wsInputNum.IsEmpty() || m_spPattern.empty())
1860 size_t dot_index_f = m_spPattern.size();
1861 uint32_t dwNumStyle = 0;
1862 WideString wsNumFormat;
1864 GetNumericFormat(pLocaleMgr, &dot_index_f, &dwNumStyle, &wsNumFormat);
1868 pdfium::span<
const wchar_t> spNumFormat = wsNumFormat.span();
1869 WideString wsSrcNum = wsInputNum;
1872 wsSrcNum.InsertAtFront(
'0');
1880 int32_t exponent = 0;
1882 int fixed_count = 0;
1883 for (size_t ccf = 0; ccf < dot_index_f; ++ccf) {
1884 switch (spNumFormat[ccf]) {
1886 GetLiteralText(spNumFormat, &ccf);
1896 FX_SAFE_UINT32 threshold = 1;
1897 while (fixed_count > 1) {
1901 if (!threshold.IsValid())
1904 bool bAdjusted =
false;
1906 fabs(decimal
.ToDouble()) < threshold.ValueOrDie()) {
1913 if (!threshold.IsValid())
1917 fabs(decimal
.ToDouble()) > threshold.ValueOrDie()) {
1924 bool bTrimTailZeros =
false;
1926 GetNumTrailingLimit(wsNumFormat, dot_index_f, &bTrimTailZeros);
1928 if (iTreading < scale) {
1932 if (bTrimTailZeros && scale > 0 && iTreading > 0) {
1933 wsSrcNum.TrimRight(L"0");
1934 wsSrcNum.TrimRight(L".");
1939 if (wsSrcNum
[0
] ==
'-') {
1941 wsSrcNum.Delete(0, 1);
1944 bool bAddNeg =
false;
1945 pdfium::span<
const wchar_t> spSrcNum = wsSrcNum.span();
1946 auto dot_index = wsSrcNum.Find(
'.');
1947 if (!dot_index.has_value())
1948 dot_index = spSrcNum.size();
1950 size_t cc = dot_index.value() - 1;
1951 for (size_t ccf = dot_index_f - 1; ccf < spNumFormat.size(); --ccf) {
1952 switch (spNumFormat[ccf]) {
1954 if (cc < spSrcNum.size()) {
1955 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
1957 wsOutput->InsertAtFront(spSrcNum[cc]);
1960 wsOutput->InsertAtFront(L'0');
1964 if (cc < spSrcNum.size()) {
1965 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
1967 if (spSrcNum[0] !=
'0')
1968 wsOutput->InsertAtFront(spSrcNum[cc]);
1973 if (cc < spSrcNum.size()) {
1974 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
1976 wsOutput->InsertAtFront(spSrcNum[0] ==
'0' ? L' ' : spSrcNum[cc]);
1979 wsOutput->InsertAtFront(L' ');
1987 wsOutput->InsertAtFront(L' ');
1997 *wsOutput
= WideString
::Format(L"E%+d"
, exponent
) + *wsOutput;
2003 if (ccf - 1 < spNumFormat.size() && spNumFormat[ccf - 1] ==
'c') {
2005 *wsOutput
= L"CR"
+ *wsOutput;
2009 wsOutput->InsertAtFront(
'r');
2013 if (ccf - 1 < spNumFormat.size() && spNumFormat[ccf - 1] ==
'C') {
2014 *wsOutput
= bNeg ? L"CR" : L" "
+ *wsOutput;
2018 wsOutput->InsertAtFront(
'R');
2022 if (ccf - 1 < spNumFormat.size() && spNumFormat[ccf - 1] ==
'd') {
2024 *wsOutput
= L"db"
+ *wsOutput;
2028 wsOutput->InsertAtFront(
'b');
2032 if (ccf - 1 < spNumFormat.size() && spNumFormat[ccf - 1] ==
'D') {
2033 *wsOutput
= bNeg ? L"DB" : L" "
+ *wsOutput;
2037 wsOutput->InsertAtFront(
'B');
2044 if (cc < spSrcNum.size())
2045 *wsOutput
= wsGroupSymbol
+ *wsOutput;
2048 wsOutput->InsertAtFront(bNeg ? L'(' : L' ');
2052 wsOutput->InsertAtFront(bNeg ? L')' : L' ');
2055 *wsOutput = GetLiteralTextReverse(spNumFormat, &ccf) + *wsOutput;
2058 wsOutput->InsertAtFront(spNumFormat[ccf]);
2063 if (cc < spSrcNum.size()) {
2064 size_t nPos = dot_index.value() % 3;
2066 for (size_t i = 0; i < dot_index.value(); i++) {
2067 if (i % 3 == nPos && i != 0)
2068 *wsOutput
+= wsGroupSymbol;
2069 *wsOutput += wsSrcNum[i];
2071 if (dot_index.value() < spSrcNum.size()) {
2073 *wsOutput += wsSrcNum.Last(spSrcNum.size() - dot_index.value() - 1);
2079 if (dot_index_f == wsNumFormat.GetLength()) {
2080 if (!bAddNeg && bNeg)
2086 if (spNumFormat[dot_index_f] ==
'V') {
2087 *wsOutput
+= wsDotSymbol;
2088 }
else if (spNumFormat[dot_index_f] ==
'.') {
2089 if (dot_index.value() < spSrcNum.size()) {
2090 *wsOutput
+= wsDotSymbol;
2091 }
else if (dot_index_f + 1 < spNumFormat.size() &&
2092 (spNumFormat[dot_index_f + 1] ==
'9' ||
2093 spNumFormat[dot_index_f + 1] ==
'Z')) {
2094 *wsOutput
+= wsDotSymbol;
2098 cc = dot_index.value() + 1;
2099 for (size_t ccf = dot_index_f + 1; ccf < spNumFormat.size(); ++ccf) {
2100 switch (spNumFormat[ccf]) {
2102 *wsOutput += GetLiteralText(spNumFormat, &ccf);
2105 if (cc < spSrcNum.size()) {
2106 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
2108 *wsOutput += spSrcNum[cc];
2115 if (cc < spSrcNum.size()) {
2116 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
2118 *wsOutput += spSrcNum[cc];
2123 if (cc < spSrcNum.size()) {
2124 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
2126 *wsOutput += spSrcNum[cc];
2140 if (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'r') {
2148 if (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'R') {
2149 *wsOutput
+= bNeg ? L"CR" : L" ";
2155 if (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'b') {
2163 if (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'B') {
2164 *wsOutput
+= bNeg ? L"DB" : L" ";
2173 while (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'8')
2175 while (cc < spSrcNum.size() && FXSYS_IsDecimalDigit(spSrcNum[cc])) {
2176 *wsOutput += spSrcNum[cc];
2181 *wsOutput
+= wsGroupSymbol;
2184 *wsOutput
+= bNeg ?
'(' :
' ';
2188 *wsOutput
+= bNeg ?
')' :
' ';
2194 if (!bAddNeg && bNeg)
2201 const WideString& wsSrcDateTime,
2203 WideString* wsOutput)
const {
2204 if (wsSrcDateTime.IsEmpty() || m_spPattern.empty())
2207 WideString wsDatePattern;
2208 WideString wsTimePattern;
2211 GetDateTimeFormat(pLocaleMgr, &pLocale, &wsDatePattern, &wsTimePattern);
2217 wsTimePattern =
std::move(wsDatePattern);
2218 wsDatePattern
= WideString
();
2220 eCategory = eDateTimeType;
2226 auto iT = wsSrcDateTime.Find(L"T");
2227 if (!iT.has_value()) {
2229 FX_DateFromCanonical(wsSrcDateTime.span(), &dt)) {
2230 *wsOutput
= FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern,
true,
2235 FX_TimeFromCanonical(pLocale, wsSrcDateTime.span(), &dt)) {
2236 *wsOutput
= FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern,
true,
2241 pdfium::span<
const wchar_t> wsSrcDate =
2242 wsSrcDateTime.span().first(iT.value());
2243 pdfium::span<
const wchar_t> wsSrcTime =
2244 wsSrcDateTime.span().subspan(iT.value() + 1);
2245 if (wsSrcDate.empty() || wsSrcTime.empty())
2248 if (FX_DateFromCanonical(wsSrcDate, &dt) &&
2249 FX_TimeFromCanonical(pLocale, wsSrcTime, &dt)) {
2251 FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern,
2260 if (m_spPattern.empty())
2263 WideString wsTextFormat = GetTextFormat(L"zero");
2264 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
2265 for (size_t iPattern = 0; iPattern < spTextFormat.size(); ++iPattern) {
2266 if (spTextFormat[iPattern] ==
'\'') {
2267 *wsOutput += GetLiteralText(spTextFormat, &iPattern);
2270 *wsOutput += spTextFormat[iPattern];
2276 if (m_spPattern.empty())
2279 WideString wsTextFormat = GetTextFormat(L"null");
2280 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
2281 for (size_t iPattern = 0; iPattern < spTextFormat.size(); ++iPattern) {
2282 if (spTextFormat[iPattern] ==
'\'') {
2283 *wsOutput += GetLiteralText(spTextFormat, &iPattern);
2286 *wsOutput += spTextFormat[iPattern];
bool FX_IsLeapYear(int32_t iYear)
void SetScale(uint8_t newScale)
CFGAS_Decimal(float val, uint8_t scale)
CFGAS_Decimal operator*(const CFGAS_Decimal &val) const
WideString ToWideString() const
CFGAS_Decimal operator/(const CFGAS_Decimal &val) const
CFGAS_Decimal(int32_t val)
void SetDate(int32_t year, uint8_t month, uint8_t day)
uint8_t GetSecond() const
uint8_t GetMinute() const
void SetTime(uint8_t hour, uint8_t minute, uint8_t second, uint16_t millisecond)
uint16_t GetMillisecond() const
virtual WideString GetDayName(int32_t nWeek, bool bAbbr) const =0
virtual WideString GetDecimalSymbol() const =0
virtual WideString GetMonthName(int32_t nMonth, bool bAbbr) const =0
virtual WideString GetNumPattern(NumSubcategory eType) const =0
virtual WideString GetDatePattern(DateTimeSubcategory eType) const =0
virtual int GetTimeZoneInMinutes() const =0
virtual WideString GetMeridiemName(bool bAM) const =0
virtual WideString GetCurrencySymbol() const =0
virtual WideString GetTimePattern(DateTimeSubcategory eType) const =0
virtual WideString GetPercentSymbol() const =0
virtual WideString GetGroupingSymbol() const =0
virtual WideString GetEraName(bool bAD) const =0
virtual WideString GetMinusSymbol() const =0
virtual LocaleIface * GetLocaleByName(const WideString &wsLCID)=0
virtual LocaleIface * GetDefLocale()=0
WideString & operator+=(const WideString &str)
static WideString Format(const wchar_t *pFormat,...)
WideString & operator=(WideString &&that) noexcept
WideString & operator+=(const wchar_t *str)
bool operator==(const wchar_t *ptr) const
WideString & operator+=(wchar_t ch)
void TrimLeft(wchar_t target)
bool EqualsASCIINoCase(ByteStringView that) const
CharType operator[](const size_t index) const
const wchar_t * c_str() const
WideString & operator=(const WideString &that)
bool operator!=(const wchar_t *ptr) const
bool EqualsASCII(ByteStringView that) const
bool FXSYS_IsHexDigit(char c)
int FXSYS_HexCharToInt(char c)
WideString operator+(const WideString &str1, const WideString &str2)
WideString operator+(wchar_t ch, const WideString &str2)
WideString operator+(const wchar_t *str1, const WideString &str2)