7#include "xfa/fgas/crt/cfgas_stringformatter.h"
16#include "core/fxcrt/cfx_datetime.h"
17#include "core/fxcrt/compiler_specific.h"
18#include "core/fxcrt/containers/contains.h"
19#include "core/fxcrt/fx_extension.h"
20#include "core/fxcrt/fx_safe_types.h"
21#include "core/fxcrt/notreached.h"
22#include "core/fxcrt/stl_util.h"
23#include "xfa/fgas/crt/cfgas_decimal.h"
24#include "xfa/fgas/crt/locale_mgr_iface.h"
30#define FX_NUMSTYLE_Percent 0x01
31#define FX_NUMSTYLE_Exponent 0x02
32#define FX_NUMSTYLE_DotVorv 0x04
36struct LocaleDateTimeSubcategoryWithHash {
41struct LocaleNumberSubcategoryWithHash {
47#define SUBC(a, b, c) a, c
48constexpr LocaleDateTimeSubcategoryWithHash kLocaleDateTimeSubcategoryData[] = {
56constexpr LocaleNumberSubcategoryWithHash kLocaleNumSubcategoryData[] = {
64struct FX_LOCALETIMEZONEINFO {
70constexpr auto kFXLocaleTimeZoneData =
71 fxcrt::ToArray<
const FX_LOCALETIMEZONEINFO>({
82constexpr wchar_t kTimeSymbols[] = L"hHkKMSFAzZ";
83constexpr wchar_t kDateSymbols[] = L"DJMEeGgYwW";
84constexpr wchar_t kConstChars[] = L",-:/. ";
86constexpr wchar_t kDateStr[] = L"date";
87constexpr wchar_t kTimeStr[] = L"time";
88constexpr wchar_t kDateTimeStr[] = L"datetime";
89constexpr wchar_t kNumStr[] = L"num";
90constexpr wchar_t kTextStr[] = L"text";
91constexpr wchar_t kZeroStr[] = L"zero";
92constexpr wchar_t kNullStr[] = L"null";
94size_t ParseTimeZone(pdfium::span<
const wchar_t> spStr,
int* tz) {
100 const bool bNegative = (spStr[0] ==
'-');
103 size_t iEnd = iStart + 2;
105 while (iStart < spStr.size() && iStart < iEnd)
106 tz_hour = tz_hour * 10 + FXSYS_DecimalCharToInt(spStr[iStart++]);
108 if (iStart < spStr.size() && spStr[iStart] ==
':')
113 while (iStart < spStr.size() && iStart < iEnd)
114 tz_minute = tz_minute * 10 + FXSYS_DecimalCharToInt(spStr[iStart++]);
116 *tz = tz_hour * 60 + tz_minute;
123int32_t ConvertHex(int32_t iKeyValue,
wchar_t ch) {
132WideString GetLiteralText(pdfium::span<
const wchar_t> spStrPattern,
135 if (*iPattern >= spStrPattern.size() || spStrPattern[*iPattern] !=
'\'')
140 while (*iPattern < spStrPattern.size()) {
141 if (spStrPattern[*iPattern] ==
'\'') {
144 if ((*iPattern >= spStrPattern.size()) ||
145 ((spStrPattern[*iPattern] !=
'\'') && (iQuote % 2 == 0))) {
149 }
else if (spStrPattern[*iPattern] ==
'\\' &&
150 (*iPattern + 1 < spStrPattern.size()) &&
151 spStrPattern[*iPattern + 1] ==
'u') {
152 int32_t iKeyValue = 0;
154 for (int32_t i = 0; *iPattern < spStrPattern.size() && i < 4; ++i) {
155 wchar_t ch = spStrPattern[(*iPattern)++];
156 iKeyValue = ConvertHex(iKeyValue, ch);
159 wsOutput
+= static_cast<
wchar_t>(iKeyValue & 0x0000FFFF);
163 wsOutput += spStrPattern[(*iPattern)++];
168WideString GetLiteralTextReverse(pdfium::span<
const wchar_t> spStrPattern,
171 if (*iPattern >= spStrPattern.size() || spStrPattern[*iPattern] !=
'\'')
177 while (*iPattern < spStrPattern.size()) {
178 if (spStrPattern[*iPattern] ==
'\'') {
180 if (*iPattern - 1 >= spStrPattern.size() ||
181 ((spStrPattern[*iPattern - 1] !=
'\'') && (iQuote % 2 == 0))) {
186 }
else if (spStrPattern[*iPattern] ==
'\\' &&
187 *iPattern + 1 < spStrPattern.size() &&
188 spStrPattern[*iPattern + 1] ==
'u') {
190 int32_t iKeyValue = 0;
191 size_t iLen = std::min<size_t>(wsOutput.GetLength(), 5);
193 for (; i < iLen; i++) {
194 wchar_t ch = wsOutput[i];
195 iKeyValue = ConvertHex(iKeyValue, ch);
197 if (iKeyValue != 0) {
198 wsOutput.Delete(0, i);
199 wsOutput
= (
wchar_t)(iKeyValue & 0x0000FFFF)
+ wsOutput;
203 wsOutput = spStrPattern[(*iPattern)--] + wsOutput;
208bool GetNumericDotIndex(
const WideString& wsNum,
211 pdfium::span<
const wchar_t> spNum = wsNum.span();
212 pdfium::span<
const wchar_t> spDotSymbol = wsDotSymbol.span();
214 while (ccf < spNum.size()) {
215 if (spNum[ccf] ==
'\'') {
216 GetLiteralText(spNum, &ccf);
219 if (ccf + spDotSymbol.size() <= spNum.size() &&
220 wcsncmp(&spNum[ccf], spDotSymbol.data(), spDotSymbol.size()) == 0) {
226 auto result = wsNum.Find(
'.');
227 *iDotIndex = result.value_or(spNum.size());
228 return result.has_value();
231bool ExtractCountDigits(pdfium::span<
const wchar_t> spStr,
235 for (size_t i = 0; i < count; ++i) {
236 if (*cc >= spStr.size() || !FXSYS_IsDecimalDigit(spStr[*cc]))
238 *value = *value * 10 + FXSYS_DecimalCharToInt(spStr[(*cc)++]);
243bool ExtractCountDigitsWithOptional(pdfium::span<
const wchar_t> spStr,
247 if (!ExtractCountDigits(spStr, count, cc, value))
249 ExtractCountDigits(spStr, 1, cc, value);
258 uint32_t year = 1900;
262 pdfium::span<
const wchar_t> spDate = wsDate.span();
263 pdfium::span<
const wchar_t> spDatePattern = wsDatePattern.span();
264 while (*cc < spDate.size() && ccf < spDatePattern.size()) {
265 if (spDatePattern[ccf] ==
'\'') {
266 WideString wsLiteral = GetLiteralText(spDatePattern, &ccf);
267 size_t iLiteralLen = wsLiteral.GetLength();
268 if (*cc + iLiteralLen > spDate.size() ||
269 UNSAFE_TODO(wcsncmp(spDate.data() + *cc, wsLiteral.c_str(),
270 iLiteralLen)) != 0) {
276 if (!
pdfium::Contains(kDateSymbols, spDatePattern[ccf])) {
277 if (spDatePattern[ccf] != spDate[*cc])
286 symbol += spDatePattern[ccf++];
287 while (ccf < spDatePattern.size() && spDatePattern[ccf] == symbol[0]) {
288 symbol += spDatePattern[ccf++];
292 if (!ExtractCountDigitsWithOptional(spDate, 1, cc, &day))
296 ExtractCountDigits(spDate, 3, cc, &val);
299 if (!ExtractCountDigitsWithOptional(spDate, 1, cc, &month))
302 for (uint16_t i = 0; i < 12; i++) {
305 if (wsMonthName.IsEmpty())
307 if (
UNSAFE_TODO(wcsncmp(wsMonthName.c_str(), spDate.data() + *cc,
308 wsMonthName.GetLength())) == 0) {
309 *cc += wsMonthName.GetLength();
315 for (uint16_t i = 0; i < 7; i++) {
318 if (wsDayName.IsEmpty())
320 if (
UNSAFE_TODO(wcsncmp(wsDayName.c_str(), spDate.data() + *cc,
321 wsDayName.GetLength())) == 0) {
322 *cc += wsDayName.GetLength();
327 if (*cc + symbol.GetLength() > spDate.size())
331 if (!ExtractCountDigits(spDate, symbol.GetLength(), cc, &year))
343 *cc += symbol.GetLength();
346 if (*cc < spDate.size())
353void ResolveZone(
int tz_diff_minutes,
357 int32_t iMinuteDiff = *wHour * 60 + *wMinute;
359 iMinuteDiff -= tz_diff_minutes;
365 *wHour = iMinuteDiff / 60;
366 *wMinute = iMinuteDiff % 60;
377 uint32_t millisecond = 0;
379 pdfium::span<
const wchar_t> spTime = wsTime.span();
380 pdfium::span<
const wchar_t> spTimePattern = wsTimePattern.span();
383 while (*cc < spTime.size() && ccf < spTimePattern.size()) {
384 if (spTimePattern[ccf] ==
'\'') {
385 WideString wsLiteral = GetLiteralText(spTimePattern, &ccf);
386 size_t iLiteralLen = wsLiteral.GetLength();
387 if (*cc + iLiteralLen > spTime.size() ||
388 UNSAFE_TODO(wcsncmp(spTime.data() + *cc, wsLiteral.c_str(),
389 iLiteralLen)) != 0) {
395 if (!
pdfium::Contains(kTimeSymbols, spTimePattern[ccf])) {
396 if (spTimePattern[ccf] != spTime[*cc])
405 symbol += spTimePattern[ccf++];
406 while (ccf < spTimePattern.size() && spTimePattern[ccf] == symbol[0])
407 symbol += spTimePattern[ccf++];
411 if (!ExtractCountDigitsWithOptional(spTime, 1, cc, &hour))
418 if (!ExtractCountDigits(spTime, 2, cc, &hour))
424 if (!ExtractCountDigitsWithOptional(spTime, 1, cc, &minute))
428 if (!ExtractCountDigits(spTime, 2, cc, &minute))
432 if (!ExtractCountDigitsWithOptional(spTime, 1, cc, &second))
436 if (!ExtractCountDigits(spTime, 2, cc, &second))
440 if (!ExtractCountDigits(spTime, 3, cc, &millisecond))
445 if (*cc + wsAM.GetLength() <= spTime.size() &&
447 *cc += wsAM.GetLength();
449 }
else if (*cc + wsPM.GetLength() <= spTime.size() &&
452 *cc += wsPM.GetLength();
457 if (*cc + 3 > spTime.size())
461 tz += spTime[(*cc)++];
462 tz += spTime[(*cc)++];
464 int tz_diff_minutes = 0;
465 if (*cc < spTime.size() && (spTime[*cc] ==
'-' || spTime[*cc] ==
'+'))
466 *cc += ParseTimeZone(spTime.subspan(*cc), &tz_diff_minutes);
467 ResolveZone(tz_diff_minutes, pLocale, &hour, &minute);
470 for (size_t i = 0; i <
std::size(kFXLocaleTimeZoneData); ++i) {
471 const FX_LOCALETIMEZONEINFO& info = kFXLocaleTimeZoneData[i];
476 minute += info.iHour > 0 ? info.iMinute : -info.iMinute;
481 if (spTime[*cc] !=
'Z') {
482 int tz_diff_minutes = 0;
483 *cc += ParseTimeZone(spTime.subspan(*cc), &tz_diff_minutes);
484 ResolveZone(tz_diff_minutes, pLocale, &hour, &minute);
504size_t GetNumTrailingLimit(
const WideString& wsFormat,
506 bool* bTrimTailZeros) {
507 const pdfium::span<
const wchar_t> spFormat = wsFormat.span();
508 size_t iTrailing = 0;
509 for (++iDotPos; iDotPos < spFormat.size(); ++iDotPos) {
510 wchar_t wc = spFormat[iDotPos];
511 if (wc == L'z' || wc == L'9' || wc ==
'Z') {
513 *bTrimTailZeros = wc != L'9';
519bool IsLeapYear(uint32_t year) {
520 return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
523bool MonthHas30Days(uint32_t month) {
524 return month == 4 || month == 6 || month == 9 || month == 11;
527bool MonthHas31Days(uint32_t month) {
528 return month != 2 && !MonthHas30Days(month);
532uint16_t GetSolarMonthDays(uint16_t year, uint16_t month) {
536 return MonthHas30Days(month) ? 30 : 31;
539uint16_t GetWeekDay(uint16_t year, uint16_t month, uint16_t day) {
540 static constexpr auto kMonthDay =
541 fxcrt::ToArray<
const uint8_t>({0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5});
543 (year - 1) % 7 + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
544 nDays += kMonthDay[month - 1] + day;
550uint16_t GetWeekOfMonth(uint16_t year, uint16_t month, uint16_t day) {
551 uint16_t week_day = GetWeekDay(year, month, 1);
552 uint16_t week_index = 0;
553 week_index += day / 7;
555 if (week_day + day > 7)
560uint16_t GetWeekOfYear(uint16_t year, uint16_t month, uint16_t day) {
562 for (uint16_t i = 1; i < month; i++)
563 nDays += GetSolarMonthDays(year, i);
566 uint16_t week_day = GetWeekDay(year, 1, 1);
567 uint16_t week_index = 1;
568 week_index += nDays / 7;
570 if (week_day + nDays > 7)
575WideString NumToString(size_t fmt_size, int32_t value) {
577 fmt_size == 1 ? L"%d" : fmt_size == 2 ? L"%02d" : L"%03d"
, value
);
588 pdfium::span<
const wchar_t> spDatePattern = wsDatePattern.span();
589 while (ccf < spDatePattern.size()) {
590 if (spDatePattern[ccf] ==
'\'') {
591 wsResult += GetLiteralText(spDatePattern, &ccf);
594 if (!
pdfium::Contains(kDateSymbols, spDatePattern[ccf])) {
595 wsResult += spDatePattern[ccf++];
600 symbol += spDatePattern[ccf++];
601 while (ccf < spDatePattern.size() && spDatePattern[ccf] == symbol[0])
602 symbol += spDatePattern[ccf++];
605 wsResult += NumToString(symbol.GetLength(), day);
608 for (
int i = 1; i < month; i++)
609 nDays += GetSolarMonthDays(year, i);
611 wsResult += NumToString(symbol.GetLength(), nDays);
613 wsResult += NumToString(symbol.GetLength(), month);
617 uint16_t wWeekDay = GetWeekDay(year, month, day);
619 NumToString(1, symbol.EqualsASCII(
"E") ? wWeekDay + 1
620 : (wWeekDay ? wWeekDay : 7));
627 wsResult += NumToString(2, year % 100);
629 wsResult += NumToString(1, year);
631 wsResult += NumToString(1, GetWeekOfMonth(year, month, day));
633 wsResult += NumToString(2, GetWeekOfYear(year, month, day));
648 pdfium::span<
const wchar_t> spTimePattern = wsTimePattern.span();
649 uint16_t wHour = hour;
651 if (wsTimePattern.Contains(
'A')) {
656 while (ccf < spTimePattern.size()) {
657 if (spTimePattern[ccf] ==
'\'') {
658 wsResult += GetLiteralText(spTimePattern, &ccf);
661 if (!
pdfium::Contains(kTimeSymbols, spTimePattern[ccf])) {
662 wsResult += spTimePattern[ccf++];
668 symbol += spTimePattern[ccf++];
669 while (ccf < spTimePattern.size() && spTimePattern[ccf] == symbol[0])
670 symbol += spTimePattern[ccf++];
675 wsResult += NumToString(symbol.GetLength(), wHour == 0 ? 12 : wHour);
677 wsResult += NumToString(symbol.GetLength(), wHour == 0 ? 24 : wHour);
681 wsResult += NumToString(symbol.GetLength(), wHour);
683 wsResult += NumToString(symbol.GetLength(), wHour);
685 wsResult += NumToString(symbol.GetLength(), minute);
687 wsResult += NumToString(symbol.GetLength(), second);
689 wsResult += NumToString(3, millisecond);
696 if (tz_minutes != 0) {
697 wsResult
+= tz_minutes < 0 ? L"-" : L"+";
698 int abs_tz_minutes = abs(tz_minutes);
700 abs_tz_minutes % 60
);
713 if (!wsDatePattern.IsEmpty())
714 wsDateOut
= DateFormat(wsDatePattern, pLocale, dt);
717 if (!wsTimePattern.IsEmpty())
718 wsTimeOut
= TimeFormat(wsTimePattern, pLocale, dt);
720 return bDateFirst ? wsDateOut
+ wsTimeOut : wsTimeOut
+ wsDateOut;
763 if (spDate.size() > 10)
768 if (!ExtractCountDigits(spDate, 4, &cc, &year))
772 if (cc >= spDate.size()) {
777 if (spDate[cc] ==
'-')
781 if (!ExtractCountDigits(spDate, 2, &cc, &month) || month < 1 || month > 12)
784 if (cc >= spDate.size()) {
789 if (spDate[cc] ==
'-')
793 if (!ExtractCountDigits(spDate, 2, &cc, &day))
797 if ((MonthHas31Days(month) && day > 31) ||
798 (MonthHas30Days(month) && day > 30)) {
801 if (month == 2 && day > (IsLeapYear(year) ? 29U : 28U))
809 pdfium::span<
const wchar_t> spTime,
816 if (!ExtractCountDigits(spTime, 2, &cc, &hour) || hour >= 24)
819 if (cc >= spTime.size()) {
824 if (spTime[cc] ==
':')
828 if (!ExtractCountDigits(spTime, 2, &cc, &minute) || minute >= 60)
831 if (cc >= spTime.size()) {
836 if (spTime[cc] ==
':')
840 uint32_t millisecond = 0;
841 if (cc < spTime.size() && spTime[cc] !=
'Z') {
842 if (!ExtractCountDigits(spTime, 2, &cc, &second) || second >= 60)
845 if (cc < spTime.size() && spTime[cc] ==
'.') {
847 if (!ExtractCountDigits(spTime, 3, &cc, &millisecond))
853 while (cc < spTime.size()) {
854 if (spTime[cc] ==
'+' || spTime[cc] ==
'-')
859 if (cc < spTime.size()) {
860 int tz_diff_minutes = 0;
861 if (spTime[cc] !=
'Z')
862 cc += ParseTimeZone(spTime.subspan(cc), &tz_diff_minutes);
863 ResolveZone(tz_diff_minutes, pLocale, &hour, &minute);
878 std::vector<WideString> wsPatterns;
879 pdfium::span<
const wchar_t> spFormatString = wsFormatString.span();
883 for (; index < spFormatString.size(); ++index) {
884 if (spFormatString[index] ==
'\'') {
886 }
else if (spFormatString[index] == L'|' && !bQuote) {
888 WideString(spFormatString.data() + token, index - token)));
892 wsPatterns.push_back(
900 bool bBraceOpen =
false;
901 while (ccf < m_spPattern.size()) {
902 if (m_spPattern[ccf] ==
'\'') {
903 GetLiteralText(m_spPattern, &ccf);
906 if (!bBraceOpen && !pdfium::Contains(kConstChars, m_spPattern[ccf])) {
910 if (ccf >= m_spPattern.size())
912 if (m_spPattern[ccf] ==
'.' || m_spPattern[ccf] ==
'(')
914 if (m_spPattern[ccf] ==
'{') {
918 wsCategory += m_spPattern[ccf];
921 if (wsCategory
== kDateTimeStr)
923 if (wsCategory
== kTextStr)
925 if (wsCategory
== kNumStr)
927 if (wsCategory
== kZeroStr)
929 if (wsCategory
== kNullStr)
931 if (wsCategory
== kDateStr) {
935 }
else if (wsCategory
== kTimeStr) {
940 }
else if (m_spPattern[ccf] ==
'}') {
951 bool bBrackOpen =
false;
953 while (ccf < m_spPattern.size()) {
954 if (m_spPattern[ccf] ==
'\'') {
955 size_t iCurChar = ccf;
956 GetLiteralText(m_spPattern, &ccf);
958 WideStringView(m_spPattern.subspan(iCurChar, ccf - iCurChar));
961 if (!bBrackOpen && !pdfium::Contains(kConstChars, m_spPattern[ccf])) {
962 WideString wsSearchCategory(m_spPattern[ccf]);
964 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
'{' &&
965 m_spPattern[ccf] !=
'.' && m_spPattern[ccf] !=
'(') {
966 wsSearchCategory += m_spPattern[ccf];
969 if (wsSearchCategory != wsCategory)
972 while (ccf < m_spPattern.size()) {
973 if (m_spPattern[ccf] ==
'(') {
976 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
')')
978 }
else if (m_spPattern[ccf] ==
'{') {
984 }
else if (m_spPattern[ccf] !=
'}') {
985 wsPurgePattern += m_spPattern[ccf];
990 wsPurgePattern = m_wsPattern;
992 return wsPurgePattern;
1003 bool bFindDot =
false;
1004 bool bBrackOpen =
false;
1005 while (ccf < m_spPattern.size()) {
1006 if (m_spPattern[ccf] ==
'\'') {
1007 size_t iCurChar = ccf;
1008 GetLiteralText(m_spPattern, &ccf);
1010 WideStringView(m_spPattern.subspan(iCurChar, ccf - iCurChar));
1013 if (!bBrackOpen && !pdfium::Contains(kConstChars, m_spPattern[ccf])) {
1016 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
'{' &&
1017 m_spPattern[ccf] !=
'.' && m_spPattern[ccf] !=
'(') {
1018 wsCategory += m_spPattern[ccf];
1026 while (ccf < m_spPattern.size()) {
1027 if (m_spPattern[ccf] ==
'{') {
1031 if (m_spPattern[ccf] ==
'(') {
1034 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
')')
1035 wsLCID += m_spPattern[ccf++];
1038 }
else if (m_spPattern[ccf] ==
'.') {
1041 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
'(' &&
1042 m_spPattern[ccf] !=
'{') {
1043 wsSubCategory += m_spPattern[ccf++];
1045 uint32_t dwSubHash = FX_HashCode_GetW(wsSubCategory.AsStringView());
1048 for (
const auto& data : kLocaleNumSubcategoryData) {
1049 if (data.uHash == dwSubHash) {
1050 eSubCategory = data.eSubCategory;
1058 auto result = wsSubCategory.Find(
'.');
1059 if (result.has_value() && result.value() != 0) {
1061 *iDotIndex = wsPurgePattern->GetLength() + result.value();
1065 *wsPurgePattern
+= wsSubCategory;
1072 }
else if (m_spPattern[ccf] ==
'E') {
1074 *wsPurgePattern += m_spPattern[ccf];
1075 }
else if (m_spPattern[ccf] ==
'%') {
1077 *wsPurgePattern += m_spPattern[ccf];
1078 }
else if (m_spPattern[ccf] !=
'}') {
1079 *wsPurgePattern += m_spPattern[ccf];
1081 if (!bFindDot && ccf < m_spPattern.size() &&
1082 (m_spPattern[ccf] ==
'.' || m_spPattern[ccf] ==
'V' ||
1083 m_spPattern[ccf] ==
'v')) {
1085 *iDotIndex = wsPurgePattern->GetLength() - 1;
1091 *iDotIndex = wsPurgePattern->GetLength();
1100 if (wsSrcText.IsEmpty() || m_spPattern.empty())
1103 WideString wsTextFormat = GetTextFormat(L"text");
1104 if (wsTextFormat.IsEmpty())
1107 pdfium::span<
const wchar_t> spSrcText = wsSrcText.span();
1108 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
1111 size_t iPattern = 0;
1112 while (iPattern < spTextFormat.size() && iText < spSrcText.size()) {
1113 switch (spTextFormat[iPattern]) {
1115 WideString wsLiteral = GetLiteralText(spTextFormat, &iPattern);
1116 size_t iLiteralLen = wsLiteral.GetLength();
1117 if (iText + iLiteralLen > spSrcText.size() ||
1118 UNSAFE_TODO(wcsncmp(spSrcText.data() + iText, wsLiteral.c_str(),
1119 iLiteralLen)) != 0) {
1120 *wsValue
= wsSrcText;
1123 iText += iLiteralLen;
1127 if (FXSYS_iswalpha(spSrcText[iText])) {
1128 *wsValue += spSrcText[iText];
1134 *wsValue += spSrcText[iText];
1140 if (FXSYS_IsDecimalDigit(spSrcText[iText]) ||
1141 FXSYS_iswalpha(spSrcText[iText])) {
1142 *wsValue += spSrcText[iText];
1148 if (FXSYS_IsDecimalDigit(spSrcText[iText])) {
1149 *wsValue += spSrcText[iText];
1155 if (spTextFormat[iPattern] != spSrcText[iText]) {
1156 *wsValue
= wsSrcText;
1164 return iPattern == spTextFormat.size() && iText == spSrcText.size();
1171 if (wsSrcNum.IsEmpty() || m_spPattern.empty())
1174 size_t dot_index_f = m_spPattern.size();
1175 uint32_t dwFormatStyle = 0;
1178 GetNumericFormat(pLocaleMgr, &dot_index_f, &dwFormatStyle, &wsNumFormat);
1179 if (!pLocale || wsNumFormat.IsEmpty())
1182 int32_t iExponent = 0;
1186 size_t iGroupLen = wsGroupSymbol.GetLength();
1187 size_t iMinusLen = wsMinus.GetLength();
1189 pdfium::span<
const wchar_t> spSrcNum = wsSrcNum.span();
1190 pdfium::span<
const wchar_t> spNumFormat = wsNumFormat.span();
1192 bool bHavePercentSymbol =
false;
1194 bool bReverseParse =
false;
1195 size_t dot_index = 0;
1199 if (!GetNumericDotIndex(wsSrcNum, wsDotSymbol, &dot_index) &&
1201 bReverseParse =
true;
1211 size_t cc = dot_index - 1;
1212 size_t ccf = dot_index_f - 1;
1213 while (ccf < spNumFormat.size() && cc < spSrcNum.size()) {
1214 switch (spNumFormat[ccf]) {
1216 WideString wsLiteral = GetLiteralTextReverse(spNumFormat, &ccf);
1217 size_t iLiteralLen = wsLiteral.GetLength();
1218 cc -= iLiteralLen - 1;
1219 if (cc >= spSrcNum.size() ||
1220 UNSAFE_TODO(wcsncmp(spSrcNum.data() + cc, wsLiteral.c_str(),
1221 iLiteralLen)) != 0) {
1229 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
1232 wsValue->InsertAtFront(spSrcNum[cc]);
1238 if (spNumFormat[ccf] ==
'z' || spSrcNum[cc] !=
' ') {
1239 if (FXSYS_IsDecimalDigit(spSrcNum[cc])) {
1240 wsValue->InsertAtFront(spSrcNum[cc]);
1250 if (spSrcNum[cc] ==
'+' ||
1251 (spNumFormat[ccf] ==
'S' && spSrcNum[cc] ==
' ')) {
1254 cc -= iMinusLen - 1;
1255 if (cc >= spSrcNum.size() ||
1256 UNSAFE_TODO(wcsncmp(spSrcNum.data() + cc, wsMinus.c_str(),
1267 bool bExpSign =
false;
1268 while (cc < spSrcNum.size()) {
1269 if (spSrcNum[cc] ==
'E' || spSrcNum[cc] ==
'e')
1271 if (FXSYS_IsDecimalDigit(spSrcNum[cc])) {
1272 if (iExponent >
std::numeric_limits<
int>::max() / 10)
1274 iExponent = iExponent + FXSYS_DecimalCharToInt(spSrcNum[cc]) * 10;
1278 if (spSrcNum[cc] ==
'+') {
1282 if (cc - iMinusLen + 1 <= spSrcNum.size() &&
1283 UNSAFE_TODO(wcsncmp(spSrcNum.data() + (cc - iMinusLen + 1),
1284 wsMinus.c_str(), iMinusLen)) == 0) {
1293 iExponent = bExpSign ? -iExponent : iExponent;
1299 size_t iSymbolLen = wsSymbol.GetLength();
1300 cc -= iSymbolLen - 1;
1301 if (cc >= spSrcNum.size() ||
1302 UNSAFE_TODO(wcsncmp(spSrcNum.data() + cc, wsSymbol.c_str(),
1303 iSymbolLen)) != 0) {
1312 if (ccf - 1 < spNumFormat.size() &&
1313 ((spNumFormat[ccf] ==
'R' && spNumFormat[ccf - 1] ==
'C') ||
1314 (spNumFormat[ccf] ==
'r' && spNumFormat[ccf - 1] ==
'c'))) {
1315 if (spNumFormat[ccf] ==
'R' && spSrcNum[cc] ==
' ') {
1317 }
else if (spSrcNum[cc] ==
'R' && cc - 1 < spSrcNum.size() &&
1318 spSrcNum[cc - 1] ==
'C') {
1329 if (ccf - 1 < spNumFormat.size() &&
1330 ((spNumFormat[ccf] ==
'B' && spNumFormat[ccf - 1] ==
'D') ||
1331 (spNumFormat[ccf] ==
'b' && spNumFormat[ccf - 1] ==
'd'))) {
1332 if (spNumFormat[ccf] ==
'B' && spSrcNum[cc] ==
' ') {
1334 }
else if (spSrcNum[cc] ==
'B' && cc - 1 < spSrcNum.size() &&
1335 spSrcNum[cc - 1] ==
'D') {
1346 size_t iSymbolLen = wsSymbol.GetLength();
1347 cc -= iSymbolLen - 1;
1348 if (cc >= spSrcNum.size() ||
1349 UNSAFE_TODO(wcsncmp(spSrcNum.data() + cc, wsSymbol.c_str(),
1350 iSymbolLen)) != 0) {
1355 bHavePercentSymbol =
true;
1364 if (cc < spSrcNum.size()) {
1365 cc -= iGroupLen - 1;
1366 if (cc < spSrcNum.size() &&
1367 UNSAFE_TODO(wcsncmp(spSrcNum.data() + cc, wsGroupSymbol.c_str(),
1371 cc += iGroupLen - 1;
1379 if (spSrcNum[cc] == spNumFormat[ccf])
1381 else if (spSrcNum[cc] != L' ')
1388 if (spNumFormat[ccf] != spSrcNum[cc])
1395 if (cc < spSrcNum.size()) {
1396 if (spSrcNum[cc] ==
'-') {
1400 if (cc < spSrcNum.size())
1406 if (!bReverseParse) {
1407 cc = (dot_index == spSrcNum.size()) ? spSrcNum.size() : dot_index + 1;
1408 ccf = dot_index_f + 1;
1409 while (cc < spSrcNum.size() && ccf < spNumFormat.size()) {
1410 switch (spNumFormat[ccf]) {
1412 WideString wsLiteral = GetLiteralText(spNumFormat, &ccf);
1413 size_t iLiteralLen = wsLiteral.GetLength();
1414 if (cc + iLiteralLen > spSrcNum.size() ||
1415 UNSAFE_TODO(wcsncmp(spSrcNum.data() + cc, wsLiteral.c_str(),
1416 iLiteralLen)) != 0) {
1423 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
1426 *wsValue += spSrcNum[cc];
1431 if (spNumFormat[ccf] ==
'z' || spSrcNum[cc] !=
' ') {
1432 if (FXSYS_IsDecimalDigit(spSrcNum[cc])) {
1433 *wsValue += spSrcNum[cc];
1442 if (spSrcNum[cc] ==
'+' ||
1443 (spNumFormat[ccf] ==
'S' && spSrcNum[cc] ==
' ')) {
1446 if (cc + iMinusLen > spSrcNum.size() ||
1447 UNSAFE_TODO(wcsncmp(spSrcNum.data() + cc, wsMinus.c_str(),
1456 if (cc >= spSrcNum.size() ||
1457 (spSrcNum[cc] !=
'E' && spSrcNum[cc] !=
'e')) {
1461 bool bExpSign =
false;
1463 if (cc < spSrcNum.size()) {
1464 if (spSrcNum[cc] ==
'+') {
1466 }
else if (spSrcNum[cc] ==
'-') {
1471 while (cc < spSrcNum.size()) {
1472 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
1474 int digit = FXSYS_DecimalCharToInt(spSrcNum[cc]);
1475 if (iExponent > (
std::numeric_limits<
int>::max() - digit) / 10)
1477 iExponent = iExponent * 10 + digit;
1480 iExponent = bExpSign ? -iExponent : iExponent;
1485 size_t iSymbolLen = wsSymbol.GetLength();
1486 if (cc + iSymbolLen > spSrcNum.size() ||
1487 UNSAFE_TODO(wcsncmp(spSrcNum.data() + cc, wsSymbol.c_str(),
1488 iSymbolLen)) != 0) {
1496 if (ccf + 1 < spNumFormat.size() &&
1497 ((spNumFormat[ccf] ==
'C' && spNumFormat[ccf + 1] ==
'R') ||
1498 (spNumFormat[ccf] ==
'c' && spNumFormat[ccf + 1] ==
'r'))) {
1499 if (spNumFormat[ccf] ==
'C' && spSrcNum[cc] ==
' ') {
1501 }
else if (spSrcNum[cc] ==
'C' && cc + 1 < spSrcNum.size() &&
1502 spSrcNum[cc + 1] ==
'R') {
1511 if (ccf + 1 < spNumFormat.size() &&
1512 ((spNumFormat[ccf] ==
'D' && spNumFormat[ccf + 1] ==
'B') ||
1513 (spNumFormat[ccf] ==
'd' && spNumFormat[ccf + 1] ==
'b'))) {
1514 if (spNumFormat[ccf] ==
'D' && spSrcNum[cc] ==
' ') {
1516 }
else if (spSrcNum[cc] ==
'D' && cc + 1 < spSrcNum.size() &&
1517 spSrcNum[cc + 1] ==
'B') {
1530 size_t iSymbolLen = wsSymbol.GetLength();
1531 if (cc + iSymbolLen <= spSrcNum.size() &&
1532 UNSAFE_TODO(wcsncmp(spSrcNum.data() + cc, wsSymbol.c_str(),
1533 iSymbolLen)) == 0) {
1536 bHavePercentSymbol =
true;
1539 while (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'8')
1542 while (cc < spSrcNum.size() && FXSYS_IsDecimalDigit(spSrcNum[cc])) {
1543 *wsValue += spSrcNum[cc];
1548 if (cc + iGroupLen <= spSrcNum.size() &&
1549 UNSAFE_TODO(wcsncmp(spSrcNum.data() + cc, wsGroupSymbol.c_str(),
1557 if (spSrcNum[cc] == spNumFormat[ccf])
1559 else if (spSrcNum[cc] != L' ')
1565 if (spNumFormat[ccf] != spSrcNum[cc])
1572 if (cc != spSrcNum.size())
1575 if (iExponent || bHavePercentSymbol) {
1579 if (bHavePercentSymbol)
1584 wsValue->InsertAtFront(L'-');
1599 bool bBraceOpen =
false;
1600 while (ccf < m_spPattern.size()) {
1601 if (m_spPattern[ccf] ==
'\'') {
1602 size_t iCurChar = ccf;
1603 GetLiteralText(m_spPattern, &ccf);
1605 WideStringView(m_spPattern.subspan(iCurChar, ccf - iCurChar));
1608 if (!bBraceOpen && eDateTimeType != DateTimeType::kDateTime &&
1609 !pdfium::Contains(kConstChars, m_spPattern[ccf])) {
1612 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
'{' &&
1613 m_spPattern[ccf] !=
'.' && m_spPattern[ccf] !=
'(') {
1614 if (m_spPattern[ccf] ==
'T') {
1615 *wsDatePattern = m_wsPattern.First(ccf);
1616 *wsTimePattern = m_wsPattern.Last(m_wsPattern.GetLength() - ccf);
1617 wsTimePattern->SetAt(0,
' ');
1622 wsCategory += m_spPattern[ccf];
1625 if (!HasDate(eDateTimeType) && wsCategory
.EqualsASCII(
"date")) {
1626 eDateTimeType = AddDateToDatelessType(eDateTimeType);
1628 }
else if (!HasTime(eDateTimeType) && wsCategory
.EqualsASCII(
"time")) {
1629 eDateTimeType = AddTimeToTimelessType(eDateTimeType);
1637 while (ccf < m_spPattern.size()) {
1638 if (m_spPattern[ccf] ==
'{') {
1642 if (m_spPattern[ccf] ==
'(') {
1645 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
')')
1646 wsLCID += m_spPattern[ccf++];
1649 }
else if (m_spPattern[ccf] ==
'.') {
1652 while (ccf < m_spPattern.size() && m_spPattern[ccf] !=
'(' &&
1653 m_spPattern[ccf] !=
'{')
1654 wsSubCategory += m_spPattern[ccf++];
1656 uint32_t dwSubHash = FX_HashCode_GetW(wsSubCategory.AsStringView());
1659 for (
const auto& data : kLocaleDateTimeSubcategoryData) {
1660 if (data.uHash == dwSubHash) {
1661 eSubCategory = data.eSubCategory;
1668 switch (eCategory) {
1685 wsTempPattern.clear();
1690 }
else if (m_spPattern[ccf] ==
'}') {
1692 if (!wsTempPattern.IsEmpty()) {
1694 *wsTimePattern =
std::move(wsTempPattern);
1696 *wsDatePattern =
std::move(wsTempPattern);
1698 wsTempPattern.clear();
1701 wsTempPattern += m_spPattern[ccf];
1706 if (!wsTempPattern.IsEmpty()) {
1708 *wsDatePattern
+= wsTempPattern;
1710 *wsTimePattern
+= wsTempPattern;
1715 wsTimePattern->clear();
1716 *wsDatePattern = m_wsPattern;
1718 return eDateTimeType;
1726 if (wsSrcDateTime.IsEmpty() || m_spPattern.empty())
1733 GetDateTimeFormat(pLocaleMgr, &pLocale, &wsDatePattern, &wsTimePattern);
1738 eCategory = eDateTimeType;
1741 switch (eCategory) {
1742 case DateTimeType::kDate:
1743 return ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue,
1745 case DateTimeType::kTime:
1746 return ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue,
1748 case DateTimeType::kDateTime:
1749 return ParseLocaleDate(wsSrcDateTime, wsTimePattern, pLocale, dtValue,
1751 ParseLocaleTime(wsSrcDateTime, wsDatePattern, pLocale, dtValue,
1753 case DateTimeType::kTimeDate:
1754 return ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue,
1756 ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue,
1764 WideString wsTextFormat = GetTextFormat(L"zero");
1765 pdfium::span<
const wchar_t> spSrcText = wsSrcText.span();
1766 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
1769 size_t iPattern = 0;
1770 while (iPattern < spTextFormat.size() && iText < spSrcText.size()) {
1771 if (spTextFormat[iPattern] ==
'\'') {
1772 WideString wsLiteral = GetLiteralText(spTextFormat, &iPattern);
1773 size_t iLiteralLen = wsLiteral.GetLength();
1774 if (iText + iLiteralLen > spSrcText.size() ||
1775 UNSAFE_TODO(wcsncmp(spSrcText.data() + iText, wsLiteral.c_str(),
1779 iText += iLiteralLen;
1782 if (spTextFormat[iPattern] != spSrcText[iText]) {
1788 return iPattern == spTextFormat.size() && iText == spSrcText.size();
1792 WideString wsTextFormat = GetTextFormat(L"null");
1793 pdfium::span<
const wchar_t> spSrcText = wsSrcText.span();
1794 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
1797 size_t iPattern = 0;
1798 while (iPattern < spTextFormat.size() && iText < spSrcText.size()) {
1799 if (spTextFormat[iPattern] ==
'\'') {
1800 WideString wsLiteral = GetLiteralText(spTextFormat, &iPattern);
1801 size_t iLiteralLen = wsLiteral.GetLength();
1802 if (iText + iLiteralLen > spSrcText.size() ||
1803 UNSAFE_TODO(wcsncmp(spSrcText.data() + iText, wsLiteral.c_str(),
1807 iText += iLiteralLen;
1810 if (spTextFormat[iPattern] != spSrcText[iText]) {
1816 return iPattern == spTextFormat.size() && iText == spSrcText.size();
1821 if (wsSrcText.IsEmpty() || m_spPattern.empty())
1824 WideString wsTextFormat = GetTextFormat(L"text");
1825 pdfium::span<
const wchar_t> spSrcText = wsSrcText.span();
1826 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
1829 size_t iPattern = 0;
1830 while (iPattern < spTextFormat.size()) {
1831 switch (spTextFormat[iPattern]) {
1833 *wsOutput += GetLiteralText(spTextFormat, &iPattern);
1837 if (iText >= spSrcText.size() || !FXSYS_iswalpha(spSrcText[iText]))
1840 *wsOutput += spSrcText[iText++];
1844 if (iText >= spSrcText.size())
1847 *wsOutput += spSrcText[iText++];
1852 if (iText >= spSrcText.size() ||
1853 (!FXSYS_IsDecimalDigit(spSrcText[iText]) &&
1854 !FXSYS_iswalpha(spSrcText[iText]))) {
1857 *wsOutput += spSrcText[iText++];
1861 if (iText >= spSrcText.size() ||
1862 !FXSYS_IsDecimalDigit(spSrcText[iText]))
1865 *wsOutput += spSrcText[iText++];
1869 *wsOutput += spTextFormat[iPattern++];
1873 return iText == spSrcText.size();
1879 if (wsInputNum.IsEmpty() || m_spPattern.empty())
1882 size_t dot_index_f = m_spPattern.size();
1883 uint32_t dwNumStyle = 0;
1886 GetNumericFormat(pLocaleMgr, &dot_index_f, &dwNumStyle, &wsNumFormat);
1887 if (!pLocale || wsNumFormat.IsEmpty())
1890 pdfium::span<
const wchar_t> spNumFormat = wsNumFormat.span();
1892 wsSrcNum.TrimFront(
'0');
1893 if (wsSrcNum.IsEmpty() || wsSrcNum[0] ==
'.')
1894 wsSrcNum.InsertAtFront(
'0');
1902 int32_t exponent = 0;
1904 int fixed_count = 0;
1906 while (ccf < dot_index_f) {
1907 switch (spNumFormat[ccf]) {
1909 GetLiteralText(spNumFormat, &ccf);
1921 while (fixed_count > 1) {
1925 if (!threshold.IsValid())
1928 bool bAdjusted =
false;
1930 fabs(decimal
.ToDouble()) < threshold.ValueOrDie()) {
1937 if (!threshold.IsValid())
1941 fabs(decimal
.ToDouble()) > threshold.ValueOrDie()) {
1948 bool bTrimTailZeros =
false;
1950 GetNumTrailingLimit(wsNumFormat, dot_index_f, &bTrimTailZeros);
1952 if (iTreading < scale) {
1956 if (bTrimTailZeros && scale > 0 && iTreading > 0) {
1957 wsSrcNum.TrimBack(L"0");
1958 wsSrcNum.TrimBack(L".");
1963 if (wsSrcNum[0] ==
'-') {
1965 wsSrcNum.Delete(0, 1);
1968 bool bAddNeg =
false;
1969 pdfium::span<
const wchar_t> spSrcNum = wsSrcNum.span();
1970 auto dot_index = wsSrcNum.Find(
'.');
1971 if (!dot_index.has_value())
1972 dot_index = spSrcNum.size();
1974 size_t cc = dot_index.value() - 1;
1975 for (size_t ccf = dot_index_f - 1; ccf < spNumFormat.size(); --ccf) {
1976 switch (spNumFormat[ccf]) {
1978 if (cc < spSrcNum.size()) {
1979 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
1981 wsOutput->InsertAtFront(spSrcNum[cc]);
1984 wsOutput->InsertAtFront(L'0');
1988 if (cc < spSrcNum.size()) {
1989 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
1991 if (spSrcNum[0] !=
'0')
1992 wsOutput->InsertAtFront(spSrcNum[cc]);
1997 if (cc < spSrcNum.size()) {
1998 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
2000 wsOutput->InsertAtFront(spSrcNum[0] ==
'0' ? L' ' : spSrcNum[cc]);
2003 wsOutput->InsertAtFront(L' ');
2011 wsOutput->InsertAtFront(L' ');
2027 if (ccf - 1 < spNumFormat.size() && spNumFormat[ccf - 1] ==
'c') {
2029 *wsOutput
= L"CR"
+ *wsOutput;
2033 wsOutput->InsertAtFront(
'r');
2037 if (ccf - 1 < spNumFormat.size() && spNumFormat[ccf - 1] ==
'C') {
2038 *wsOutput
= bNeg ? L"CR" : L" "
+ *wsOutput;
2042 wsOutput->InsertAtFront(
'R');
2046 if (ccf - 1 < spNumFormat.size() && spNumFormat[ccf - 1] ==
'd') {
2048 *wsOutput
= L"db"
+ *wsOutput;
2052 wsOutput->InsertAtFront(
'b');
2056 if (ccf - 1 < spNumFormat.size() && spNumFormat[ccf - 1] ==
'D') {
2057 *wsOutput
= bNeg ? L"DB" : L" "
+ *wsOutput;
2061 wsOutput->InsertAtFront(
'B');
2068 if (cc < spSrcNum.size())
2069 *wsOutput
= wsGroupSymbol
+ *wsOutput;
2072 wsOutput->InsertAtFront(bNeg ? L'(' : L' ');
2076 wsOutput->InsertAtFront(bNeg ? L')' : L' ');
2079 *wsOutput = GetLiteralTextReverse(spNumFormat, &ccf) + *wsOutput;
2082 wsOutput->InsertAtFront(spNumFormat[ccf]);
2087 if (cc < spSrcNum.size()) {
2088 size_t nPos = dot_index.value() % 3;
2090 for (size_t i = 0; i < dot_index.value(); i++) {
2091 if (i % 3 == nPos && i != 0)
2092 *wsOutput
+= wsGroupSymbol;
2093 *wsOutput += wsSrcNum[i];
2095 if (dot_index.value() < spSrcNum.size()) {
2097 *wsOutput += wsSrcNum.Last(spSrcNum.size() - dot_index.value() - 1);
2103 if (dot_index_f == wsNumFormat.GetLength()) {
2104 if (!bAddNeg && bNeg)
2110 if (spNumFormat[dot_index_f] ==
'V') {
2111 *wsOutput
+= wsDotSymbol;
2112 }
else if (spNumFormat[dot_index_f] ==
'.') {
2113 if (dot_index.value() < spSrcNum.size()) {
2114 *wsOutput
+= wsDotSymbol;
2115 }
else if (dot_index_f + 1 < spNumFormat.size() &&
2116 (spNumFormat[dot_index_f + 1] ==
'9' ||
2117 spNumFormat[dot_index_f + 1] ==
'Z')) {
2118 *wsOutput
+= wsDotSymbol;
2122 cc = dot_index.value() + 1;
2123 size_t ccf = dot_index_f + 1;
2124 while (ccf < spNumFormat.size()) {
2125 switch (spNumFormat[ccf]) {
2127 *wsOutput += GetLiteralText(spNumFormat, &ccf);
2130 if (cc < spSrcNum.size()) {
2131 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
2133 *wsOutput += spSrcNum[cc];
2140 if (cc < spSrcNum.size()) {
2141 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
2143 *wsOutput += spSrcNum[cc];
2148 if (cc < spSrcNum.size()) {
2149 if (!FXSYS_IsDecimalDigit(spSrcNum[cc]))
2151 *wsOutput += spSrcNum[cc];
2165 if (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'r') {
2173 if (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'R') {
2174 *wsOutput
+= bNeg ? L"CR" : L" ";
2180 if (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'b') {
2188 if (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'B') {
2189 *wsOutput
+= bNeg ? L"DB" : L" ";
2198 while (ccf + 1 < spNumFormat.size() && spNumFormat[ccf + 1] ==
'8')
2200 while (cc < spSrcNum.size() && FXSYS_IsDecimalDigit(spSrcNum[cc])) {
2201 *wsOutput += spSrcNum[cc];
2206 *wsOutput
+= wsGroupSymbol;
2209 *wsOutput
+= bNeg ?
'(' :
' ';
2213 *wsOutput
+= bNeg ?
')' :
' ';
2220 if (!bAddNeg && bNeg)
2230 if (wsSrcDateTime.IsEmpty() || m_spPattern.empty())
2237 GetDateTimeFormat(pLocaleMgr, &pLocale, &wsDatePattern, &wsTimePattern);
2243 wsTimePattern =
std::move(wsDatePattern);
2246 eCategory = eDateTimeType;
2252 auto iT = wsSrcDateTime.Find(L"T");
2253 if (!iT.has_value()) {
2254 if (eCategory == DateTimeType::kDate &&
2255 FX_DateFromCanonical(wsSrcDateTime.span(), &dt)) {
2256 *wsOutput
= FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern,
true,
2260 if (eCategory == DateTimeType::kTime &&
2261 FX_TimeFromCanonical(pLocale, wsSrcDateTime.span(), &dt)) {
2262 *wsOutput
= FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern,
true,
2267 pdfium::span<
const wchar_t> wsSrcDate =
2268 wsSrcDateTime.span().first(iT.value());
2269 pdfium::span<
const wchar_t> wsSrcTime =
2270 wsSrcDateTime.span().subspan(iT.value() + 1);
2271 if (wsSrcDate.empty() || wsSrcTime.empty())
2274 if (FX_DateFromCanonical(wsSrcDate, &dt) &&
2275 FX_TimeFromCanonical(pLocale, wsSrcTime, &dt)) {
2277 FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern,
2286 if (m_spPattern.empty())
2289 WideString wsTextFormat = GetTextFormat(L"zero");
2290 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
2291 size_t iPattern = 0;
2292 while (iPattern < spTextFormat.size()) {
2293 if (spTextFormat[iPattern] ==
'\'') {
2294 *wsOutput += GetLiteralText(spTextFormat, &iPattern);
2297 *wsOutput += spTextFormat[iPattern++];
2303 if (m_spPattern.empty())
2306 WideString wsTextFormat = GetTextFormat(L"null");
2307 pdfium::span<
const wchar_t> spTextFormat = wsTextFormat.span();
2308 size_t iPattern = 0;
2309 while (iPattern < spTextFormat.size()) {
2310 if (spTextFormat[iPattern] ==
'\'') {
2311 *wsOutput += GetLiteralText(spTextFormat, &iPattern);
2314 *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)
bool EqualsASCIINoCase(ByteStringView that) 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)
pdfium::CheckedNumeric< uint32_t > FX_SAFE_UINT32
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)
#define NOTREACHED_NORETURN()
fxcrt::WideStringView WideStringView
fxcrt::WideString WideString