summaryrefslogtreecommitdiff
path: root/xfa/src/fgas/localization
diff options
context:
space:
mode:
authorDan Sinclair <dsinclair@chromium.org>2016-03-09 13:49:00 -0500
committerDan Sinclair <dsinclair@chromium.org>2016-03-09 13:49:00 -0500
commit9332e0c2fced598a632e3bbe905b6f63b1f5b06b (patch)
treea8957a09cb34ecd28afcd6ebbed309d9c60e4644 /xfa/src/fgas/localization
parent8388037a5c58d60043b11c03a8efe78c54c65a4b (diff)
downloadpdfium-9332e0c2fced598a632e3bbe905b6f63b1f5b06b.tar.xz
Cleanup the xfa/src/fgas directory.
This CL moves the code from xfa/src/fgas/src up one level. It then takes the headers in xfa/src/fgas/include and moves them to their correct folder. The src/ and include/ directories are then removed. In some cases, when moving from include/ there was another header with the same name. Those headers were either folded together, or the content of the conflicting folder moved to an anonymous namespace in the cpp file as they were not used anywhere else. Files with duplicate names as core/src/crt were renamed to be fgas_ instead of fx_. (e.g. fgas_system.h, fgas_memory.h, fgas_stream.h) R=tsepez@chromium.org Review URL: https://codereview.chromium.org/1776303002 .
Diffstat (limited to 'xfa/src/fgas/localization')
-rw-r--r--xfa/src/fgas/localization/fgas_datetime.cpp550
-rw-r--r--xfa/src/fgas/localization/fgas_datetime.h406
-rw-r--r--xfa/src/fgas/localization/fgas_locale.cpp5030
-rw-r--r--xfa/src/fgas/localization/fgas_locale.h206
-rw-r--r--xfa/src/fgas/localization/fgas_localeimp.h122
-rw-r--r--xfa/src/fgas/localization/fgas_localemgr.cpp97
-rw-r--r--xfa/src/fgas/localization/fgas_localemgr.h28
7 files changed, 6439 insertions, 0 deletions
diff --git a/xfa/src/fgas/localization/fgas_datetime.cpp b/xfa/src/fgas/localization/fgas_datetime.cpp
new file mode 100644
index 0000000000..e803b490d6
--- /dev/null
+++ b/xfa/src/fgas/localization/fgas_datetime.cpp
@@ -0,0 +1,550 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/include/fxcrt/fx_system.h"
+#include "xfa/src/fgas/localization/fgas_datetime.h"
+
+#if _FX_OS_ == _FX_LINUX_DESKTOP_ || _FX_OS_ == _FX_ANDROID_ || \
+ _FX_OS_ == _FX_MACOSX_ || _FX_OS_ == _FX_IOS_
+#include <sys/time.h>
+#include <time.h>
+#endif
+
+const uint8_t g_FXDaysPerMonth[12] = {31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31};
+const uint8_t g_FXDaysPerLeapMonth[12] = {31, 29, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31};
+const int32_t g_FXDaysBeforeMonth[12] = {0, 31, 59, 90, 120, 151,
+ 181, 212, 243, 273, 304, 334};
+const int32_t g_FXDaysBeforeLeapMonth[12] = {0, 31, 60, 91, 121, 152,
+ 182, 213, 244, 274, 305, 335};
+const int32_t g_FXDaysPerYear = 365;
+const int32_t g_FXDaysPerLeapYear = 366;
+const int32_t g_FXDaysPer4Years = 1461;
+const int32_t g_FXDaysPer100Years = 36524;
+const int32_t g_FXDaysPer400Years = 146097;
+const int64_t g_FXMillisecondsPerSecond = 1000;
+const int64_t g_FXMillisecondsPerMinute = 60000;
+const int64_t g_FXMillisecondsPerHour = 3600000;
+const int64_t g_FXMillisecondsPerDay = 86400000;
+FX_BOOL FX_IsLeapYear(int32_t iYear) {
+ FXSYS_assert(iYear != 0);
+ return ((iYear % 4) == 0 && (iYear % 100) != 0) || (iYear % 400) == 0;
+}
+int32_t FX_DaysInYear(int32_t iYear) {
+ FXSYS_assert(iYear != 0);
+ return FX_IsLeapYear(iYear) ? g_FXDaysPerLeapYear : g_FXDaysPerYear;
+}
+uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth) {
+ FXSYS_assert(iYear != 0);
+ FXSYS_assert(iMonth >= 1 && iMonth <= 12);
+ const uint8_t* p =
+ FX_IsLeapYear(iYear) ? g_FXDaysPerLeapMonth : g_FXDaysPerMonth;
+ return p[iMonth - 1];
+}
+static int32_t FX_DaysBeforeMonthInYear(int32_t iYear, uint8_t iMonth) {
+ FXSYS_assert(iYear != 0);
+ FXSYS_assert(iMonth >= 1 && iMonth <= 12);
+ const int32_t* p =
+ FX_IsLeapYear(iYear) ? g_FXDaysBeforeLeapMonth : g_FXDaysBeforeMonth;
+ return p[iMonth - 1];
+}
+static int64_t FX_DateToDays(int32_t iYear,
+ uint8_t iMonth,
+ uint8_t iDay,
+ FX_BOOL bIncludeThisDay = FALSE) {
+ FXSYS_assert(iYear != 0);
+ FXSYS_assert(iMonth >= 1 && iMonth <= 12);
+ FXSYS_assert(iDay >= 1 && iDay <= FX_DaysInMonth(iYear, iMonth));
+ int64_t iDays = FX_DaysBeforeMonthInYear(iYear, iMonth);
+ iDays += iDay;
+ if (!bIncludeThisDay) {
+ iDays--;
+ }
+ if (iYear > 0) {
+ iYear--;
+ } else {
+ iDays -= FX_DaysInYear(iYear);
+ iYear++;
+ }
+ return iDays + (int64_t)iYear * 365 + iYear / 4 - iYear / 100 + iYear / 400;
+}
+static void FX_DaysToDate(int64_t iDays,
+ int32_t& iYear,
+ uint8_t& iMonth,
+ uint8_t& iDay) {
+ FX_BOOL bBC = iDays < 0;
+ if (bBC) {
+ iDays = -iDays;
+ }
+ iYear = 1;
+ iMonth = 1;
+ iDay = 1;
+ if (iDays >= g_FXDaysPer400Years) {
+ iYear += (int32_t)(iDays / g_FXDaysPer400Years * 400);
+ iDays %= g_FXDaysPer400Years;
+ }
+ if (iDays >= g_FXDaysPer100Years) {
+ if (iDays == g_FXDaysPer100Years * 4) {
+ iYear += 300;
+ iDays -= g_FXDaysPer100Years * 3;
+ } else {
+ iYear += (int32_t)(iDays / g_FXDaysPer100Years * 100);
+ iDays %= g_FXDaysPer100Years;
+ }
+ }
+ if (iDays >= g_FXDaysPer4Years) {
+ iYear += (int32_t)(iDays / g_FXDaysPer4Years * 4);
+ iDays %= g_FXDaysPer4Years;
+ }
+ while (TRUE) {
+ int32_t iYearDays = FX_DaysInYear(iYear);
+ if (iDays < iYearDays) {
+ if (bBC) {
+ iYear = -iYear;
+ iDays = iYearDays - iDays;
+ }
+ break;
+ }
+ iYear++;
+ iDays -= iYearDays;
+ }
+ while (TRUE) {
+ int32_t iMonthDays = FX_DaysInMonth(iYear, iMonth);
+ if (iDays < iMonthDays) {
+ break;
+ }
+ iMonth++;
+ iDays -= iMonthDays;
+ }
+ iDay += (uint8_t)iDays;
+}
+
+struct FXUT_SYSTEMTIME {
+ FX_WORD wYear;
+ FX_WORD wMonth;
+ FX_WORD wDayOfWeek;
+ FX_WORD wDay;
+ FX_WORD wHour;
+ FX_WORD wMinute;
+ FX_WORD wSecond;
+ FX_WORD wMilliseconds;
+};
+
+void CFX_Unitime::Now() {
+ FXUT_SYSTEMTIME utLocal;
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \
+ _FX_OS_ == _FX_WIN64_
+ ::GetLocalTime((LPSYSTEMTIME)&utLocal);
+#elif _FX_OS_ != _FX_EMBEDDED_
+#if 1
+ timeval curTime;
+ gettimeofday(&curTime, NULL);
+#else
+ struct timespec curTime;
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &curTime);
+#endif
+ struct tm st;
+ localtime_r(&curTime.tv_sec, &st);
+ utLocal.wYear = st.tm_year + 1900;
+ utLocal.wMonth = st.tm_mon + 1;
+ utLocal.wDayOfWeek = st.tm_wday;
+ utLocal.wDay = st.tm_mday;
+ utLocal.wHour = st.tm_hour;
+ utLocal.wMinute = st.tm_min;
+ utLocal.wSecond = st.tm_sec;
+ utLocal.wMilliseconds = curTime.tv_usec / 1000;
+#endif
+ Set(utLocal.wYear, (uint8_t)utLocal.wMonth, (uint8_t)utLocal.wDay,
+ (uint8_t)utLocal.wHour, (uint8_t)utLocal.wMinute,
+ (uint8_t)utLocal.wSecond, (FX_WORD)utLocal.wMilliseconds);
+}
+void CFX_Unitime::SetGMTime() {
+ FXUT_SYSTEMTIME utLocal;
+#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \
+ _FX_OS_ == _FX_WIN64_
+ ::GetSystemTime((LPSYSTEMTIME)&utLocal);
+#elif _FX_OS_ != _FX_EMBEDDED_
+#if 1
+ timeval curTime;
+ gettimeofday(&curTime, NULL);
+#else
+ struct timespec curTime;
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &curTime);
+#endif
+ struct tm st;
+ gmtime_r(&curTime.tv_sec, &st);
+ utLocal.wYear = st.tm_year + 1900;
+ utLocal.wMonth = st.tm_mon + 1;
+ utLocal.wDayOfWeek = st.tm_wday;
+ utLocal.wDay = st.tm_mday;
+ utLocal.wHour = st.tm_hour;
+ utLocal.wMinute = st.tm_min;
+ utLocal.wSecond = st.tm_sec;
+ utLocal.wMilliseconds = curTime.tv_usec / 1000;
+#endif
+ Set(utLocal.wYear, (uint8_t)utLocal.wMonth, (uint8_t)utLocal.wDay,
+ (uint8_t)utLocal.wHour, (uint8_t)utLocal.wMinute,
+ (uint8_t)utLocal.wSecond, (FX_WORD)utLocal.wMilliseconds);
+}
+void CFX_Unitime::Set(int32_t year,
+ uint8_t month,
+ uint8_t day,
+ uint8_t hour,
+ uint8_t minute,
+ uint8_t second,
+ FX_WORD millisecond) {
+ FXSYS_assert(hour <= 23);
+ FXSYS_assert(minute <= 59);
+ FXSYS_assert(second <= 59);
+ FXSYS_assert(millisecond <= 999);
+ m_iUnitime = (int64_t)hour * g_FXMillisecondsPerHour +
+ (int64_t)minute * g_FXMillisecondsPerMinute +
+ (int64_t)second * g_FXMillisecondsPerSecond + millisecond;
+ if (year > 0) {
+ m_iUnitime =
+ m_iUnitime +
+ FX_DateToDays(year, month, day, FALSE) * g_FXMillisecondsPerDay;
+ }
+}
+void CFX_Unitime::Set(FX_UNITIME t) {
+ m_iUnitime = t;
+}
+int32_t CFX_Unitime::GetYear() const {
+ int32_t iYear;
+ uint8_t iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ return iYear;
+}
+uint8_t CFX_Unitime::GetMonth() const {
+ int32_t iYear;
+ uint8_t iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ return iMonth;
+}
+uint8_t CFX_Unitime::GetDay() const {
+ int32_t iYear;
+ uint8_t iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ return iDay;
+}
+FX_WEEKDAY CFX_Unitime::GetDayOfWeek() const {
+ int32_t v = (int32_t)((m_iUnitime / g_FXMillisecondsPerDay + 1) % 7);
+ if (v < 0) {
+ v += 7;
+ }
+ return (FX_WEEKDAY)v;
+}
+FX_WORD CFX_Unitime::GetDayOfYear() const {
+ int32_t iYear;
+ uint8_t iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ return FX_DaysBeforeMonthInYear(iYear, iMonth) + iDay;
+}
+int64_t CFX_Unitime::GetDayOfAD() const {
+ FX_BOOL bBC = m_iUnitime < 0;
+ int64_t iDays = m_iUnitime / g_FXMillisecondsPerDay;
+ iDays += bBC ? -1 : 0;
+ if (bBC && (m_iUnitime % g_FXMillisecondsPerDay) == 0) {
+ iDays++;
+ }
+ return iDays;
+}
+uint8_t CFX_Unitime::GetHour() const {
+ int32_t v = (int32_t)(m_iUnitime % g_FXMillisecondsPerDay);
+ if (v < 0) {
+ v += g_FXMillisecondsPerDay;
+ }
+ return (uint8_t)(v / g_FXMillisecondsPerHour);
+}
+uint8_t CFX_Unitime::GetMinute() const {
+ int32_t v = (int32_t)(m_iUnitime % g_FXMillisecondsPerHour);
+ if (v < 0) {
+ v += g_FXMillisecondsPerHour;
+ }
+ return (uint8_t)(v / g_FXMillisecondsPerMinute);
+}
+uint8_t CFX_Unitime::GetSecond() const {
+ int32_t v = (int32_t)(m_iUnitime % g_FXMillisecondsPerMinute);
+ if (v < 0) {
+ v += g_FXMillisecondsPerMinute;
+ }
+ return (uint8_t)(v / g_FXMillisecondsPerSecond);
+}
+FX_WORD CFX_Unitime::GetMillisecond() const {
+ int32_t v = (int32_t)(m_iUnitime % g_FXMillisecondsPerSecond);
+ if (v < 0) {
+ v += g_FXMillisecondsPerSecond;
+ }
+ return (FX_WORD)v;
+}
+FX_BOOL CFX_Unitime::AddYears(int32_t iYears) {
+ FX_UNITIME ut = m_iUnitime;
+ if (ut < 0) {
+ ut = -ut;
+ }
+ FX_UNITIME r = ut % g_FXMillisecondsPerDay;
+ int32_t iYear;
+ uint8_t iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ iYear += iYears;
+ if (iYear == 0) {
+ iYear = iYears > 0 ? 1 : -1;
+ }
+ m_iUnitime =
+ FX_DateToDays(iYear, iMonth, iDay, FALSE) * g_FXMillisecondsPerDay;
+ m_iUnitime += (iYear < 0) ? -r : r;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddMonths(int32_t iMonths) {
+ FX_BOOL b = iMonths > 0;
+ FX_UNITIME ut = m_iUnitime;
+ if (ut < 0) {
+ ut = -ut;
+ }
+ FX_UNITIME r = ut % g_FXMillisecondsPerDay;
+ int32_t iYear;
+ uint8_t iMonth, iDay;
+ FX_DaysToDate(GetDayOfAD(), iYear, iMonth, iDay);
+ iMonths += iMonth;
+ while (iMonths < 1) {
+ iYear--, iMonths += 12;
+ }
+ while (iMonths > 12) {
+ iYear++, iMonths -= 12;
+ }
+ if (iYear == 0) {
+ iYear = b ? 1 : -1;
+ }
+ m_iUnitime = FX_DateToDays(iYear, (uint8_t)iMonths, iDay, FALSE) *
+ g_FXMillisecondsPerDay;
+ m_iUnitime += (iYear < 0) ? -r : r;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddDays(int32_t iDays) {
+ m_iUnitime += (int64_t)iDays * g_FXMillisecondsPerDay;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddHours(int32_t iHours) {
+ m_iUnitime += (int64_t)iHours * g_FXMillisecondsPerHour;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddMinutes(int32_t iMinutes) {
+ m_iUnitime += (int64_t)iMinutes * g_FXMillisecondsPerMinute;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddSeconds(int32_t iSeconds) {
+ m_iUnitime += ((int64_t)iSeconds) * g_FXMillisecondsPerSecond;
+ return TRUE;
+}
+FX_BOOL CFX_Unitime::AddMilliseconds(int32_t iMilliseconds) {
+ m_iUnitime += iMilliseconds;
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::Set(int32_t year,
+ uint8_t month,
+ uint8_t day,
+ uint8_t hour,
+ uint8_t minute,
+ uint8_t second,
+ FX_WORD millisecond) {
+ ASSERT(year != 0);
+ ASSERT(month >= 1 && month <= 12);
+ ASSERT(day >= 1 && day <= FX_DaysInMonth(year, month));
+ ASSERT(hour <= 23);
+ ASSERT(minute <= 59);
+ ASSERT(second <= 59);
+ ASSERT(millisecond <= 999);
+ m_DateTime.Date.sDate.year = year;
+ m_DateTime.Date.sDate.month = month;
+ m_DateTime.Date.sDate.day = day;
+ m_DateTime.Time.sTime.hour = hour;
+ m_DateTime.Time.sTime.minute = minute;
+ m_DateTime.Time.sTime.second = second;
+ m_DateTime.Time.sTime.millisecond = millisecond;
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::FromUnitime(FX_UNITIME t) {
+ CFX_Unitime ut(t);
+ FX_DaysToDate(ut.GetDayOfAD(), m_DateTime.Date.sDate.year,
+ m_DateTime.Date.sDate.month, m_DateTime.Date.sDate.day);
+ m_DateTime.Date.sDate.day = ut.GetHour();
+ m_DateTime.Time.sTime.minute = ut.GetMinute();
+ m_DateTime.Time.sTime.second = ut.GetSecond();
+ m_DateTime.Time.sTime.millisecond = ut.GetMillisecond();
+ return TRUE;
+}
+FX_UNITIME CFX_DateTime::ToUnitime() const {
+ FX_UNITIME v =
+ (int64_t)m_DateTime.Date.sDate.day * g_FXMillisecondsPerHour +
+ (int64_t)m_DateTime.Time.sTime.minute * g_FXMillisecondsPerMinute +
+ (int64_t)m_DateTime.Time.sTime.second * g_FXMillisecondsPerSecond +
+ m_DateTime.Time.sTime.millisecond;
+ v += FX_DateToDays(m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month,
+ m_DateTime.Date.sDate.day, FALSE) *
+ g_FXMillisecondsPerDay;
+ return v;
+}
+int32_t CFX_DateTime::GetYear() const {
+ return m_DateTime.Date.sDate.year;
+}
+uint8_t CFX_DateTime::GetMonth() const {
+ return m_DateTime.Date.sDate.month;
+}
+uint8_t CFX_DateTime::GetDay() const {
+ return m_DateTime.Date.sDate.day;
+}
+FX_WEEKDAY CFX_DateTime::GetDayOfWeek() const {
+ int32_t v = (int32_t)(FX_DateToDays(m_DateTime.Date.sDate.year,
+ m_DateTime.Date.sDate.month,
+ m_DateTime.Date.sDate.day, TRUE) %
+ 7);
+ if (v < 0) {
+ v += 7;
+ }
+ return (FX_WEEKDAY)v;
+}
+FX_WORD CFX_DateTime::GetDayOfYear() const {
+ return FX_DaysBeforeMonthInYear(m_DateTime.Date.sDate.year,
+ m_DateTime.Date.sDate.month) +
+ m_DateTime.Date.sDate.day;
+}
+int64_t CFX_DateTime::GetDayOfAD() const {
+ return FX_DateToDays(m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month,
+ m_DateTime.Date.sDate.day, TRUE);
+}
+uint8_t CFX_DateTime::GetHour() const {
+ return m_DateTime.Date.sDate.day;
+}
+uint8_t CFX_DateTime::GetMinute() const {
+ return m_DateTime.Time.sTime.minute;
+}
+uint8_t CFX_DateTime::GetSecond() const {
+ return m_DateTime.Time.sTime.second;
+}
+FX_WORD CFX_DateTime::GetMillisecond() const {
+ return m_DateTime.Time.sTime.millisecond;
+}
+FX_BOOL CFX_DateTime::AddYears(int32_t iYears) {
+ if (iYears == 0) {
+ return FALSE;
+ }
+ int32_t v = m_DateTime.Date.sDate.year + iYears;
+ if (v >= 0 && m_DateTime.Date.sDate.year < 0) {
+ v++;
+ } else if (v <= 0 && m_DateTime.Date.sDate.year > 0) {
+ v--;
+ }
+ m_DateTime.Date.sDate.year = v;
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddMonths(int32_t iMonths) {
+ if (iMonths == 0) {
+ return FALSE;
+ }
+ FX_BOOL b = iMonths > 0;
+ iMonths += m_DateTime.Date.sDate.month;
+ while (iMonths < 1) {
+ m_DateTime.Date.sDate.year--;
+ if (m_DateTime.Date.sDate.year == 0) {
+ m_DateTime.Date.sDate.year = -1;
+ }
+ iMonths += 12;
+ }
+ while (iMonths > 12) {
+ m_DateTime.Date.sDate.year++;
+ if (m_DateTime.Date.sDate.year == 0) {
+ m_DateTime.Date.sDate.year = 1;
+ }
+ iMonths -= 12;
+ }
+ if (m_DateTime.Date.sDate.year == 0) {
+ m_DateTime.Date.sDate.year = b ? 1 : -1;
+ }
+ m_DateTime.Date.sDate.month = (uint8_t)iMonths;
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddDays(int32_t iDays) {
+ if (iDays == 0) {
+ return FALSE;
+ }
+ int64_t v1 =
+ FX_DateToDays(m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month,
+ m_DateTime.Date.sDate.day, TRUE);
+ int64_t v2 = v1 + iDays;
+ if (v2 <= 0 && v1 > 0) {
+ v2--;
+ } else if (v2 >= 0 && v1 < 0) {
+ v2++;
+ }
+ FX_DaysToDate(v2, m_DateTime.Date.sDate.year, m_DateTime.Date.sDate.month,
+ m_DateTime.Date.sDate.day);
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddHours(int32_t iHours) {
+ if (iHours == 0) {
+ return FALSE;
+ }
+ iHours += m_DateTime.Date.sDate.day;
+ int32_t iDays = iHours / 24;
+ iHours %= 24;
+ if (iHours < 0) {
+ iDays--, iHours += 24;
+ }
+ m_DateTime.Date.sDate.day = (uint8_t)iHours;
+ if (iDays != 0) {
+ AddDays(iDays);
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddMinutes(int32_t iMinutes) {
+ if (iMinutes == 0) {
+ return FALSE;
+ }
+ iMinutes += m_DateTime.Time.sTime.minute;
+ int32_t iHours = iMinutes / 60;
+ iMinutes %= 60;
+ if (iMinutes < 0) {
+ iHours--, iMinutes += 60;
+ }
+ m_DateTime.Time.sTime.minute = (uint8_t)iMinutes;
+ if (iHours != 0) {
+ AddHours(iHours);
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddSeconds(int32_t iSeconds) {
+ if (iSeconds == 0) {
+ return FALSE;
+ }
+ iSeconds += m_DateTime.Time.sTime.second;
+ int32_t iMinutes = iSeconds / 60;
+ iSeconds %= 60;
+ if (iSeconds < 0) {
+ iMinutes--, iSeconds += 60;
+ }
+ m_DateTime.Time.sTime.second = (uint8_t)iSeconds;
+ if (iMinutes != 0) {
+ AddMinutes(iMinutes);
+ }
+ return TRUE;
+}
+FX_BOOL CFX_DateTime::AddMilliseconds(int32_t iMilliseconds) {
+ if (iMilliseconds == 0) {
+ return FALSE;
+ }
+ iMilliseconds += m_DateTime.Time.sTime.millisecond;
+ int32_t iSeconds = (int32_t)(iMilliseconds / g_FXMillisecondsPerSecond);
+ iMilliseconds %= g_FXMillisecondsPerSecond;
+ if (iMilliseconds < 0) {
+ iSeconds--, iMilliseconds += g_FXMillisecondsPerSecond;
+ }
+ m_DateTime.Time.sTime.millisecond = (FX_WORD)iMilliseconds;
+ if (iSeconds != 0) {
+ AddSeconds(iSeconds);
+ }
+ return TRUE;
+}
diff --git a/xfa/src/fgas/localization/fgas_datetime.h b/xfa/src/fgas/localization/fgas_datetime.h
new file mode 100644
index 0000000000..5dd70ccc65
--- /dev/null
+++ b/xfa/src/fgas/localization/fgas_datetime.h
@@ -0,0 +1,406 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_LOCALIZATION_FGAS_DATETIME_H_
+#define XFA_SRC_FGAS_LOCALIZATION_FGAS_DATETIME_H_
+
+#include "core/include/fxcrt/fx_system.h"
+
+class CFX_Unitime;
+class CFX_DateTime;
+
+typedef int64_t FX_UNITIME;
+enum FX_WEEKDAY {
+ FX_Sunday = 0,
+ FX_Monday,
+ FX_Tuesday,
+ FX_Wednesday,
+ FX_Thursday,
+ FX_Friday,
+ FX_Saturday,
+};
+
+FX_BOOL FX_IsLeapYear(int32_t iYear);
+int32_t FX_DaysInYear(int32_t iYear);
+uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth);
+
+class CFX_Unitime {
+ public:
+ CFX_Unitime() { m_iUnitime = 0; }
+ CFX_Unitime(FX_UNITIME iUnitime) { m_iUnitime = iUnitime; }
+ CFX_Unitime(const CFX_Unitime& unitime) { m_iUnitime = unitime.m_iUnitime; }
+ operator FX_UNITIME*() { return &m_iUnitime; }
+ operator FX_UNITIME const*() const { return &m_iUnitime; }
+ operator FX_UNITIME&() { return m_iUnitime; }
+ operator const FX_UNITIME&() const { return m_iUnitime; }
+ CFX_Unitime& operator=(const CFX_Unitime& t) {
+ m_iUnitime = t.m_iUnitime;
+ return *this;
+ }
+ CFX_Unitime& operator=(FX_UNITIME t) {
+ m_iUnitime = t;
+ return *this;
+ }
+ CFX_Unitime& operator+=(const CFX_Unitime& t) {
+ m_iUnitime += t.m_iUnitime;
+ return *this;
+ }
+ CFX_Unitime& operator+=(FX_UNITIME t) {
+ m_iUnitime += t;
+ return *this;
+ }
+ CFX_Unitime& operator-=(const CFX_Unitime& t) {
+ m_iUnitime -= t.m_iUnitime;
+ return *this;
+ }
+ CFX_Unitime& operator-=(FX_UNITIME t) {
+ m_iUnitime -= t;
+ return *this;
+ }
+ void Now();
+ void SetGMTime();
+ void Set(int32_t year,
+ uint8_t month,
+ uint8_t day,
+ uint8_t hour = 0,
+ uint8_t minute = 0,
+ uint8_t second = 0,
+ FX_WORD millisecond = 0);
+ void Set(FX_UNITIME t);
+ int32_t GetYear() const;
+ uint8_t GetMonth() const;
+ uint8_t GetDay() const;
+ FX_WEEKDAY GetDayOfWeek() const;
+ FX_WORD GetDayOfYear() const;
+ int64_t GetDayOfAD() const;
+ uint8_t GetHour() const;
+ uint8_t GetMinute() const;
+ uint8_t GetSecond() const;
+ FX_WORD GetMillisecond() const;
+ FX_BOOL AddYears(int32_t iYears);
+ FX_BOOL AddMonths(int32_t iMonths);
+ FX_BOOL AddDays(int32_t iDays);
+ FX_BOOL AddHours(int32_t iHours);
+ FX_BOOL AddMinutes(int32_t iMinutes);
+ FX_BOOL AddSeconds(int32_t iSeconds);
+ FX_BOOL AddMilliseconds(int32_t iMilliseconds);
+ friend CFX_Unitime operator+(const CFX_Unitime& t1, const CFX_Unitime& t2) {
+ return CFX_Unitime(t1.m_iUnitime + t2.m_iUnitime);
+ }
+ friend CFX_Unitime operator+(const CFX_Unitime& t1, FX_UNITIME t2) {
+ return CFX_Unitime(t1.m_iUnitime + t2);
+ }
+ friend CFX_Unitime operator+(FX_UNITIME t1, const CFX_Unitime& t2) {
+ return CFX_Unitime(t1 + t2.m_iUnitime);
+ }
+ friend CFX_Unitime operator-(const CFX_Unitime& t1, const CFX_Unitime& t2) {
+ return CFX_Unitime(t1.m_iUnitime + t2.m_iUnitime);
+ }
+ friend CFX_Unitime operator-(const CFX_Unitime& t1, FX_UNITIME t2) {
+ return CFX_Unitime(t1.m_iUnitime + t2);
+ }
+ friend CFX_Unitime operator-(FX_UNITIME t1, const CFX_Unitime& t2) {
+ return CFX_Unitime(t1 + t2.m_iUnitime);
+ }
+ friend bool operator==(const CFX_Unitime& t1, const CFX_Unitime& t2) {
+ return t1.m_iUnitime == t2.m_iUnitime;
+ }
+ friend bool operator==(const CFX_Unitime& t1, FX_UNITIME t2) {
+ return t1.m_iUnitime == t2;
+ }
+ friend bool operator==(FX_UNITIME t1, const CFX_Unitime& t2) {
+ return t1 == t2.m_iUnitime;
+ }
+ friend bool operator!=(const CFX_Unitime& t1, const CFX_Unitime& t2) {
+ return t1.m_iUnitime != t2.m_iUnitime;
+ }
+ friend bool operator!=(const CFX_Unitime& t1, FX_UNITIME t2) {
+ return t1.m_iUnitime != t2;
+ }
+ friend bool operator!=(FX_UNITIME t1, const CFX_Unitime& t2) {
+ return t1 != t2.m_iUnitime;
+ }
+ friend bool operator>(const CFX_Unitime& t1, const CFX_Unitime& t2) {
+ return t1.m_iUnitime > t2.m_iUnitime;
+ }
+ friend bool operator>(const CFX_Unitime& t1, FX_UNITIME t2) {
+ return t1.m_iUnitime > t2;
+ }
+ friend bool operator>(FX_UNITIME t1, const CFX_Unitime& t2) {
+ return t1 > t2.m_iUnitime;
+ }
+ friend bool operator>=(const CFX_Unitime& t1, const CFX_Unitime& t2) {
+ return t1.m_iUnitime >= t2.m_iUnitime;
+ }
+ friend bool operator>=(const CFX_Unitime& t1, FX_UNITIME t2) {
+ return t1.m_iUnitime >= t2;
+ }
+ friend bool operator>=(FX_UNITIME t1, const CFX_Unitime& t2) {
+ return t1 >= t2.m_iUnitime;
+ }
+ friend bool operator<(const CFX_Unitime& t1, const CFX_Unitime& t2) {
+ return t1.m_iUnitime < t2.m_iUnitime;
+ }
+ friend bool operator<(const CFX_Unitime& t1, FX_UNITIME t2) {
+ return t1.m_iUnitime < t2;
+ }
+ friend bool operator<(FX_UNITIME t1, const CFX_Unitime& t2) {
+ return t1 < t2.m_iUnitime;
+ }
+ friend bool operator<=(const CFX_Unitime& t1, const CFX_Unitime& t2) {
+ return t1.m_iUnitime <= t2.m_iUnitime;
+ }
+ friend bool operator<=(const CFX_Unitime& t1, FX_UNITIME t2) {
+ return t1.m_iUnitime <= t2;
+ }
+ friend bool operator<=(FX_UNITIME t1, const CFX_Unitime& t2) {
+ return t1 <= t2.m_iUnitime;
+ }
+
+ private:
+ FX_UNITIME m_iUnitime;
+};
+
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(push, 1)
+#endif
+struct FX_DATE {
+ int32_t year;
+ uint8_t month;
+ uint8_t day;
+};
+
+struct FX_TIME {
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ FX_WORD millisecond;
+};
+
+struct FX_TIMEZONE {
+ int8_t tzHour;
+ uint8_t tzMinute;
+};
+
+struct FX_DATETIME {
+ union {
+ struct {
+ int32_t year;
+ uint8_t month;
+ uint8_t day;
+ } sDate;
+ FX_DATE aDate;
+ } Date;
+ union {
+ struct {
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ FX_WORD millisecond;
+ } sTime;
+ FX_TIME aTime;
+ } Time;
+};
+
+struct FX_DATETIMEZONE {
+ union {
+ struct {
+ union {
+ struct {
+ int32_t year;
+ uint8_t month;
+ uint8_t day;
+ };
+ FX_DATE date;
+ };
+ union {
+ struct {
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ FX_WORD millisecond;
+ };
+ FX_TIME time;
+ };
+ };
+ FX_DATETIME dt;
+ };
+ union {
+ struct {
+ int8_t tzHour;
+ uint8_t tzMinute;
+ };
+ FX_TIMEZONE tz;
+ };
+};
+#if _FX_OS_ != _FX_ANDROID_
+#pragma pack(pop)
+#endif
+
+class CFX_DateTime {
+ public:
+ CFX_DateTime() {}
+ CFX_DateTime(const FX_DATETIME& dt) { m_DateTime = dt; }
+ CFX_DateTime(const CFX_DateTime& dt) { m_DateTime = dt.m_DateTime; }
+ virtual ~CFX_DateTime() {}
+ operator FX_DATETIME*() { return &m_DateTime; }
+ operator const FX_DATETIME*() const { return &m_DateTime; }
+ operator FX_DATETIME&() { return m_DateTime; }
+ operator const FX_DATETIME&() const { return m_DateTime; }
+ CFX_DateTime& operator=(const CFX_DateTime& dt) {
+ m_DateTime = dt.m_DateTime;
+ return *this;
+ }
+ CFX_DateTime& operator=(const FX_DATETIME& dt) {
+ m_DateTime = dt;
+ return *this;
+ }
+ CFX_DateTime& operator+=(const CFX_DateTime& dt) {
+ FromUnitime(ToUnitime() + dt.ToUnitime());
+ return *this;
+ }
+ CFX_DateTime& operator+=(const FX_DATETIME& dt) {
+ FromUnitime(ToUnitime() + ((const CFX_DateTime&)dt).ToUnitime());
+ return *this;
+ }
+ CFX_DateTime& operator-=(const CFX_DateTime& dt) {
+ FromUnitime(ToUnitime() - dt.ToUnitime());
+ return *this;
+ }
+ CFX_DateTime& operator-=(const FX_DATETIME& dt) {
+ FromUnitime(ToUnitime() - ((const CFX_DateTime&)dt).ToUnitime());
+ return *this;
+ }
+ virtual FX_BOOL Set(int32_t year,
+ uint8_t month,
+ uint8_t day,
+ uint8_t hour = 0,
+ uint8_t minute = 0,
+ uint8_t second = 0,
+ FX_WORD millisecond = 0);
+ virtual FX_BOOL FromUnitime(FX_UNITIME t);
+ virtual FX_UNITIME ToUnitime() const;
+ virtual int32_t GetYear() const;
+ virtual uint8_t GetMonth() const;
+ virtual uint8_t GetDay() const;
+ virtual FX_WEEKDAY GetDayOfWeek() const;
+ virtual FX_WORD GetDayOfYear() const;
+ virtual int64_t GetDayOfAD() const;
+ virtual uint8_t GetHour() const;
+ virtual uint8_t GetMinute() const;
+ virtual uint8_t GetSecond() const;
+ virtual FX_WORD GetMillisecond() const;
+ virtual FX_BOOL AddYears(int32_t iYears);
+ virtual FX_BOOL AddMonths(int32_t iMonths);
+ virtual FX_BOOL AddDays(int32_t iDays);
+ virtual FX_BOOL AddHours(int32_t iHours);
+ virtual FX_BOOL AddMinutes(int32_t iMinutes);
+ virtual FX_BOOL AddSeconds(int32_t iSeconds);
+ virtual FX_BOOL AddMilliseconds(int32_t iMilliseconds);
+ friend CFX_DateTime operator+(const CFX_DateTime& dt1,
+ const CFX_DateTime& dt2) {
+ CFX_DateTime dt;
+ dt.FromUnitime(dt1.ToUnitime() + dt2.ToUnitime());
+ return dt;
+ }
+ friend CFX_DateTime operator+(const CFX_DateTime& dt1,
+ const FX_DATETIME& dt2) {
+ CFX_DateTime dt;
+ dt.FromUnitime(dt1.ToUnitime() + ((const CFX_DateTime&)dt2).ToUnitime());
+ return dt;
+ }
+ friend CFX_DateTime operator+(const FX_DATETIME& dt1,
+ const CFX_DateTime& dt2) {
+ CFX_DateTime dt;
+ dt.FromUnitime(((const CFX_DateTime&)dt1).ToUnitime() + dt2.ToUnitime());
+ return dt;
+ }
+ friend CFX_DateTime operator-(const CFX_DateTime& dt1,
+ const CFX_DateTime& dt2) {
+ CFX_DateTime dt;
+ dt.FromUnitime(dt1.ToUnitime() - dt2.ToUnitime());
+ return dt;
+ }
+ friend CFX_DateTime operator-(const CFX_DateTime& dt1,
+ const FX_DATETIME& dt2) {
+ CFX_DateTime dt;
+ dt.FromUnitime(dt1.ToUnitime() - ((const CFX_DateTime&)dt2).ToUnitime());
+ return dt;
+ }
+ friend CFX_DateTime operator-(const FX_DATETIME& dt1,
+ const CFX_DateTime& dt2) {
+ CFX_DateTime dt;
+ dt.FromUnitime(((const CFX_DateTime&)dt1).ToUnitime() - dt2.ToUnitime());
+ return dt;
+ }
+ friend FX_BOOL operator==(const CFX_DateTime& dt1, const CFX_DateTime& dt2) {
+ return FXSYS_memcmp(static_cast<const FX_DATETIME*>(dt1),
+ static_cast<const FX_DATETIME*>(dt2),
+ sizeof(FX_DATETIME)) == 0;
+ }
+ friend FX_BOOL operator==(const CFX_DateTime& dt1, const FX_DATETIME& dt2) {
+ return FXSYS_memcmp(static_cast<const FX_DATETIME*>(dt1), &dt2,
+ sizeof(FX_DATETIME)) == 0;
+ }
+ friend FX_BOOL operator==(const FX_DATETIME& dt1, const CFX_DateTime& dt2) {
+ return FXSYS_memcmp(&dt1, static_cast<const FX_DATETIME*>(dt2),
+ sizeof(FX_DATETIME)) == 0;
+ }
+ friend FX_BOOL operator!=(const CFX_DateTime& dt1, const CFX_DateTime& dt2) {
+ return FXSYS_memcmp(static_cast<const FX_DATETIME*>(dt1),
+ static_cast<const FX_DATETIME*>(dt2),
+ sizeof(FX_DATETIME)) != 0;
+ }
+ friend FX_BOOL operator!=(const CFX_DateTime& dt1, const FX_DATETIME& dt2) {
+ return FXSYS_memcmp(static_cast<const FX_DATETIME*>(dt1), &dt2,
+ sizeof(FX_DATETIME)) != 0;
+ }
+ friend FX_BOOL operator!=(const FX_DATETIME& dt1, const CFX_DateTime& dt2) {
+ return FXSYS_memcmp(&dt1, static_cast<const FX_DATETIME*>(dt2),
+ sizeof(FX_DATETIME)) != 0;
+ }
+ friend FX_BOOL operator>(const CFX_DateTime& dt1, const CFX_DateTime& dt2) {
+ return dt1.ToUnitime() > dt2.ToUnitime();
+ }
+ friend FX_BOOL operator>(const CFX_DateTime& dt1, const FX_DATETIME& dt2) {
+ return dt1.ToUnitime() > ((const CFX_DateTime&)dt2).ToUnitime();
+ }
+ friend FX_BOOL operator>(const FX_DATETIME& dt1, const CFX_DateTime& dt2) {
+ return ((const CFX_DateTime&)dt1).ToUnitime() > dt2.ToUnitime();
+ }
+ friend FX_BOOL operator>=(const CFX_DateTime& dt1, const CFX_DateTime& dt2) {
+ return dt1.ToUnitime() >= dt2.ToUnitime();
+ }
+ friend FX_BOOL operator>=(const CFX_DateTime& dt1, const FX_DATETIME& dt2) {
+ return dt1.ToUnitime() >= ((const CFX_DateTime&)dt2).ToUnitime();
+ }
+ friend FX_BOOL operator>=(const FX_DATETIME& dt1, const CFX_DateTime& dt2) {
+ return ((const CFX_DateTime&)dt1).ToUnitime() >= dt2.ToUnitime();
+ }
+ friend FX_BOOL operator<(const CFX_DateTime& dt1, const CFX_DateTime& dt2) {
+ return dt1.ToUnitime() < dt2.ToUnitime();
+ }
+ friend FX_BOOL operator<(const CFX_DateTime& dt1, const FX_DATETIME& dt2) {
+ return dt1.ToUnitime() < ((const CFX_DateTime&)dt2).ToUnitime();
+ }
+ friend FX_BOOL operator<(const FX_DATETIME& dt1, const CFX_DateTime& dt2) {
+ return ((const CFX_DateTime&)dt1).ToUnitime() < dt2.ToUnitime();
+ }
+ friend FX_BOOL operator<=(const CFX_DateTime& dt1, const CFX_DateTime& dt2) {
+ return dt1.ToUnitime() <= dt2.ToUnitime();
+ }
+ friend FX_BOOL operator<=(const CFX_DateTime& dt1, const FX_DATETIME& dt2) {
+ return dt1.ToUnitime() <= ((const CFX_DateTime&)dt2).ToUnitime();
+ }
+ friend FX_BOOL operator<=(const FX_DATETIME& dt1, const CFX_DateTime& dt2) {
+ return ((const CFX_DateTime&)dt1).ToUnitime() <= dt2.ToUnitime();
+ }
+
+ private:
+ FX_DATETIME m_DateTime;
+};
+
+#endif // XFA_SRC_FGAS_LOCALIZATION_FGAS_DATETIME_H_
diff --git a/xfa/src/fgas/localization/fgas_locale.cpp b/xfa/src/fgas/localization/fgas_locale.cpp
new file mode 100644
index 0000000000..1eaa0ebd48
--- /dev/null
+++ b/xfa/src/fgas/localization/fgas_locale.cpp
@@ -0,0 +1,5030 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include <algorithm>
+
+#include "core/include/fxcrt/fx_ext.h"
+#include "core/include/fxcrt/fx_xml.h"
+#include "xfa/src/fgas/localization/fgas_localeimp.h"
+
+#define FX_LOCALECATEGORY_DateHash 0xbde9abde
+#define FX_LOCALECATEGORY_TimeHash 0x2d71b00f
+#define FX_LOCALECATEGORY_DateTimeHash 0x158c72ed
+#define FX_LOCALECATEGORY_NumHash 0x0b4ff870
+#define FX_LOCALECATEGORY_TextHash 0x2d08af85
+#define FX_LOCALECATEGORY_ZeroHash 0x568cb500
+#define FX_LOCALECATEGORY_NullHash 0x052931bb
+
+struct FX_LOCALESUBCATEGORYINFO {
+ uint32_t uHash;
+ const FX_WCHAR* pName;
+ int32_t eSubCategory;
+};
+
+static const FX_LOCALESUBCATEGORYINFO g_FXLocaleDateTimeSubCatData[] = {
+ {0x14da2125, L"default", FX_LOCALEDATETIMESUBCATEGORY_Default},
+ {0x9041d4b0, L"short", FX_LOCALEDATETIMESUBCATEGORY_Short},
+ {0xa084a381, L"medium", FX_LOCALEDATETIMESUBCATEGORY_Medium},
+ {0xcdce56b3, L"full", FX_LOCALEDATETIMESUBCATEGORY_Full},
+ {0xf6b4afb0, L"long", FX_LOCALEDATETIMESUBCATEGORY_Long},
+};
+static const int32_t g_iFXLocaleDateTimeSubCatCount =
+ sizeof(g_FXLocaleDateTimeSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO);
+
+static const FX_LOCALESUBCATEGORYINFO g_FXLocaleNumSubCatData[] = {
+ {0x46f95531, L"percent", FX_LOCALENUMPATTERN_Percent},
+ {0x4c4e8acb, L"currency", FX_LOCALENUMPATTERN_Currency},
+ {0x54034c2f, L"decimal", FX_LOCALENUMPATTERN_Decimal},
+ {0x7568e6ae, L"integer", FX_LOCALENUMPATTERN_Integer},
+};
+static const int32_t g_iFXLocaleNumSubCatCount =
+ sizeof(g_FXLocaleNumSubCatData) / sizeof(FX_LOCALESUBCATEGORYINFO);
+
+struct FX_LOCALETIMEZONEINFO {
+ FX_DWORD uHash;
+ int16_t iHour;
+ int16_t iMinute;
+};
+
+static const FX_LOCALETIMEZONEINFO g_FXLocaleTimeZoneData[] = {
+ {FXBSTR_ID(0, 'C', 'D', 'T'), -5, 0}, {FXBSTR_ID(0, 'C', 'S', 'T'), -6, 0},
+ {FXBSTR_ID(0, 'E', 'D', 'T'), -4, 0}, {FXBSTR_ID(0, 'E', 'S', 'T'), -5, 0},
+ {FXBSTR_ID(0, 'M', 'D', 'T'), -6, 0}, {FXBSTR_ID(0, 'M', 'S', 'T'), -7, 0},
+ {FXBSTR_ID(0, 'P', 'D', 'T'), -7, 0}, {FXBSTR_ID(0, 'P', 'S', 'T'), -8, 0},
+};
+
+static const CFX_WideStringC gs_wsTextSymbols = FX_WSTRC(L"AXO09");
+static const CFX_WideStringC gs_wsTimeSymbols = FX_WSTRC(L"hHkKMSFAzZ");
+static const CFX_WideStringC gs_wsDateSymbols = FX_WSTRC(L"DJMEeGgYwW");
+static const CFX_WideStringC gs_wsConstChars = FX_WSTRC(L",-:/. ");
+
+static FX_STRSIZE FX_Local_Find(const CFX_WideStringC& wsSymbols,
+ FX_WCHAR ch,
+ FX_STRSIZE nStart = 0) {
+ FX_STRSIZE nLength = wsSymbols.GetLength();
+ if (nLength < 1 || nStart > nLength) {
+ return -1;
+ }
+ const FX_WCHAR* lpsz =
+ (const FX_WCHAR*)FXSYS_wcschr(wsSymbols.GetPtr() + nStart, ch);
+ return (lpsz == NULL) ? -1 : (FX_STRSIZE)(lpsz - wsSymbols.GetPtr());
+}
+static const FX_WCHAR* const gs_LocalNumberSymbols[] = {
+ L"decimal", L"grouping", L"percent", L"minus",
+ L"zero", L"currencySymbol", L"currencyName",
+};
+IFX_Locale* IFX_Locale::Create(CXML_Element* pLocaleData) {
+ return new CFX_Locale(pLocaleData);
+}
+CFX_Locale::CFX_Locale(CXML_Element* pLocaleData) {
+ m_pElement = pLocaleData;
+}
+CFX_Locale::~CFX_Locale() {}
+CFX_WideString CFX_Locale::GetName() {
+ return CFX_WideString();
+}
+static CFX_WideString FX_GetXMLContent(const CFX_ByteStringC& bsSpace,
+ CXML_Element* pxmlElement,
+ const CFX_ByteStringC& bsTag,
+ const CFX_WideStringC& wsName) {
+ CXML_Element* pDatePattern = NULL;
+ int32_t nCount = pxmlElement->CountElements(bsSpace, bsTag);
+ int32_t i = 0;
+ for (; i < nCount; i++) {
+ pDatePattern = pxmlElement->GetElement(bsSpace, bsTag, i);
+ if (pDatePattern->GetAttrValue("name") == wsName) {
+ break;
+ }
+ }
+ if (i < nCount && pDatePattern) {
+ return pDatePattern->GetContent(0);
+ }
+ return L"";
+}
+void CFX_Locale::GetNumbericSymbol(FX_LOCALENUMSYMBOL eType,
+ CFX_WideString& wsNumSymbol) const {
+ if (!m_pElement) {
+ return;
+ }
+ CFX_ByteString bsSpace;
+ CFX_WideString wsName = gs_LocalNumberSymbols[eType];
+ CXML_Element* pNumberSymbols =
+ m_pElement->GetElement(bsSpace, "numberSymbols");
+ if (!pNumberSymbols) {
+ return;
+ }
+ wsNumSymbol =
+ FX_GetXMLContent(bsSpace, pNumberSymbols, "numberSymbol", wsName);
+}
+void CFX_Locale::GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const {
+ if (!m_pElement) {
+ return;
+ }
+ CFX_ByteString bsSpace;
+ CXML_Element* pNumberSymbols =
+ m_pElement->GetElement(bsSpace, "dateTimeSymbols");
+ if (!pNumberSymbols) {
+ return;
+ }
+ wsDtSymbol = pNumberSymbols->GetContent(0);
+}
+static void FX_GetCalendarSymbol(CXML_Element* pXmlElement,
+ const CFX_ByteString& symbol_type,
+ int32_t index,
+ FX_BOOL bAbbr,
+ CFX_WideString& wsName) {
+ CFX_ByteString bsSpace;
+ CFX_ByteString pstrSymbolNames = symbol_type + "Names";
+ CXML_Element* pChild = pXmlElement->GetElement(bsSpace, "calendarSymbols");
+ if (!pChild) {
+ return;
+ }
+ CXML_Element* pSymbolNames = pChild->GetElement(bsSpace, pstrSymbolNames);
+ if (!pSymbolNames) {
+ return;
+ }
+ if (pSymbolNames->GetAttrInteger("abbr") != bAbbr) {
+ pSymbolNames = pChild->GetElement(bsSpace, pstrSymbolNames, 1);
+ }
+ if (pSymbolNames && pSymbolNames->GetAttrInteger("abbr") == bAbbr) {
+ CXML_Element* pSymbolName =
+ pSymbolNames->GetElement(bsSpace, symbol_type, index);
+ if (pSymbolName) {
+ wsName = pSymbolName->GetContent(0);
+ }
+ }
+}
+void CFX_Locale::GetMonthName(int32_t nMonth,
+ CFX_WideString& wsMonthName,
+ FX_BOOL bAbbr) const {
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetCalendarSymbol(m_pElement, "month", nMonth, bAbbr, wsMonthName);
+}
+void CFX_Locale::GetDayName(int32_t nWeek,
+ CFX_WideString& wsDayName,
+ FX_BOOL bAbbr) const {
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetCalendarSymbol(m_pElement, "day", nWeek, bAbbr, wsDayName);
+}
+void CFX_Locale::GetMeridiemName(CFX_WideString& wsMeridiemName,
+ FX_BOOL bAM) const {
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetCalendarSymbol(m_pElement, "meridiem", bAM ? 0 : 1, FALSE,
+ wsMeridiemName);
+}
+static int32_t FX_ParseTimeZone(const FX_WCHAR* pStr,
+ int32_t iLen,
+ FX_TIMEZONE& tz) {
+ tz.tzHour = 0;
+ tz.tzMinute = 0;
+ if (iLen < 0) {
+ return 0;
+ }
+ int32_t iStart = 1;
+ int32_t iEnd = iStart + 2;
+ while (iStart < iLen && iStart < iEnd) {
+ tz.tzHour = tz.tzHour * 10 + pStr[iStart++] - '0';
+ }
+ if (iStart < iLen && pStr[iStart] == ':') {
+ iStart++;
+ }
+ iEnd = iStart + 2;
+ while (iStart < iLen && iStart < iEnd) {
+ tz.tzMinute = tz.tzMinute * 10 + pStr[iStart++] - '0';
+ }
+ if (pStr[0] == '-') {
+ tz.tzHour = -tz.tzHour;
+ }
+ return iStart;
+}
+void CFX_Locale::GetTimeZone(FX_TIMEZONE& tz) const {
+ tz.tzHour = 0;
+ tz.tzMinute = 0;
+ if (!m_pElement) {
+ return;
+ }
+ CXML_Element* pxmlTimeZone = m_pElement->GetElement("", "timeZone");
+ if (pxmlTimeZone) {
+ CFX_WideString wsTimeZone = pxmlTimeZone->GetContent(0);
+ FX_ParseTimeZone(wsTimeZone, wsTimeZone.GetLength(), tz);
+ }
+}
+void CFX_Locale::GetEraName(CFX_WideString& wsEraName, FX_BOOL bAD) const {
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetCalendarSymbol(m_pElement, "era", bAD ? 0 : 1, FALSE, wsEraName);
+}
+static void FX_GetPattern(CXML_Element* pXmlElement,
+ const CFX_ByteString& bsCategory,
+ const CFX_WideString& wsSubCategory,
+ CFX_WideString& wsPattern) {
+ CFX_ByteString bsSpace;
+ CXML_Element* pDatePatterns =
+ pXmlElement->GetElement(bsSpace, bsCategory + "s");
+ if (!pDatePatterns) {
+ return;
+ }
+ wsPattern =
+ FX_GetXMLContent(bsSpace, pDatePatterns, bsCategory, wsSubCategory);
+}
+static void FX_GetDateTimePattern(CXML_Element* pXmlElement,
+ const CFX_ByteString& bsCategory,
+ FX_LOCALEDATETIMESUBCATEGORY eType,
+ CFX_WideString& wsPattern) {
+ CFX_WideString wsType = g_FXLocaleDateTimeSubCatData[eType].pName;
+ FX_GetPattern(pXmlElement, bsCategory, wsType, wsPattern);
+}
+void CFX_Locale::GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
+ CFX_WideString& wsPattern) const {
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetDateTimePattern(m_pElement, "datePattern", eType, wsPattern);
+}
+void CFX_Locale::GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
+ CFX_WideString& wsPattern) const {
+ if (!m_pElement) {
+ return;
+ }
+ FX_GetDateTimePattern(m_pElement, "timePattern", eType, wsPattern);
+}
+void CFX_Locale::GetNumPattern(FX_LOCALENUMSUBCATEGORY eType,
+ CFX_WideString& wsPattern) const {
+ CFX_WideString wsType = g_FXLocaleNumSubCatData[eType].pName;
+ FX_GetPattern(m_pElement, "numberPattern", wsType, wsPattern);
+}
+static FX_BOOL FX_IsDigit(FX_WCHAR c) {
+ return c >= '0' && c <= '9';
+}
+static FX_BOOL FX_IsAlpha(FX_WCHAR c) {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+static FX_BOOL FX_IsSpace(FX_WCHAR c) {
+ return (c == 0x20) || (c == 0x0d) || (c == 0x0a) || (c == 0x09);
+}
+static const FX_FLOAT gs_fraction_scales[] = {
+ 0.1f, 0.01f, 0.001f, 0.0001f,
+ 0.00001f, 0.000001f, 0.0000001f, 0.00000001f,
+ 0.000000001f, 0.0000000001f, 0.00000000001f};
+static const int32_t gs_fraction_count =
+ sizeof(gs_fraction_scales) / sizeof(FX_FLOAT);
+
+class CFX_LCNumeric {
+ public:
+ CFX_LCNumeric();
+ CFX_LCNumeric(int64_t integral,
+ uint32_t fractional = 0,
+ int32_t exponent = 0);
+ CFX_LCNumeric(FX_FLOAT dbRetValue);
+ CFX_LCNumeric(double dbvalue);
+ CFX_LCNumeric(CFX_WideString& wsNumeric);
+
+ FX_FLOAT GetFloat() const;
+ double GetDouble() const;
+ CFX_WideString ToString() const;
+ CFX_WideString ToString(int32_t nTreading, FX_BOOL bTrimTailZeros) const;
+
+ int64_t m_Integral;
+ uint32_t m_Fractional;
+ int32_t m_Exponent;
+};
+
+static FX_BOOL FX_WStringToNumeric(const CFX_WideString& wsValue,
+ CFX_LCNumeric& lcnum) {
+ lcnum.m_Integral = 0;
+ lcnum.m_Fractional = 0;
+ lcnum.m_Exponent = 0;
+
+ if (wsValue.IsEmpty())
+ return FALSE;
+
+ const int32_t nIntegralMaxLen = 17;
+ int32_t cc = 0;
+ bool bNegative = false;
+ bool bExpSign = false;
+ const FX_WCHAR* str = (const FX_WCHAR*)wsValue;
+ int32_t len = wsValue.GetLength();
+ while (cc < len && FX_IsSpace(str[cc]))
+ cc++;
+
+ if (cc >= len)
+ return FALSE;
+
+ if (str[cc] == '+') {
+ cc++;
+ } else if (str[cc] == '-') {
+ bNegative = true;
+ cc++;
+ }
+ int32_t nIntegralLen = 0;
+ while (cc < len) {
+ if (str[cc] == '.')
+ break;
+
+ if (!FX_IsDigit(str[cc])) {
+ if ((str[cc] == 'E' || str[cc] == 'e'))
+ break;
+ else
+ return FALSE;
+ }
+ if (nIntegralLen < nIntegralMaxLen) {
+ lcnum.m_Integral = lcnum.m_Integral * 10 + str[cc] - '0';
+ nIntegralLen++;
+ }
+ cc++;
+ }
+
+ lcnum.m_Integral = bNegative ? -lcnum.m_Integral : lcnum.m_Integral;
+ if (cc < len && str[cc] == '.') {
+ int scale = 0;
+ double fraction = 0.0;
+ cc++;
+ while (cc < len) {
+ if (scale >= gs_fraction_count) {
+ while (cc < len) {
+ if (!FX_IsDigit(str[cc]))
+ break;
+ cc++;
+ }
+ }
+ if (!FX_IsDigit(str[cc])) {
+ if ((str[cc] == 'E' || str[cc] == 'e'))
+ break;
+ else
+ return FALSE;
+ }
+ fraction += gs_fraction_scales[scale] * (str[cc] - '0');
+ scale++;
+ cc++;
+ }
+ lcnum.m_Fractional = (FX_DWORD)(fraction * 4294967296.0);
+ }
+ if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) {
+ cc++;
+ if (cc < len) {
+ if (str[cc] == '+') {
+ cc++;
+ } else if (str[cc] == '-') {
+ bExpSign = true;
+ cc++;
+ }
+ }
+ while (cc < len) {
+ if (FX_IsDigit(str[cc]))
+ return FALSE;
+ lcnum.m_Exponent = lcnum.m_Exponent * 10 + str[cc] - '0';
+ cc++;
+ }
+ lcnum.m_Exponent = bExpSign ? -lcnum.m_Exponent : lcnum.m_Exponent;
+ }
+ return TRUE;
+}
+
+CFX_LCNumeric::CFX_LCNumeric() {
+ m_Integral = 0;
+ m_Fractional = 0;
+ m_Exponent = 0;
+}
+CFX_LCNumeric::CFX_LCNumeric(int64_t integral,
+ FX_DWORD fractional,
+ int32_t exponent) {
+ m_Integral = integral;
+ m_Fractional = fractional;
+ m_Exponent = exponent;
+}
+CFX_LCNumeric::CFX_LCNumeric(FX_FLOAT dbRetValue) {
+ m_Integral = (int64_t)dbRetValue;
+ m_Fractional = (FX_DWORD)(((dbRetValue > 0) ? (dbRetValue - m_Integral)
+ : (m_Integral - dbRetValue)) *
+ 4294967296);
+ m_Exponent = 0;
+}
+CFX_LCNumeric::CFX_LCNumeric(double dbvalue) {
+ m_Integral = (int64_t)dbvalue;
+ m_Fractional = (FX_DWORD)(
+ ((dbvalue > 0) ? (dbvalue - m_Integral) : (m_Integral - dbvalue)) *
+ 4294967296);
+ m_Exponent = 0;
+}
+CFX_LCNumeric::CFX_LCNumeric(CFX_WideString& wsNumeric) {
+ FX_WStringToNumeric(wsNumeric, *this);
+}
+FX_FLOAT CFX_LCNumeric::GetFloat() const {
+ FX_FLOAT dbRetValue = m_Fractional / 4294967296.0f;
+ dbRetValue = m_Integral + (m_Integral >= 0 ? dbRetValue : -dbRetValue);
+ if (m_Exponent != 0) {
+ dbRetValue *= FXSYS_pow(10, (FX_FLOAT)m_Exponent);
+ }
+ return dbRetValue;
+}
+double CFX_LCNumeric::GetDouble() const {
+ double value = m_Fractional / 4294967296.0;
+ value = m_Integral + (m_Integral >= 0 ? value : -value);
+ if (m_Exponent != 0) {
+ value *= FXSYS_pow(10, (FX_FLOAT)m_Exponent);
+ }
+ return value;
+}
+
+CFX_WideString CFX_LCNumeric::ToString() const {
+ return ToString(8, TRUE);
+}
+
+CFX_WideString CFX_LCNumeric::ToString(int32_t nTreading,
+ FX_BOOL bTrimTailZeros) const {
+ CFX_WideString wsFormat;
+ wsFormat.Format(L"%%.%df", nTreading);
+ CFX_WideString wsResult;
+ wsResult.Format(wsFormat.c_str(), GetDouble());
+ if (bTrimTailZeros && nTreading > 0) {
+ wsResult.TrimRight(L"0");
+ wsResult.TrimRight(L".");
+ }
+ return wsResult;
+}
+
+IFX_FormatString* IFX_FormatString::Create(IFX_LocaleMgr* pLocaleMgr,
+ FX_BOOL bUseLCID) {
+ if (!pLocaleMgr) {
+ return NULL;
+ }
+ return new CFX_FormatString(pLocaleMgr, bUseLCID);
+}
+CFX_FormatString::CFX_FormatString(IFX_LocaleMgr* pLocaleMgr, FX_BOOL bUseLCID)
+ : m_pLocaleMgr(pLocaleMgr), m_bUseLCID(bUseLCID) {}
+CFX_FormatString::~CFX_FormatString() {}
+void CFX_FormatString::SplitFormatString(const CFX_WideString& wsFormatString,
+ CFX_WideStringArray& wsPatterns) {
+ int32_t iStrLen = wsFormatString.GetLength();
+ const FX_WCHAR* pStr = (const FX_WCHAR*)wsFormatString;
+ const FX_WCHAR* pToken = pStr;
+ const FX_WCHAR* pEnd = pStr + iStrLen;
+ FX_BOOL iQuote = FALSE;
+ while (TRUE) {
+ if (pStr >= pEnd) {
+ CFX_WideString sub(pToken, pStr - pToken);
+ wsPatterns.Add(sub);
+ return;
+ } else if (*pStr == '\'') {
+ iQuote = !iQuote;
+ } else if (*pStr == L'|' && !iQuote) {
+ CFX_WideString sub(pToken, pStr - pToken);
+ wsPatterns.Add(sub);
+ pToken = pStr + 1;
+ }
+ pStr++;
+ }
+}
+static CFX_WideString FX_GetLiteralText(const FX_WCHAR* pStrPattern,
+ int32_t& iPattern,
+ int32_t iLenPattern) {
+ CFX_WideString wsOutput;
+ if (pStrPattern[iPattern] != '\'') {
+ return wsOutput;
+ }
+ iPattern++;
+ int32_t iQuote = 1;
+ while (iPattern < iLenPattern) {
+ if (pStrPattern[iPattern] == '\'') {
+ iQuote++;
+ if ((iPattern + 1 >= iLenPattern) ||
+ ((pStrPattern[iPattern + 1] != '\'') && (iQuote % 2 == 0))) {
+ break;
+ } else {
+ iQuote++;
+ }
+ iPattern++;
+ } else if (pStrPattern[iPattern] == '\\' && (iPattern + 1 < iLenPattern) &&
+ pStrPattern[iPattern + 1] == 'u') {
+ int32_t iKeyValue = 0;
+ iPattern += 2;
+ int32_t i = 0;
+ while (iPattern < iLenPattern && i++ < 4) {
+ FX_WCHAR ch = pStrPattern[iPattern++];
+ if ((ch >= '0' && ch <= '9')) {
+ iKeyValue = iKeyValue * 16 + ch - '0';
+ } else if ((ch >= 'a' && ch <= 'f')) {
+ iKeyValue = iKeyValue * 16 + ch - 'a' + 10;
+ } else if ((ch >= 'A' && ch <= 'F')) {
+ iKeyValue = iKeyValue * 16 + ch - 'A' + 10;
+ }
+ }
+ if (iKeyValue != 0) {
+ wsOutput += (FX_WCHAR)(iKeyValue & 0x0000FFFF);
+ }
+ continue;
+ }
+ wsOutput += pStrPattern[iPattern++];
+ }
+ return wsOutput;
+}
+static CFX_WideString FX_GetLiteralTextReverse(const FX_WCHAR* pStrPattern,
+ int32_t& iPattern) {
+ CFX_WideString wsOutput;
+ if (pStrPattern[iPattern] != '\'') {
+ return wsOutput;
+ }
+ iPattern--;
+ int32_t iQuote = 1;
+ while (iPattern >= 0) {
+ if (pStrPattern[iPattern] == '\'') {
+ iQuote++;
+ if (iPattern - 1 >= 0 ||
+ ((pStrPattern[iPattern - 1] != '\'') && (iQuote % 2 == 0))) {
+ break;
+ } else {
+ iQuote++;
+ }
+ iPattern--;
+ } else if (pStrPattern[iPattern] == '\\' &&
+ pStrPattern[iPattern + 1] == 'u') {
+ iPattern--;
+ int32_t iKeyValue = 0;
+ int32_t iLen = wsOutput.GetLength();
+ int32_t i = 1;
+ for (; i < iLen && i < 5; i++) {
+ FX_WCHAR ch = wsOutput[i];
+ if ((ch >= '0' && ch <= '9')) {
+ iKeyValue = iKeyValue * 16 + ch - '0';
+ } else if ((ch >= 'a' && ch <= 'f')) {
+ iKeyValue = iKeyValue * 16 + ch - 'a' + 10;
+ } else if ((ch >= 'A' && ch <= 'F')) {
+ iKeyValue = iKeyValue * 16 + ch - 'A' + 10;
+ }
+ }
+ if (iKeyValue != 0) {
+ wsOutput.Delete(0, i);
+ wsOutput = (FX_WCHAR)(iKeyValue & 0x0000FFFF) + wsOutput;
+ }
+ continue;
+ }
+ wsOutput = pStrPattern[iPattern--] + wsOutput;
+ }
+ return wsOutput;
+}
+FX_LOCALECATEGORY CFX_FormatString::GetCategory(
+ const CFX_WideString& wsPattern) {
+ FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown;
+ int32_t ccf = 0;
+ int32_t iLenf = wsPattern.GetLength();
+ const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern;
+ FX_BOOL bBraceOpen = FALSE;
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ } else if (!bBraceOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
+ CFX_WideString wsCategory(pStr[ccf]);
+ ccf++;
+ while (TRUE) {
+ if (ccf == iLenf) {
+ return eCategory;
+ }
+ if (pStr[ccf] == '.' || pStr[ccf] == '(') {
+ break;
+ }
+ if (pStr[ccf] == '{') {
+ bBraceOpen = TRUE;
+ break;
+ }
+ wsCategory += pStr[ccf];
+ ccf++;
+ }
+ FX_DWORD dwHash =
+ FX_HashCode_String_GetW(wsCategory, wsCategory.GetLength());
+ if (dwHash == FX_LOCALECATEGORY_DateHash) {
+ if (eCategory == FX_LOCALECATEGORY_Time) {
+ return FX_LOCALECATEGORY_DateTime;
+ }
+ eCategory = FX_LOCALECATEGORY_Date;
+ } else if (dwHash == FX_LOCALECATEGORY_TimeHash) {
+ if (eCategory == FX_LOCALECATEGORY_Date) {
+ return FX_LOCALECATEGORY_DateTime;
+ }
+ eCategory = FX_LOCALECATEGORY_Time;
+ } else if (dwHash == FX_LOCALECATEGORY_DateTimeHash) {
+ return FX_LOCALECATEGORY_DateTime;
+ } else if (dwHash == FX_LOCALECATEGORY_TextHash) {
+ return FX_LOCALECATEGORY_Text;
+ } else if (dwHash == FX_LOCALECATEGORY_NumHash) {
+ return FX_LOCALECATEGORY_Num;
+ } else if (dwHash == FX_LOCALECATEGORY_ZeroHash) {
+ return FX_LOCALECATEGORY_Zero;
+ } else if (dwHash == FX_LOCALECATEGORY_NullHash) {
+ return FX_LOCALECATEGORY_Null;
+ }
+ } else if (pStr[ccf] == '}') {
+ bBraceOpen = FALSE;
+ }
+ ccf++;
+ }
+ return eCategory;
+}
+static FX_WORD FX_WStringToLCID(const FX_WCHAR* pstrLCID) {
+ if (!pstrLCID) {
+ return 0;
+ }
+ wchar_t* pEnd;
+ return (FX_WORD)wcstol((wchar_t*)pstrLCID, &pEnd, 16);
+}
+FX_WORD CFX_FormatString::GetLCID(const CFX_WideString& wsPattern) {
+ return FX_WStringToLCID(GetLocaleName(wsPattern));
+}
+CFX_WideString CFX_FormatString::GetLocaleName(
+ const CFX_WideString& wsPattern) {
+ int32_t ccf = 0;
+ int32_t iLenf = wsPattern.GetLength();
+ const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern;
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ } else if (pStr[ccf] == '(') {
+ ccf++;
+ CFX_WideString wsLCID;
+ while (ccf < iLenf && pStr[ccf] != ')') {
+ wsLCID += pStr[ccf++];
+ }
+ return wsLCID;
+ }
+ ccf++;
+ }
+ return CFX_WideString();
+}
+IFX_Locale* CFX_FormatString::GetTextFormat(const CFX_WideString& wsPattern,
+ const CFX_WideStringC& wsCategory,
+ CFX_WideString& wsPurgePattern) {
+ IFX_Locale* pLocale = NULL;
+ int32_t ccf = 0;
+ int32_t iLenf = wsPattern.GetLength();
+ const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern;
+ FX_BOOL bBrackOpen = FALSE;
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ int32_t iCurChar = ccf;
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ wsPurgePattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1);
+ } else if (!bBrackOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
+ CFX_WideString wsSearchCategory(pStr[ccf]);
+ ccf++;
+ while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' &&
+ pStr[ccf] != '(') {
+ wsSearchCategory += pStr[ccf];
+ ccf++;
+ }
+ if (wsSearchCategory != wsCategory) {
+ continue;
+ }
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '(') {
+ ccf++;
+ CFX_WideString wsLCID;
+ while (ccf < iLenf && pStr[ccf] != ')') {
+ wsLCID += pStr[ccf++];
+ }
+ pLocale = GetPatternLocale(wsLCID);
+ } else if (pStr[ccf] == '{') {
+ bBrackOpen = TRUE;
+ break;
+ }
+ ccf++;
+ }
+ } else if (pStr[ccf] != '}') {
+ wsPurgePattern += pStr[ccf];
+ }
+ ccf++;
+ }
+ if (!bBrackOpen) {
+ wsPurgePattern = wsPattern;
+ }
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ return pLocale;
+}
+#define FX_NUMSTYLE_Percent 0x01
+#define FX_NUMSTYLE_Exponent 0x02
+#define FX_NUMSTYLE_DotVorv 0x04
+IFX_Locale* CFX_FormatString::GetNumericFormat(const CFX_WideString& wsPattern,
+ int32_t& iDotIndex,
+ FX_DWORD& dwStyle,
+ CFX_WideString& wsPurgePattern) {
+ dwStyle = 0;
+ IFX_Locale* pLocale = NULL;
+ int32_t ccf = 0;
+ int32_t iLenf = wsPattern.GetLength();
+ const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern;
+ FX_BOOL bFindDot = FALSE;
+ FX_BOOL bBrackOpen = FALSE;
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ int32_t iCurChar = ccf;
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ wsPurgePattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1);
+ } else if (!bBrackOpen && FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
+ CFX_WideString wsCategory(pStr[ccf]);
+ ccf++;
+ while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' &&
+ pStr[ccf] != '(') {
+ wsCategory += pStr[ccf];
+ ccf++;
+ }
+ if (wsCategory != FX_WSTRC(L"num")) {
+ bBrackOpen = TRUE;
+ ccf = 0;
+ continue;
+ }
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '(') {
+ ccf++;
+ CFX_WideString wsLCID;
+ while (ccf < iLenf && pStr[ccf] != ')') {
+ wsLCID += pStr[ccf++];
+ }
+ pLocale = GetPatternLocale(wsLCID);
+ } else if (pStr[ccf] == '{') {
+ bBrackOpen = TRUE;
+ break;
+ } else if (pStr[ccf] == '.') {
+ CFX_WideString wsSubCategory;
+ ccf++;
+ while (ccf < iLenf && pStr[ccf] != '(' && pStr[ccf] != '{') {
+ wsSubCategory += pStr[ccf++];
+ }
+ FX_DWORD dwSubHash =
+ FX_HashCode_String_GetW(wsSubCategory, wsSubCategory.GetLength());
+ FX_LOCALENUMSUBCATEGORY eSubCategory = FX_LOCALENUMPATTERN_Decimal;
+ for (int32_t i = 0; i < g_iFXLocaleNumSubCatCount; i++) {
+ if (g_FXLocaleNumSubCatData[i].uHash == dwSubHash) {
+ eSubCategory = (FX_LOCALENUMSUBCATEGORY)g_FXLocaleNumSubCatData[i]
+ .eSubCategory;
+ break;
+ }
+ }
+ wsSubCategory.Empty();
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ FXSYS_assert(pLocale != NULL);
+ pLocale->GetNumPattern(eSubCategory, wsSubCategory);
+ iDotIndex = wsSubCategory.Find('.');
+ if (iDotIndex > 0) {
+ iDotIndex += wsPurgePattern.GetLength();
+ bFindDot = TRUE;
+ dwStyle |= FX_NUMSTYLE_DotVorv;
+ }
+ wsPurgePattern += wsSubCategory;
+ if (eSubCategory == FX_LOCALENUMPATTERN_Percent) {
+ dwStyle |= FX_NUMSTYLE_Percent;
+ }
+ continue;
+ }
+ ccf++;
+ }
+ } else if (pStr[ccf] == 'E') {
+ dwStyle |= FX_NUMSTYLE_Exponent;
+ wsPurgePattern += pStr[ccf];
+ } else if (pStr[ccf] == '%') {
+ dwStyle |= FX_NUMSTYLE_Percent;
+ wsPurgePattern += pStr[ccf];
+ } else if (pStr[ccf] != '}') {
+ wsPurgePattern += pStr[ccf];
+ }
+ if (!bFindDot) {
+ if (pStr[ccf] == '.' || pStr[ccf] == 'V' || pStr[ccf] == 'v') {
+ bFindDot = TRUE;
+ iDotIndex = wsPurgePattern.GetLength() - 1;
+ dwStyle |= FX_NUMSTYLE_DotVorv;
+ }
+ }
+ ccf++;
+ }
+ if (!bFindDot) {
+ iDotIndex = wsPurgePattern.GetLength();
+ }
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ return pLocale;
+}
+static FX_BOOL FX_GetNumericDotIndex(const CFX_WideString& wsNum,
+ const CFX_WideString& wsDotSymbol,
+ int32_t& iDotIndex) {
+ int32_t ccf = 0;
+ int32_t iLenf = wsNum.GetLength();
+ const FX_WCHAR* pStr = (const FX_WCHAR*)wsNum;
+ int32_t iLenDot = wsDotSymbol.GetLength();
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ } else if (ccf + iLenDot <= iLenf &&
+ !FXSYS_wcsncmp(pStr + ccf, (const FX_WCHAR*)wsDotSymbol,
+ iLenDot)) {
+ iDotIndex = ccf;
+ return TRUE;
+ }
+ ccf++;
+ }
+ iDotIndex = wsNum.Find('.');
+ if (iDotIndex < 0) {
+ iDotIndex = iLenf;
+ return FALSE;
+ }
+ return TRUE;
+}
+FX_BOOL CFX_FormatString::ParseText(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsValue) {
+ wsValue.Empty();
+ if (wsSrcText.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsTextFormat;
+ GetTextFormat(wsPattern, FX_WSTRC(L"text"), wsTextFormat);
+ if (wsTextFormat.IsEmpty()) {
+ return FALSE;
+ }
+ int32_t iText = 0, iPattern = 0;
+ const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText;
+ int32_t iLenText = wsSrcText.GetLength();
+ const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
+ int32_t iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern && iText < iLenText) {
+ switch (pStrPattern[iPattern]) {
+ case '\'': {
+ CFX_WideString wsLiteral =
+ FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ int32_t iLiteralLen = wsLiteral.GetLength();
+ if (iText + iLiteralLen > iLenText ||
+ FXSYS_wcsncmp(pStrText + iText, (const FX_WCHAR*)wsLiteral,
+ iLiteralLen)) {
+ wsValue = wsSrcText;
+ return FALSE;
+ }
+ iText += iLiteralLen;
+ iPattern++;
+ break;
+ }
+ case 'A':
+ if (FX_IsAlpha(pStrText[iText])) {
+ wsValue += pStrText[iText];
+ iText++;
+ }
+ iPattern++;
+ break;
+ case 'X':
+ wsValue += pStrText[iText];
+ iText++;
+ iPattern++;
+ break;
+ case 'O':
+ case '0':
+ if (FX_IsDigit(pStrText[iText]) || FX_IsAlpha(pStrText[iText])) {
+ wsValue += pStrText[iText];
+ iText++;
+ }
+ iPattern++;
+ break;
+ case '9':
+ if (FX_IsDigit(pStrText[iText])) {
+ wsValue += pStrText[iText];
+ iText++;
+ }
+ iPattern++;
+ break;
+ default:
+ if (pStrPattern[iPattern] != pStrText[iText]) {
+ wsValue = wsSrcText;
+ return FALSE;
+ }
+ iPattern++;
+ iText++;
+ break;
+ }
+ }
+ return iPattern == iLenPattern && iText == iLenText;
+}
+FX_BOOL CFX_FormatString::ParseNum(const CFX_WideString& wsSrcNum,
+ const CFX_WideString& wsPattern,
+ FX_FLOAT& fValue) {
+ fValue = 0.0f;
+ if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ int32_t dot_index_f = -1;
+ FX_DWORD dwFormatStyle = 0;
+ CFX_WideString wsNumFormat;
+ IFX_Locale* pLocale =
+ GetNumericFormat(wsPattern, dot_index_f, dwFormatStyle, wsNumFormat);
+ if (!pLocale || wsNumFormat.IsEmpty()) {
+ return FALSE;
+ }
+ int32_t iExponent = 0;
+ CFX_WideString wsDotSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
+ CFX_WideString wsGroupSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
+ int32_t iGroupLen = wsGroupSymbol.GetLength();
+ CFX_WideString wsMinus;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinus);
+ int32_t iMinusLen = wsMinus.GetLength();
+ int cc = 0, ccf = 0;
+ const FX_WCHAR* str = (const FX_WCHAR*)wsSrcNum;
+ int len = wsSrcNum.GetLength();
+ const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat;
+ int lenf = wsNumFormat.GetLength();
+ double dbRetValue = 0;
+ double coeff = 1;
+ FX_BOOL bHavePercentSymbol = FALSE;
+ FX_BOOL bNeg = FALSE;
+ FX_BOOL bReverseParse = FALSE;
+ int32_t dot_index = 0;
+ if (!FX_GetNumericDotIndex(wsSrcNum, wsDotSymbol, dot_index) &&
+ (dwFormatStyle & FX_NUMSTYLE_DotVorv)) {
+ bReverseParse = TRUE;
+ }
+ bReverseParse = FALSE;
+ if (bReverseParse) {
+ ccf = lenf - 1;
+ cc = len - 1;
+ while (ccf > dot_index_f && cc >= 0) {
+ switch (strf[ccf]) {
+ case '\'': {
+ CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf);
+ int32_t iLiteralLen = wsLiteral.GetLength();
+ cc -= iLiteralLen - 1;
+ if (cc < 0 || FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral,
+ iLiteralLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ }
+ case '9':
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1;
+ coeff *= 0.1;
+ cc--;
+ ccf--;
+ break;
+ case 'z':
+ if (cc >= 0) {
+ dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1;
+ coeff *= 0.1;
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'Z':
+ if (str[cc] != ' ') {
+ dbRetValue = dbRetValue * coeff + (str[cc] - '0') * 0.1;
+ coeff *= 0.1;
+ }
+ cc--;
+ ccf--;
+ break;
+ case 'S':
+ if (str[cc] == '+' || str[cc] == ' ') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 's':
+ if (str[cc] == '+') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 'E': {
+ if (cc >= dot_index) {
+ return FALSE;
+ }
+ FX_BOOL bExpSign = FALSE;
+ while (cc >= 0) {
+ if (str[cc] == 'E' || str[cc] == 'e') {
+ break;
+ }
+ if (FX_IsDigit(str[cc])) {
+ iExponent = iExponent + (str[cc] - '0') * 10;
+ cc--;
+ continue;
+ } else if (str[cc] == '+') {
+ cc--;
+ continue;
+ } else if (cc - iMinusLen + 1 > 0 &&
+ !FXSYS_wcsncmp(str + (cc - iMinusLen + 1),
+ (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ bExpSign = TRUE;
+ cc -= iMinusLen;
+ } else {
+ return FALSE;
+ }
+ }
+ cc--;
+ iExponent = bExpSign ? -iExponent : iExponent;
+ ccf--;
+ } break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol,
+ wsSymbol);
+ int32_t iSymbolLen = wsSymbol.GetLength();
+ cc -= iSymbolLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ } break;
+ case 'r':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
+ if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'R':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'b':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
+ if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'B':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case '.':
+ case 'V':
+ case 'v':
+ return FALSE;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ int32_t iSysmbolLen = wsSymbol.GetLength();
+ cc -= iSysmbolLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSysmbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ bHavePercentSymbol = TRUE;
+ } break;
+ case '8':
+ while (ccf < lenf && strf[ccf] == '8') {
+ ccf++;
+ }
+ while (cc < len && FX_IsDigit(str[cc])) {
+ dbRetValue = (str[cc] - '0') * coeff + dbRetValue;
+ coeff *= 0.1;
+ cc++;
+ }
+ break;
+ case ',': {
+ if (cc >= 0) {
+ cc -= iGroupLen - 1;
+ if (cc >= 0 &&
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol,
+ iGroupLen) == 0) {
+ cc--;
+ } else {
+ cc += iGroupLen - 1;
+ }
+ }
+ ccf--;
+ } break;
+ case '(':
+ if (str[cc] == L'(') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ case ')':
+ if (str[cc] == L')') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ default:
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ }
+ }
+ dot_index = cc + 1;
+ }
+ ccf = dot_index_f - 1;
+ cc = dot_index - 1;
+ coeff = 1;
+ while (ccf >= 0 && cc >= 0) {
+ switch (strf[ccf]) {
+ case '\'': {
+ CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf);
+ int32_t iLiteralLen = wsLiteral.GetLength();
+ cc -= iLiteralLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ }
+ case '9':
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 10;
+ cc--;
+ ccf--;
+ break;
+ case 'z':
+ if (FX_IsDigit(str[cc])) {
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 10;
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'Z':
+ if (str[cc] != ' ') {
+ if (FX_IsDigit(str[cc])) {
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 10;
+ cc--;
+ }
+ } else {
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'S':
+ if (str[cc] == '+' || str[cc] == ' ') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 's':
+ if (str[cc] == '+') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 'E': {
+ if (cc >= dot_index) {
+ return FALSE;
+ }
+ FX_BOOL bExpSign = FALSE;
+ while (cc >= 0) {
+ if (str[cc] == 'E' || str[cc] == 'e') {
+ break;
+ }
+ if (FX_IsDigit(str[cc])) {
+ iExponent = iExponent + (str[cc] - '0') * 10;
+ cc--;
+ continue;
+ } else if (str[cc] == '+') {
+ cc--;
+ continue;
+ } else if (cc - iMinusLen + 1 > 0 &&
+ !FXSYS_wcsncmp(str + (cc - iMinusLen + 1),
+ (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ bExpSign = TRUE;
+ cc -= iMinusLen;
+ } else {
+ return FALSE;
+ }
+ }
+ cc--;
+ iExponent = bExpSign ? -iExponent : iExponent;
+ ccf--;
+ } break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ int32_t iSymbolLen = wsSymbol.GetLength();
+ cc -= iSymbolLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ } break;
+ case 'r':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
+ if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'R':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'b':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
+ if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'B':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case '.':
+ case 'V':
+ case 'v':
+ return FALSE;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ int32_t iSysmbolLen = wsSymbol.GetLength();
+ cc -= iSysmbolLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSysmbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ bHavePercentSymbol = TRUE;
+ } break;
+ case '8':
+ return FALSE;
+ case ',': {
+ if (cc >= 0) {
+ cc -= iGroupLen - 1;
+ if (cc >= 0 &&
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol,
+ iGroupLen) == 0) {
+ cc--;
+ } else {
+ cc += iGroupLen - 1;
+ }
+ }
+ ccf--;
+ } break;
+ case '(':
+ if (str[cc] == L'(') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ case ')':
+ if (str[cc] == L')') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ default:
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ }
+ }
+ if (cc >= 0) {
+ return FALSE;
+ }
+ if (!bReverseParse) {
+ ccf = dot_index_f + 1;
+ cc = (dot_index == len) ? len : dot_index + 1;
+ coeff = 0.1;
+ while (cc < len && ccf < lenf) {
+ switch (strf[ccf]) {
+ case '\'': {
+ CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
+ int32_t iLiteralLen = wsLiteral.GetLength();
+ if (cc + iLiteralLen > len ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral,
+ iLiteralLen)) {
+ return FALSE;
+ }
+ cc += iLiteralLen;
+ ccf++;
+ break;
+ }
+ case '9':
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ {
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 0.1;
+ }
+ cc++;
+ ccf++;
+ break;
+ case 'z':
+ if (FX_IsDigit(str[cc])) {
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 0.1;
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'Z':
+ if (str[cc] != ' ') {
+ if (FX_IsDigit(str[cc])) {
+ dbRetValue = dbRetValue + (str[cc] - '0') * coeff;
+ coeff *= 0.1;
+ cc++;
+ }
+ } else {
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'S':
+ if (str[cc] == '+' || str[cc] == ' ') {
+ cc++;
+ } else {
+ if (cc + iMinusLen > len ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ bNeg = TRUE;
+ cc += iMinusLen;
+ }
+ ccf++;
+ break;
+ case 's':
+ if (str[cc] == '+') {
+ cc++;
+ } else {
+ if (cc + iMinusLen > len ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ bNeg = TRUE;
+ cc += iMinusLen;
+ }
+ ccf++;
+ break;
+ case 'E': {
+ if (cc >= len || (str[cc] != 'E' && str[cc] != 'e')) {
+ return FALSE;
+ }
+ FX_BOOL bExpSign = FALSE;
+ cc++;
+ if (cc < len) {
+ if (str[cc] == '+') {
+ cc++;
+ } else if (str[cc] == '-') {
+ bExpSign = TRUE;
+ cc++;
+ }
+ }
+ while (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ break;
+ }
+ iExponent = iExponent * 10 + str[cc] - '0';
+ cc++;
+ }
+ iExponent = bExpSign ? -iExponent : iExponent;
+ ccf++;
+ } break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol,
+ wsSymbol);
+ int32_t iSymbolLen = wsSymbol.GetLength();
+ if (cc + iSymbolLen > len ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) {
+ return FALSE;
+ }
+ cc += iSymbolLen;
+ ccf++;
+ } break;
+ case 'c':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
+ if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'C':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'd':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
+ if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'D':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case '.':
+ case 'V':
+ case 'v':
+ return FALSE;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ int32_t iSysmbolLen = wsSymbol.GetLength();
+ if (cc + iSysmbolLen <= len &&
+ !FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol,
+ iSysmbolLen)) {
+ cc += iSysmbolLen;
+ }
+ ccf++;
+ bHavePercentSymbol = TRUE;
+ } break;
+ case '8': {
+ while (ccf < lenf && strf[ccf] == '8') {
+ ccf++;
+ }
+ while (cc < len && FX_IsDigit(str[cc])) {
+ dbRetValue = (str[cc] - '0') * coeff + dbRetValue;
+ coeff *= 0.1;
+ cc++;
+ }
+ } break;
+ case ',': {
+ if (cc + iGroupLen <= len &&
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol,
+ iGroupLen) == 0) {
+ cc += iGroupLen;
+ }
+ ccf++;
+ } break;
+ case '(':
+ if (str[cc] == L'(') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ break;
+ case ')':
+ if (str[cc] == L')') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ break;
+ default:
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ }
+ }
+ if (cc != len) {
+ return FALSE;
+ }
+ }
+ if (iExponent) {
+ dbRetValue *= FXSYS_pow(10, (FX_FLOAT)iExponent);
+ }
+ if (bHavePercentSymbol) {
+ dbRetValue /= 100.0;
+ }
+ if (bNeg) {
+ dbRetValue = -dbRetValue;
+ }
+ fValue = (FX_FLOAT)dbRetValue;
+ return TRUE;
+}
+void FX_ParseNumString(const CFX_WideString& wsNum, CFX_WideString& wsResult) {
+ int32_t iCount = wsNum.GetLength();
+ const FX_WCHAR* pStr = (const FX_WCHAR*)wsNum;
+ FX_WCHAR* pDst = wsResult.GetBuffer(iCount);
+ int32_t nIndex = 0;
+ FX_BOOL bMinus = FALSE;
+ int32_t i = 0;
+ for (i = 0; i < iCount; i++) {
+ FX_WCHAR wc = pStr[i];
+ if (wc == '.') {
+ break;
+ }
+ if ((wc == L'0' || wc == L' ' || wc == '+') && nIndex == 0) {
+ continue;
+ }
+ if (wc == '-') {
+ pDst[nIndex++] = wc;
+ bMinus = TRUE;
+ continue;
+ }
+ if (wc == L'0' && nIndex == 1 && bMinus) {
+ continue;
+ }
+ pDst[nIndex++] = wc;
+ }
+ if (bMinus && nIndex == 1) {
+ pDst[nIndex++] = '0';
+ }
+ if (nIndex == 0) {
+ wsResult.ReleaseBuffer(0);
+ pDst = wsResult.GetBuffer(iCount + 1);
+ pDst[nIndex++] = '0';
+ }
+ int32_t j = 0;
+ for (j = iCount - 1; j > i; j--) {
+ FX_WCHAR wc = pStr[j];
+ if (wc != L'0' && wc != L' ') {
+ break;
+ }
+ }
+ if (j > i) {
+ pDst[nIndex++] = '.';
+ FXSYS_wcsncpy(pDst + nIndex, pStr + i + 1, j - i);
+ nIndex += j - i;
+ }
+ wsResult.ReleaseBuffer(nIndex);
+}
+FX_BOOL CFX_FormatString::ParseNum(const CFX_WideString& wsSrcNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsValue) {
+ wsValue.Empty();
+ if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ int32_t dot_index_f = -1;
+ FX_DWORD dwFormatStyle = 0;
+ CFX_WideString wsNumFormat;
+ IFX_Locale* pLocale =
+ GetNumericFormat(wsPattern, dot_index_f, dwFormatStyle, wsNumFormat);
+ if (!pLocale || wsNumFormat.IsEmpty()) {
+ return FALSE;
+ }
+ int32_t iExponent = 0;
+ CFX_WideString wsDotSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
+ CFX_WideString wsGroupSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
+ int32_t iGroupLen = wsGroupSymbol.GetLength();
+ CFX_WideString wsMinus;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinus);
+ int32_t iMinusLen = wsMinus.GetLength();
+ int cc = 0, ccf = 0;
+ const FX_WCHAR* str = (const FX_WCHAR*)wsSrcNum;
+ int len = wsSrcNum.GetLength();
+ const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat;
+ int lenf = wsNumFormat.GetLength();
+ FX_BOOL bHavePercentSymbol = FALSE;
+ FX_BOOL bNeg = FALSE;
+ FX_BOOL bReverseParse = FALSE;
+ int32_t dot_index = 0;
+ if (!FX_GetNumericDotIndex(wsSrcNum, wsDotSymbol, dot_index) &&
+ (dwFormatStyle & FX_NUMSTYLE_DotVorv)) {
+ bReverseParse = TRUE;
+ }
+ bReverseParse = FALSE;
+ ccf = dot_index_f - 1;
+ cc = dot_index - 1;
+ while (ccf >= 0 && cc >= 0) {
+ switch (strf[ccf]) {
+ case '\'': {
+ CFX_WideString wsLiteral = FX_GetLiteralTextReverse(strf, ccf);
+ int32_t iLiteralLen = wsLiteral.GetLength();
+ cc -= iLiteralLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ }
+ case '9':
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wsValue = CFX_WideStringC(str[cc]) + wsValue;
+ cc--;
+ ccf--;
+ break;
+ case 'z':
+ if (FX_IsDigit(str[cc])) {
+ wsValue = CFX_WideStringC(str[cc]) + wsValue;
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'Z':
+ if (str[cc] != ' ') {
+ if (FX_IsDigit(str[cc])) {
+ wsValue = CFX_WideStringC(str[cc]) + wsValue;
+ cc--;
+ }
+ } else {
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'S':
+ if (str[cc] == '+' || str[cc] == ' ') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 's':
+ if (str[cc] == '+') {
+ cc--;
+ } else {
+ cc -= iMinusLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ cc--;
+ bNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 'E': {
+ if (cc >= dot_index) {
+ return FALSE;
+ }
+ FX_BOOL bExpSign = FALSE;
+ while (cc >= 0) {
+ if (str[cc] == 'E' || str[cc] == 'e') {
+ break;
+ }
+ if (FX_IsDigit(str[cc])) {
+ iExponent = iExponent + (str[cc] - '0') * 10;
+ cc--;
+ continue;
+ } else if (str[cc] == '+') {
+ cc--;
+ continue;
+ } else if (cc - iMinusLen + 1 > 0 &&
+ !FXSYS_wcsncmp(str + (cc - iMinusLen + 1),
+ (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ bExpSign = TRUE;
+ cc -= iMinusLen;
+ } else {
+ return FALSE;
+ }
+ }
+ cc--;
+ iExponent = bExpSign ? -iExponent : iExponent;
+ ccf--;
+ } break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ int32_t iSymbolLen = wsSymbol.GetLength();
+ cc -= iSymbolLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ } break;
+ case 'r':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
+ if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'R':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'R' && cc - 1 >= 0 && str[cc - 1] == 'C') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'b':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
+ if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case 'B':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'B' && cc - 1 >= 0 && str[cc - 1] == 'D') {
+ bNeg = TRUE;
+ cc -= 2;
+ }
+ ccf -= 2;
+ } else {
+ ccf--;
+ }
+ break;
+ case '.':
+ case 'V':
+ case 'v':
+ return FALSE;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ int32_t iSysmbolLen = wsSymbol.GetLength();
+ cc -= iSysmbolLen - 1;
+ if (cc < 0 ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSysmbolLen)) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ bHavePercentSymbol = TRUE;
+ } break;
+ case '8':
+ return FALSE;
+ case ',': {
+ if (cc >= 0) {
+ cc -= iGroupLen - 1;
+ if (cc >= 0 &&
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol,
+ iGroupLen) == 0) {
+ cc--;
+ } else {
+ cc += iGroupLen - 1;
+ }
+ }
+ ccf--;
+ } break;
+ case '(':
+ if (str[cc] == L'(') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ case ')':
+ if (str[cc] == L')') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ break;
+ default:
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc--;
+ ccf--;
+ }
+ }
+ if (cc >= 0) {
+ if (str[cc] == '-') {
+ bNeg = TRUE;
+ cc--;
+ }
+ if (cc >= 0) {
+ return FALSE;
+ }
+ }
+ if (dot_index < len && (dwFormatStyle & FX_NUMSTYLE_DotVorv)) {
+ wsValue += '.';
+ }
+ if (!bReverseParse) {
+ ccf = dot_index_f + 1;
+ cc = (dot_index == len) ? len : dot_index + 1;
+ while (cc < len && ccf < lenf) {
+ switch (strf[ccf]) {
+ case '\'': {
+ CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
+ int32_t iLiteralLen = wsLiteral.GetLength();
+ if (cc + iLiteralLen > len ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral,
+ iLiteralLen)) {
+ return FALSE;
+ }
+ cc += iLiteralLen;
+ ccf++;
+ break;
+ }
+ case '9':
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ { wsValue += str[cc]; }
+ cc++;
+ ccf++;
+ break;
+ case 'z':
+ if (FX_IsDigit(str[cc])) {
+ wsValue += str[cc];
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'Z':
+ if (str[cc] != ' ') {
+ if (FX_IsDigit(str[cc])) {
+ wsValue += str[cc];
+ cc++;
+ }
+ } else {
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'S':
+ if (str[cc] == '+' || str[cc] == ' ') {
+ cc++;
+ } else {
+ if (cc + iMinusLen > len ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ bNeg = TRUE;
+ cc += iMinusLen;
+ }
+ ccf++;
+ break;
+ case 's':
+ if (str[cc] == '+') {
+ cc++;
+ } else {
+ if (cc + iMinusLen > len ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsMinus, iMinusLen)) {
+ return FALSE;
+ }
+ bNeg = TRUE;
+ cc += iMinusLen;
+ }
+ ccf++;
+ break;
+ case 'E': {
+ if (cc >= len || (str[cc] != 'E' && str[cc] != 'e')) {
+ return FALSE;
+ }
+ FX_BOOL bExpSign = FALSE;
+ cc++;
+ if (cc < len) {
+ if (str[cc] == '+') {
+ cc++;
+ } else if (str[cc] == '-') {
+ bExpSign = TRUE;
+ cc++;
+ }
+ }
+ while (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ break;
+ }
+ iExponent = iExponent * 10 + str[cc] - '0';
+ cc++;
+ }
+ iExponent = bExpSign ? -iExponent : iExponent;
+ ccf++;
+ } break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol,
+ wsSymbol);
+ int32_t iSymbolLen = wsSymbol.GetLength();
+ if (cc + iSymbolLen > len ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol, iSymbolLen)) {
+ return FALSE;
+ }
+ cc += iSymbolLen;
+ ccf++;
+ } break;
+ case 'c':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
+ if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'C':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'C' && cc + 1 < len && str[cc + 1] == 'R') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'd':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
+ if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case 'D':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
+ if (str[cc] == ' ') {
+ cc++;
+ } else if (str[cc] == 'D' && cc + 1 < len && str[cc + 1] == 'B') {
+ bNeg = TRUE;
+ cc += 2;
+ }
+ ccf += 2;
+ }
+ break;
+ case '.':
+ case 'V':
+ case 'v':
+ return FALSE;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ int32_t iSysmbolLen = wsSymbol.GetLength();
+ if (cc + iSysmbolLen <= len &&
+ !FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsSymbol,
+ iSysmbolLen)) {
+ cc += iSysmbolLen;
+ }
+ ccf++;
+ bHavePercentSymbol = TRUE;
+ } break;
+ case '8': {
+ while (ccf < lenf && strf[ccf] == '8') {
+ ccf++;
+ }
+ while (cc < len && FX_IsDigit(str[cc])) {
+ wsValue += str[cc];
+ cc++;
+ }
+ } break;
+ case ',': {
+ if (cc + iGroupLen <= len &&
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsGroupSymbol,
+ iGroupLen) == 0) {
+ cc += iGroupLen;
+ }
+ ccf++;
+ } break;
+ case '(':
+ if (str[cc] == L'(') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ break;
+ case ')':
+ if (str[cc] == L')') {
+ bNeg = TRUE;
+ } else if (str[cc] != L' ') {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ break;
+ default:
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ }
+ }
+ if (cc != len) {
+ return FALSE;
+ }
+ }
+ if (iExponent || bHavePercentSymbol) {
+ CFX_Decimal decimal = CFX_Decimal(wsValue);
+ if (iExponent) {
+ decimal = decimal * CFX_Decimal(FXSYS_pow(10, (FX_FLOAT)iExponent));
+ }
+ if (bHavePercentSymbol) {
+ decimal = decimal / CFX_Decimal(100);
+ }
+ wsValue = decimal;
+ }
+ if (bNeg) {
+ wsValue = CFX_WideStringC('-') + wsValue;
+ }
+ return TRUE;
+}
+FX_DATETIMETYPE CFX_FormatString::GetDateTimeFormat(
+ const CFX_WideString& wsPattern,
+ IFX_Locale*& pLocale,
+ CFX_WideString& wsDatePattern,
+ CFX_WideString& wsTimePattern) {
+ pLocale = NULL;
+ CFX_WideString wsTempPattern;
+ FX_LOCALECATEGORY eCategory = FX_LOCALECATEGORY_Unknown;
+ int32_t ccf = 0;
+ int32_t iLenf = wsPattern.GetLength();
+ const FX_WCHAR* pStr = (const FX_WCHAR*)wsPattern;
+ int32_t iFindCategory = 0;
+ FX_BOOL bBraceOpen = FALSE;
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '\'') {
+ int32_t iCurChar = ccf;
+ FX_GetLiteralText(pStr, ccf, iLenf);
+ wsTempPattern += CFX_WideStringC(pStr + iCurChar, ccf - iCurChar + 1);
+ } else if (!bBraceOpen && iFindCategory != 3 &&
+ FX_Local_Find(gs_wsConstChars, pStr[ccf]) < 0) {
+ CFX_WideString wsCategory(pStr[ccf]);
+ ccf++;
+ while (ccf < iLenf && pStr[ccf] != '{' && pStr[ccf] != '.' &&
+ pStr[ccf] != '(') {
+ if (pStr[ccf] == 'T') {
+ wsDatePattern = wsPattern.Left(ccf);
+ wsTimePattern = wsPattern.Right(wsPattern.GetLength() - ccf);
+ wsTimePattern.SetAt(0, ' ');
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ return FX_DATETIMETYPE_DateTime;
+ }
+ wsCategory += pStr[ccf];
+ ccf++;
+ }
+ if (!(iFindCategory & 1) && wsCategory == FX_WSTRC(L"date")) {
+ iFindCategory |= 1;
+ eCategory = FX_LOCALECATEGORY_Date;
+ if (iFindCategory & 2) {
+ iFindCategory = 4;
+ }
+ } else if (!(iFindCategory & 2) && wsCategory == FX_WSTRC(L"time")) {
+ iFindCategory |= 2;
+ eCategory = FX_LOCALECATEGORY_Time;
+ } else if (wsCategory == FX_WSTRC(L"datetime")) {
+ iFindCategory = 3;
+ eCategory = FX_LOCALECATEGORY_DateTime;
+ } else {
+ continue;
+ }
+ while (ccf < iLenf) {
+ if (pStr[ccf] == '(') {
+ ccf++;
+ CFX_WideString wsLCID;
+ while (ccf < iLenf && pStr[ccf] != ')') {
+ wsLCID += pStr[ccf++];
+ }
+ pLocale = GetPatternLocale(wsLCID);
+ } else if (pStr[ccf] == '{') {
+ bBraceOpen = TRUE;
+ break;
+ } else if (pStr[ccf] == '.') {
+ CFX_WideString wsSubCategory;
+ ccf++;
+ while (ccf < iLenf && pStr[ccf] != '(' && pStr[ccf] != '{') {
+ wsSubCategory += pStr[ccf++];
+ }
+ FX_DWORD dwSubHash =
+ FX_HashCode_String_GetW(wsSubCategory, wsSubCategory.GetLength());
+ FX_LOCALEDATETIMESUBCATEGORY eSubCategory =
+ FX_LOCALEDATETIMESUBCATEGORY_Medium;
+ for (int32_t i = 0; i < g_iFXLocaleDateTimeSubCatCount; i++) {
+ if (g_FXLocaleDateTimeSubCatData[i].uHash == dwSubHash) {
+ eSubCategory =
+ (FX_LOCALEDATETIMESUBCATEGORY)g_FXLocaleDateTimeSubCatData[i]
+ .eSubCategory;
+ break;
+ }
+ }
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ FXSYS_assert(pLocale != NULL);
+ switch (eCategory) {
+ case FX_LOCALECATEGORY_Date:
+ pLocale->GetDatePattern(eSubCategory, wsDatePattern);
+ wsDatePattern = wsTempPattern + wsDatePattern;
+ break;
+ case FX_LOCALECATEGORY_Time:
+ pLocale->GetTimePattern(eSubCategory, wsTimePattern);
+ wsTimePattern = wsTempPattern + wsTimePattern;
+ break;
+ case FX_LOCALECATEGORY_DateTime:
+ pLocale->GetDatePattern(eSubCategory, wsDatePattern);
+ wsDatePattern = wsTempPattern + wsDatePattern;
+ pLocale->GetTimePattern(eSubCategory, wsTimePattern);
+ break;
+ default:
+ break;
+ }
+ wsTempPattern.Empty();
+ continue;
+ }
+ ccf++;
+ }
+ } else if (pStr[ccf] == '}') {
+ bBraceOpen = FALSE;
+ if (!wsTempPattern.IsEmpty()) {
+ if (eCategory == FX_LOCALECATEGORY_Time) {
+ wsTimePattern = wsTempPattern;
+ } else if (eCategory == FX_LOCALECATEGORY_Date) {
+ wsDatePattern = wsTempPattern;
+ }
+ wsTempPattern.Empty();
+ }
+ } else {
+ wsTempPattern += pStr[ccf];
+ }
+ ccf++;
+ }
+ if (!wsTempPattern.IsEmpty()) {
+ if (eCategory == FX_LOCALECATEGORY_Date) {
+ wsDatePattern += wsTempPattern;
+ } else {
+ wsTimePattern += wsTempPattern;
+ }
+ }
+ if (!pLocale) {
+ pLocale = m_pLocaleMgr->GetDefLocale();
+ }
+ if (!iFindCategory) {
+ wsTimePattern.Empty();
+ wsDatePattern = wsPattern;
+ }
+ return (FX_DATETIMETYPE)iFindCategory;
+}
+static FX_BOOL FX_ParseLocaleDate(const CFX_WideString& wsDate,
+ const CFX_WideString& wsDatePattern,
+ IFX_Locale* pLocale,
+ CFX_Unitime& datetime,
+ int32_t& cc) {
+ int32_t year = 1900;
+ int32_t month = 1;
+ int32_t day = 1;
+ int32_t ccf = 0;
+ const FX_WCHAR* str = (const FX_WCHAR*)wsDate;
+ int32_t len = wsDate.GetLength();
+ const FX_WCHAR* strf = (const FX_WCHAR*)wsDatePattern;
+ int32_t lenf = wsDatePattern.GetLength();
+ while (cc < len && ccf < lenf) {
+ if (strf[ccf] == '\'') {
+ CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
+ int32_t iLiteralLen = wsLiteral.GetLength();
+ if (cc + iLiteralLen > len ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ cc += iLiteralLen;
+ ccf++;
+ continue;
+ } else if (FX_Local_Find(gs_wsDateSymbols, strf[ccf]) < 0) {
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ continue;
+ }
+ FX_DWORD dwSymbolNum = 1;
+ FX_DWORD dwSymbol = strf[ccf++];
+ while (ccf < lenf && strf[ccf] == dwSymbol) {
+ ccf++;
+ dwSymbolNum++;
+ }
+ dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
+ if (dwSymbol == FXBSTR_ID(0, 0, 'D', '1')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ day = str[cc++] - '0';
+ if (cc < len && FX_IsDigit(str[cc])) {
+ day = day * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'D', '2')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ day = str[cc++] - '0';
+ if (cc < len) {
+ day = day * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '1')) {
+ int i = 0;
+ while (cc < len && i < 3 && FX_IsDigit(str[cc])) {
+ cc++;
+ i++;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '3')) {
+ cc += 3;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ month = str[cc++] - '0';
+ if (cc < len && FX_IsDigit(str[cc])) {
+ month = month * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ month = str[cc++] - '0';
+ if (cc < len) {
+ month = month * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '3')) {
+ CFX_WideString wsMonthNameAbbr;
+ FX_WORD i = 0;
+ for (; i < 12; i++) {
+ pLocale->GetMonthName(i, wsMonthNameAbbr, TRUE);
+ if (wsMonthNameAbbr.IsEmpty()) {
+ continue;
+ }
+ if (!FXSYS_wcsncmp((const FX_WCHAR*)wsMonthNameAbbr, str + cc,
+ wsMonthNameAbbr.GetLength())) {
+ break;
+ }
+ }
+ if (i < 12) {
+ cc += wsMonthNameAbbr.GetLength();
+ month = i + 1;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '4')) {
+ CFX_WideString wsMonthName;
+ FX_WORD i = 0;
+ for (; i < 12; i++) {
+ pLocale->GetMonthName(i, wsMonthName, FALSE);
+ if (wsMonthName.IsEmpty()) {
+ continue;
+ }
+ if (!FXSYS_wcsncmp((const FX_WCHAR*)wsMonthName, str + cc,
+ wsMonthName.GetLength())) {
+ break;
+ }
+ }
+ if (i < 12) {
+ cc += wsMonthName.GetLength();
+ month = i + 1;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '1')) {
+ cc += 1;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '3')) {
+ CFX_WideString wsDayNameAbbr;
+ FX_WORD i = 0;
+ for (; i < 7; i++) {
+ pLocale->GetDayName(i, wsDayNameAbbr, TRUE);
+ if (wsDayNameAbbr.IsEmpty()) {
+ continue;
+ }
+ if (!FXSYS_wcsncmp((const FX_WCHAR*)wsDayNameAbbr, str + cc,
+ wsDayNameAbbr.GetLength())) {
+ break;
+ }
+ }
+ if (i < 12) {
+ cc += wsDayNameAbbr.GetLength();
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '4')) {
+ CFX_WideString wsDayName;
+ int32_t i = 0;
+ for (; i < 7; i++) {
+ pLocale->GetDayName(i, wsDayName, FALSE);
+ if (wsDayName == L"") {
+ continue;
+ }
+ if (!FXSYS_wcsncmp((const FX_WCHAR*)wsDayName, str + cc,
+ wsDayName.GetLength())) {
+ break;
+ }
+ }
+ if (i < 12) {
+ cc += wsDayName.GetLength();
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'e', '1')) {
+ cc += 1;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'G', '1')) {
+ cc += 2;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '2')) {
+ if (cc + 2 > len) {
+ return FALSE;
+ }
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ year = str[cc++] - '0';
+ if (cc >= len || !FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ year = year * 10 + str[cc++] - '0';
+ if (year <= 29) {
+ year += 2000;
+ } else {
+ year += 1900;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '4')) {
+ int i = 0;
+ year = 0;
+ if (cc + 4 > len) {
+ return FALSE;
+ }
+ while (i < 4) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ year = year * 10 + str[cc] - '0';
+ cc++;
+ i++;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'w', '1')) {
+ cc += 1;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'W', '2')) {
+ cc += 2;
+ }
+ }
+ if (cc < len) {
+ return FALSE;
+ }
+ CFX_Unitime ut;
+ ut.Set(year, month, day);
+ datetime = datetime + ut;
+ return cc;
+}
+static void FX_ResolveZone(uint8_t& wHour,
+ uint8_t& wMinute,
+ FX_TIMEZONE tzDiff,
+ IFX_Locale* pLocale) {
+ int32_t iMinuteDiff = wHour * 60 + wMinute;
+ FX_TIMEZONE tzLocale;
+ pLocale->GetTimeZone(tzLocale);
+ iMinuteDiff += tzLocale.tzHour * 60 +
+ (tzLocale.tzHour < 0 ? -tzLocale.tzMinute : tzLocale.tzMinute);
+ iMinuteDiff -= tzDiff.tzHour * 60 +
+ (tzDiff.tzHour < 0 ? -tzDiff.tzMinute : tzDiff.tzMinute);
+ while (iMinuteDiff > 1440) {
+ iMinuteDiff -= 1440;
+ }
+ while (iMinuteDiff < 0) {
+ iMinuteDiff += 1440;
+ }
+ wHour = iMinuteDiff / 60;
+ wMinute = iMinuteDiff % 60;
+}
+static FX_BOOL FX_ParseLocaleTime(const CFX_WideString& wsTime,
+ const CFX_WideString& wsTimePattern,
+ IFX_Locale* pLocale,
+ CFX_Unitime& datetime,
+ int32_t& cc) {
+ uint8_t hour = 0;
+ uint8_t minute = 0;
+ uint8_t second = 0;
+ FX_WORD millisecond = 0;
+ int32_t ccf = 0;
+ const FX_WCHAR* str = (const FX_WCHAR*)wsTime;
+ int len = wsTime.GetLength();
+ const FX_WCHAR* strf = (const FX_WCHAR*)wsTimePattern;
+ int lenf = wsTimePattern.GetLength();
+ FX_BOOL bHasA = FALSE;
+ FX_BOOL bPM = FALSE;
+ while (cc < len && ccf < lenf) {
+ if (strf[ccf] == '\'') {
+ CFX_WideString wsLiteral = FX_GetLiteralText(strf, ccf, lenf);
+ int32_t iLiteralLen = wsLiteral.GetLength();
+ if (cc + iLiteralLen > len ||
+ FXSYS_wcsncmp(str + cc, (const FX_WCHAR*)wsLiteral, iLiteralLen)) {
+ return FALSE;
+ }
+ cc += iLiteralLen;
+ ccf++;
+ continue;
+ } else if (FX_Local_Find(gs_wsTimeSymbols, strf[ccf]) == -1) {
+ if (strf[ccf] != str[cc]) {
+ return FALSE;
+ }
+ cc++;
+ ccf++;
+ continue;
+ }
+ FX_DWORD dwSymbolNum = 1;
+ FX_DWORD dwSymbol = strf[ccf++];
+ while (ccf < lenf && strf[ccf] == dwSymbol) {
+ ccf++;
+ dwSymbolNum++;
+ }
+ dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
+ if (dwSymbol == FXBSTR_ID(0, 0, 'k', '1') ||
+ dwSymbol == FXBSTR_ID(0, 0, 'H', '1') ||
+ dwSymbol == FXBSTR_ID(0, 0, 'h', '1') ||
+ dwSymbol == FXBSTR_ID(0, 0, 'K', '1')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ hour = str[cc++] - '0';
+ if (cc < len && FX_IsDigit(str[cc])) {
+ hour = hour * 10 + str[cc++] - '0';
+ }
+ if (dwSymbol == FXBSTR_ID(0, 0, 'K', '1') && hour == 24) {
+ hour = 0;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '2') ||
+ dwSymbol == FXBSTR_ID(0, 0, 'H', '2') ||
+ dwSymbol == FXBSTR_ID(0, 0, 'h', '2') ||
+ dwSymbol == FXBSTR_ID(0, 0, 'K', '2')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ hour = str[cc++] - '0';
+ if (cc >= len) {
+ return FALSE;
+ }
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ hour = hour * 10 + str[cc++] - '0';
+ if (dwSymbol == FXBSTR_ID(0, 0, 'K', '2') && hour == 24) {
+ hour = 0;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ minute = str[cc++] - '0';
+ if (cc < len && FX_IsDigit(str[cc])) {
+ minute = minute * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ minute = str[cc++] - '0';
+ if (cc >= len) {
+ return FALSE;
+ }
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ minute = minute * 10 + str[cc++] - '0';
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '1')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ second = str[cc++] - '0';
+ if (cc < len && FX_IsDigit(str[cc])) {
+ second = second * 10 + str[cc++] - '0';
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '2')) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ second = str[cc++] - '0';
+ if (cc >= len) {
+ return FALSE;
+ }
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ second = second * 10 + str[cc++] - '0';
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'F', '3')) {
+ if (cc + 3 >= len) {
+ return FALSE;
+ }
+ int i = 0;
+ while (i < 3) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ millisecond = millisecond * 10 + str[cc++] - '0';
+ i++;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'A', '1')) {
+ CFX_WideString wsAM;
+ pLocale->GetMeridiemName(wsAM, TRUE);
+ CFX_WideString wsPM;
+ pLocale->GetMeridiemName(wsPM, FALSE);
+ if ((cc + wsAM.GetLength() <= len) &&
+ (CFX_WideStringC(str + cc, wsAM.GetLength()) == wsAM)) {
+ cc += wsAM.GetLength();
+ bHasA = TRUE;
+ } else if ((cc + wsPM.GetLength() <= len) &&
+ (CFX_WideStringC(str + cc, wsPM.GetLength()) == wsPM)) {
+ cc += wsPM.GetLength();
+ bHasA = TRUE;
+ bPM = TRUE;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Z', '1')) {
+ if (cc + 3 > len) {
+ continue;
+ }
+ FX_DWORD dwHash = str[cc++];
+ dwHash = (dwHash << 8) | str[cc++];
+ dwHash = (dwHash << 8) | str[cc++];
+ if (dwHash == FXBSTR_ID(0, 'G', 'M', 'T')) {
+ FX_TIMEZONE tzDiff;
+ tzDiff.tzHour = 0;
+ tzDiff.tzMinute = 0;
+ if (cc < len && (str[cc] == '-' || str[cc] == '+')) {
+ cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff);
+ }
+ FX_ResolveZone(hour, minute, tzDiff, pLocale);
+ } else {
+ const FX_LOCALETIMEZONEINFO* pEnd =
+ g_FXLocaleTimeZoneData + FX_ArraySize(g_FXLocaleTimeZoneData);
+ const FX_LOCALETIMEZONEINFO* pTimeZoneInfo =
+ std::lower_bound(g_FXLocaleTimeZoneData, pEnd, dwHash,
+ [](const FX_LOCALETIMEZONEINFO& info,
+ FX_DWORD hash) { return info.uHash < hash; });
+ if (pTimeZoneInfo < pEnd && dwHash == pTimeZoneInfo->uHash) {
+ hour += pTimeZoneInfo->iHour;
+ minute += pTimeZoneInfo->iHour > 0 ? pTimeZoneInfo->iMinute
+ : -pTimeZoneInfo->iMinute;
+ }
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'z', '1')) {
+ if (str[cc] != 'Z') {
+ FX_TIMEZONE tzDiff;
+ cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff);
+ FX_ResolveZone(hour, minute, tzDiff, pLocale);
+ } else {
+ cc++;
+ }
+ }
+ }
+ if (bHasA) {
+ if (bPM) {
+ hour += 12;
+ if (hour == 24) {
+ hour = 12;
+ }
+ } else {
+ if (hour == 12) {
+ hour = 0;
+ }
+ }
+ }
+ CFX_Unitime ut;
+ ut.Set(0, 0, 0, hour, minute, second, millisecond);
+ datetime = datetime + ut;
+ return cc;
+}
+FX_BOOL CFX_FormatString::ParseDateTime(const CFX_WideString& wsSrcDateTime,
+ const CFX_WideString& wsPattern,
+ FX_DATETIMETYPE eDateTimeType,
+ CFX_Unitime& dtValue) {
+ dtValue.Set(0);
+ if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsDatePattern, wsTimePattern;
+ IFX_Locale* pLocale = NULL;
+ FX_DATETIMETYPE eCategory =
+ GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
+ if (!pLocale) {
+ return FALSE;
+ }
+ if (eCategory == FX_DATETIMETYPE_Unknown) {
+ eCategory = eDateTimeType;
+ }
+ if (eCategory == FX_DATETIMETYPE_Unknown) {
+ return FALSE;
+ }
+ if (eCategory == FX_DATETIMETYPE_TimeDate) {
+ int32_t iStart = 0;
+ if (!FX_ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue,
+ iStart)) {
+ return FALSE;
+ }
+ if (!FX_ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue,
+ iStart)) {
+ return FALSE;
+ }
+ } else {
+ int32_t iStart = 0;
+ if ((eCategory & FX_DATETIMETYPE_Date) &&
+ !FX_ParseLocaleDate(wsSrcDateTime, wsDatePattern, pLocale, dtValue,
+ iStart)) {
+ return FALSE;
+ }
+ if ((eCategory & FX_DATETIMETYPE_Time) &&
+ !FX_ParseLocaleTime(wsSrcDateTime, wsTimePattern, pLocale, dtValue,
+ iStart)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL CFX_FormatString::ParseZero(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern) {
+ CFX_WideString wsTextFormat;
+ GetTextFormat(wsPattern, FX_WSTRC(L"zero"), wsTextFormat);
+ int32_t iText = 0, iPattern = 0;
+ const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText;
+ int32_t iLenText = wsSrcText.GetLength();
+ const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
+ int32_t iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern && iText < iLenText) {
+ if (pStrPattern[iPattern] == '\'') {
+ CFX_WideString wsLiteral =
+ FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ int32_t iLiteralLen = wsLiteral.GetLength();
+ if (iText + iLiteralLen > iLenText ||
+ FXSYS_wcsncmp(pStrText + iText, (const FX_WCHAR*)wsLiteral,
+ iLiteralLen)) {
+ return FALSE;
+ }
+ iText += iLiteralLen;
+ iPattern++;
+ continue;
+ } else if (pStrPattern[iPattern] != pStrText[iText]) {
+ return FALSE;
+ } else {
+ iText++;
+ iPattern++;
+ }
+ }
+ return iPattern == iLenPattern && iText == iLenText;
+}
+FX_BOOL CFX_FormatString::ParseNull(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern) {
+ CFX_WideString wsTextFormat;
+ GetTextFormat(wsPattern, FX_WSTRC(L"null"), wsTextFormat);
+ int32_t iText = 0, iPattern = 0;
+ const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText;
+ int32_t iLenText = wsSrcText.GetLength();
+ const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
+ int32_t iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern && iText < iLenText) {
+ if (pStrPattern[iPattern] == '\'') {
+ CFX_WideString wsLiteral =
+ FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ int32_t iLiteralLen = wsLiteral.GetLength();
+ if (iText + iLiteralLen > iLenText ||
+ FXSYS_wcsncmp(pStrText + iText, (const FX_WCHAR*)wsLiteral,
+ iLiteralLen)) {
+ return FALSE;
+ }
+ iText += iLiteralLen;
+ iPattern++;
+ continue;
+ } else if (pStrPattern[iPattern] != pStrText[iText]) {
+ return FALSE;
+ } else {
+ iText++;
+ iPattern++;
+ }
+ }
+ return iPattern == iLenPattern && iText == iLenText;
+}
+FX_BOOL CFX_FormatString::FormatText(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) {
+ if (wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ int32_t iLenText = wsSrcText.GetLength();
+ if (iLenText == 0) {
+ return FALSE;
+ }
+ CFX_WideString wsTextFormat;
+ GetTextFormat(wsPattern, FX_WSTRC(L"text"), wsTextFormat);
+ int32_t iText = 0, iPattern = 0;
+ const FX_WCHAR* pStrText = (const FX_WCHAR*)wsSrcText;
+ const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
+ int32_t iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern) {
+ switch (pStrPattern[iPattern]) {
+ case '\'': {
+ wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ iPattern++;
+ break;
+ }
+ case 'A':
+ if (iText >= iLenText || !FX_IsAlpha(pStrText[iText])) {
+ return FALSE;
+ }
+ wsOutput += pStrText[iText++];
+ iPattern++;
+ break;
+ case 'X':
+ if (iText >= iLenText) {
+ return FALSE;
+ }
+ wsOutput += pStrText[iText++];
+ iPattern++;
+ break;
+ case 'O':
+ case '0':
+ if (iText >= iLenText ||
+ (!FX_IsDigit(pStrText[iText]) && !FX_IsAlpha(pStrText[iText]))) {
+ return FALSE;
+ }
+ wsOutput += pStrText[iText++];
+ iPattern++;
+ break;
+ case '9':
+ if (iText >= iLenText || !FX_IsDigit(pStrText[iText])) {
+ return FALSE;
+ }
+ wsOutput += pStrText[iText++];
+ iPattern++;
+ break;
+ default:
+ wsOutput += pStrPattern[iPattern++];
+ break;
+ }
+ }
+ return iText == iLenText;
+}
+static int32_t FX_GetNumTrailingLimit(const CFX_WideString& wsFormat,
+ int iDotPos,
+ FX_BOOL& bTrimTailZeros) {
+ if (iDotPos < 0) {
+ return 0;
+ }
+ int32_t iCount = wsFormat.GetLength();
+ int32_t iTreading = 0;
+ for (iDotPos++; iDotPos < iCount; iDotPos++) {
+ FX_WCHAR wc = wsFormat[iDotPos];
+ if (wc == L'z' || wc == L'9' || wc == 'Z') {
+ iTreading++;
+ bTrimTailZeros = (wc == L'9' ? FALSE : TRUE);
+ }
+ }
+ return iTreading;
+}
+FX_BOOL CFX_FormatString::FormatStrNum(const CFX_WideStringC& wsInputNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) {
+ if (wsInputNum.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ int32_t dot_index_f = -1;
+ FX_DWORD dwNumStyle = 0;
+ CFX_WideString wsNumFormat;
+ IFX_Locale* pLocale =
+ GetNumericFormat(wsPattern, dot_index_f, dwNumStyle, wsNumFormat);
+ if (!pLocale || wsNumFormat.IsEmpty()) {
+ return FALSE;
+ }
+ int32_t cc = 0, ccf = 0;
+ const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat;
+ int lenf = wsNumFormat.GetLength();
+ CFX_WideString wsSrcNum = wsInputNum;
+ wsSrcNum.TrimLeft('0');
+ if (wsSrcNum.IsEmpty() || wsSrcNum[0] == '.') {
+ wsSrcNum.Insert(0, '0');
+ }
+ CFX_Decimal decimal = CFX_Decimal(wsSrcNum);
+ if (dwNumStyle & FX_NUMSTYLE_Percent) {
+ decimal = decimal * CFX_Decimal(100);
+ wsSrcNum = decimal;
+ }
+ int32_t exponent = 0;
+ if (dwNumStyle & FX_NUMSTYLE_Exponent) {
+ int fixed_count = 0;
+ while (ccf < dot_index_f) {
+ switch (strf[ccf]) {
+ case '\'':
+ FX_GetLiteralText(strf, ccf, dot_index_f);
+ break;
+ case '9':
+ case 'z':
+ case 'Z':
+ fixed_count++;
+ break;
+ }
+ ccf++;
+ }
+ int threshold = 1;
+ while (fixed_count > 1) {
+ threshold *= 10;
+ fixed_count--;
+ }
+ if (decimal != CFX_Decimal(0)) {
+ if (decimal < CFX_Decimal(threshold)) {
+ decimal = decimal * CFX_Decimal(10);
+ exponent = -1;
+ while (decimal < CFX_Decimal(threshold)) {
+ decimal = decimal * CFX_Decimal(10);
+ exponent -= 1;
+ }
+ } else if (decimal > CFX_Decimal(threshold)) {
+ threshold *= 10;
+ while (decimal > CFX_Decimal(threshold)) {
+ decimal = decimal / CFX_Decimal(10);
+ exponent += 1;
+ }
+ }
+ }
+ }
+ FX_BOOL bTrimTailZeros = FALSE;
+ int32_t iTreading =
+ FX_GetNumTrailingLimit(wsNumFormat, dot_index_f, bTrimTailZeros);
+ int32_t scale = decimal.GetScale();
+ if (iTreading < scale) {
+ decimal.SetScale(iTreading);
+ wsSrcNum = decimal;
+ }
+ if (bTrimTailZeros && scale > 0 && iTreading > 0) {
+ wsSrcNum.TrimRight(L"0");
+ wsSrcNum.TrimRight(L".");
+ }
+ CFX_WideString wsGroupSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
+ FX_BOOL bNeg = FALSE;
+ if (wsSrcNum[0] == '-') {
+ bNeg = TRUE;
+ wsSrcNum.Delete(0, 1);
+ }
+ FX_BOOL bAddNeg = FALSE;
+ const FX_WCHAR* str = (const FX_WCHAR*)wsSrcNum;
+ int len = wsSrcNum.GetLength();
+ int dot_index = wsSrcNum.Find('.');
+ if (dot_index == -1) {
+ dot_index = len;
+ }
+ ccf = dot_index_f - 1;
+ cc = dot_index - 1;
+ while (ccf >= 0) {
+ switch (strf[ccf]) {
+ case '9':
+ if (cc >= 0) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ cc--;
+ } else {
+ wsOutput = CFX_WideStringC(L'0') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'z':
+ if (cc >= 0) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ if (str[0] != '0') {
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ }
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'Z':
+ if (cc >= 0) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ if (str[0] == '0') {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ } else {
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ }
+ cc--;
+ } else {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'S':
+ if (bNeg) {
+ CFX_WideString wsMinusSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
+ wsOutput = wsMinusSymbol + wsOutput;
+ bAddNeg = TRUE;
+ } else {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 's':
+ if (bNeg) {
+ CFX_WideString wsMinusSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
+ wsOutput = wsMinusSymbol + wsOutput;
+ bAddNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 'E': {
+ CFX_WideString wsExp;
+ wsExp.Format(L"E%+d", exponent);
+ wsOutput = wsExp + wsOutput;
+ }
+ ccf--;
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ wsOutput = wsSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'r':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
+ if (bNeg) {
+ wsOutput = L"CR" + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'R':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
+ if (bNeg) {
+ wsOutput = L"CR" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'b':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
+ if (bNeg) {
+ wsOutput = L"db" + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'B':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
+ if (bNeg) {
+ wsOutput = L"DB" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ wsOutput = wsSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case ',':
+ if (cc >= 0) {
+ wsOutput = wsGroupSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case '(':
+ if (bNeg) {
+ wsOutput = L"(" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ bAddNeg = TRUE;
+ ccf--;
+ break;
+ case ')':
+ if (bNeg) {
+ wsOutput = L")" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf--;
+ break;
+ case '\'':
+ wsOutput = FX_GetLiteralTextReverse(strf, ccf) + wsOutput;
+ ccf--;
+ break;
+ default:
+ wsOutput = CFX_WideStringC(strf[ccf]) + wsOutput;
+ ccf--;
+ }
+ }
+ if (cc >= 0) {
+ int nPos = dot_index % 3;
+ wsOutput.Empty();
+ for (int32_t i = 0; i < dot_index; i++) {
+ if (i % 3 == nPos && i != 0) {
+ wsOutput += wsGroupSymbol;
+ }
+ wsOutput += wsSrcNum[i];
+ }
+ if (dot_index < len) {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsSymbol);
+ wsOutput += wsSymbol;
+ wsOutput += wsSrcNum.Right(len - dot_index - 1);
+ }
+ if (bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput = wsMinusymbol + wsOutput;
+ }
+ return FALSE;
+ }
+ if (dot_index_f == wsNumFormat.GetLength()) {
+ if (!bAddNeg && bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput = wsMinusymbol + wsOutput;
+ }
+ return TRUE;
+ }
+ CFX_WideString wsDotSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
+ if (strf[dot_index_f] == 'V') {
+ wsOutput += wsDotSymbol;
+ } else if (strf[dot_index_f] == '.') {
+ if (dot_index < len) {
+ wsOutput += wsDotSymbol;
+ } else {
+ if (strf[dot_index_f + 1] == '9' || strf[dot_index_f + 1] == 'Z') {
+ wsOutput += wsDotSymbol;
+ }
+ }
+ }
+ ccf = dot_index_f + 1;
+ cc = dot_index + 1;
+ while (ccf < lenf) {
+ switch (strf[ccf]) {
+ case '\'':
+ wsOutput += FX_GetLiteralText(strf, ccf, lenf);
+ ccf++;
+ break;
+ case '9':
+ if (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wsOutput += str[cc];
+ cc++;
+ } else {
+ wsOutput += L'0';
+ }
+ ccf++;
+ break;
+ case 'z':
+ if (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wsOutput += str[cc];
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'Z':
+ if (cc < len) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wsOutput += str[cc];
+ cc++;
+ } else {
+ wsOutput += L'0';
+ }
+ ccf++;
+ break;
+ case 'E': {
+ CFX_WideString wsExp;
+ wsExp.Format(L"E%+d", exponent);
+ wsOutput += wsExp;
+ }
+ ccf++;
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ wsOutput += wsSymbol;
+ }
+ ccf++;
+ break;
+ case 'c':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
+ if (bNeg) {
+ wsOutput += L"CR";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'C':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
+ if (bNeg) {
+ wsOutput += L"CR";
+ } else {
+ wsOutput += L" ";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'd':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
+ if (bNeg) {
+ wsOutput += L"db";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'D':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
+ if (bNeg) {
+ wsOutput += L"DB";
+ } else {
+ wsOutput += L" ";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ wsOutput += wsSymbol;
+ }
+ ccf++;
+ break;
+ case '8': {
+ while (ccf < lenf && strf[ccf] == '8') {
+ ccf++;
+ }
+ while (cc < len && FX_IsDigit(str[cc])) {
+ wsOutput += str[cc];
+ cc++;
+ }
+ } break;
+ case ',':
+ wsOutput += wsGroupSymbol;
+ ccf++;
+ break;
+ case '(':
+ if (bNeg) {
+ wsOutput += '(';
+ } else {
+ wsOutput += ' ';
+ }
+ bAddNeg = TRUE;
+ ccf++;
+ break;
+ case ')':
+ if (bNeg) {
+ wsOutput += ')';
+ } else {
+ wsOutput += ' ';
+ }
+ ccf++;
+ break;
+ default:
+ ccf++;
+ }
+ }
+ if (!bAddNeg && bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput =
+ wsMinusymbol + wsOutput[0] + wsOutput.Mid(1, wsOutput.GetLength() - 1);
+ }
+ return TRUE;
+}
+FX_BOOL CFX_FormatString::FormatLCNumeric(CFX_LCNumeric& lcNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) {
+ int32_t dot_index_f = -1;
+ FX_DWORD dwNumStyle = 0;
+ CFX_WideString wsNumFormat;
+ IFX_Locale* pLocale =
+ GetNumericFormat(wsPattern, dot_index_f, dwNumStyle, wsNumFormat);
+ if (!pLocale || wsNumFormat.IsEmpty()) {
+ return FALSE;
+ }
+ int32_t cc = 0, ccf = 0;
+ const FX_WCHAR* strf = (const FX_WCHAR*)wsNumFormat;
+ int lenf = wsNumFormat.GetLength();
+ double dbOrgRaw = lcNum.GetDouble();
+ double dbRetValue = dbOrgRaw;
+ if (dwNumStyle & FX_NUMSTYLE_Percent) {
+ dbRetValue *= 100;
+ }
+ int32_t exponent = 0;
+ if (dwNumStyle & FX_NUMSTYLE_Exponent) {
+ int fixed_count = 0;
+ while (ccf < dot_index_f) {
+ switch (strf[ccf]) {
+ case '\'':
+ FX_GetLiteralText(strf, ccf, dot_index_f);
+ break;
+ case '9':
+ case 'z':
+ case 'Z':
+ fixed_count++;
+ break;
+ }
+ ccf++;
+ }
+ int threshold = 1;
+ while (fixed_count > 1) {
+ threshold *= 10;
+ fixed_count--;
+ }
+ if (dbRetValue != 0) {
+ if (dbRetValue < threshold) {
+ dbRetValue *= 10;
+ exponent = -1;
+ while (dbRetValue < threshold) {
+ dbRetValue *= 10;
+ exponent -= 1;
+ }
+ } else if (dbRetValue > threshold) {
+ threshold *= 10;
+ while (dbRetValue > threshold) {
+ dbRetValue /= 10;
+ exponent += 1;
+ }
+ }
+ }
+ }
+ if (dwNumStyle & (FX_NUMSTYLE_Percent | FX_NUMSTYLE_Exponent)) {
+ lcNum = CFX_LCNumeric(dbRetValue);
+ }
+ FX_BOOL bTrimTailZeros = FALSE;
+ int32_t iTreading =
+ FX_GetNumTrailingLimit(wsNumFormat, dot_index_f, bTrimTailZeros);
+ CFX_WideString wsNumeric = lcNum.ToString(iTreading, bTrimTailZeros);
+ if (wsNumeric.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsGroupSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Grouping, wsGroupSymbol);
+ FX_BOOL bNeg = FALSE;
+ if (wsNumeric[0] == '-') {
+ bNeg = TRUE;
+ wsNumeric.Delete(0, 1);
+ }
+ FX_BOOL bAddNeg = FALSE;
+ const FX_WCHAR* str = (const FX_WCHAR*)wsNumeric;
+ int len = wsNumeric.GetLength();
+ int dot_index = wsNumeric.Find('.');
+ if (dot_index == -1) {
+ dot_index = len;
+ }
+ ccf = dot_index_f - 1;
+ cc = dot_index - 1;
+ while (ccf >= 0) {
+ switch (strf[ccf]) {
+ case '9':
+ if (cc >= 0) {
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ cc--;
+ } else {
+ wsOutput = CFX_WideStringC(L'0') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'z':
+ if (cc >= 0) {
+ if (lcNum.m_Integral != 0) {
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ }
+ cc--;
+ }
+ ccf--;
+ break;
+ case 'Z':
+ if (cc >= 0) {
+ if (lcNum.m_Integral == 0) {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ } else {
+ wsOutput = CFX_WideStringC(str[cc]) + wsOutput;
+ }
+ cc--;
+ } else {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'S':
+ if (bNeg) {
+ CFX_WideString wsMinusSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
+ wsOutput = wsMinusSymbol + wsOutput;
+ bAddNeg = TRUE;
+ } else {
+ wsOutput = CFX_WideStringC(L' ') + wsOutput;
+ }
+ ccf--;
+ break;
+ case 's':
+ if (bNeg) {
+ CFX_WideString wsMinusSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusSymbol);
+ wsOutput = wsMinusSymbol + wsOutput;
+ bAddNeg = TRUE;
+ }
+ ccf--;
+ break;
+ case 'E': {
+ CFX_WideString wsExp;
+ wsExp.Format(L"E%+d", exponent);
+ wsOutput = wsExp + wsOutput;
+ }
+ ccf--;
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ wsOutput = wsSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case 'r':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'c') {
+ if (bNeg) {
+ wsOutput = L"CR" + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'R':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'C') {
+ if (bNeg) {
+ wsOutput = L"CR" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'b':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'd') {
+ if (bNeg) {
+ wsOutput = L"db" + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'B':
+ if (ccf - 1 >= 0 && strf[ccf - 1] == 'D') {
+ if (bNeg) {
+ wsOutput = L"DB" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf -= 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ wsOutput = wsSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case ',':
+ if (cc >= 0) {
+ wsOutput = wsGroupSymbol + wsOutput;
+ }
+ ccf--;
+ break;
+ case '(':
+ if (bNeg) {
+ wsOutput = L"(" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ bAddNeg = TRUE;
+ ccf--;
+ break;
+ case ')':
+ if (bNeg) {
+ wsOutput = L")" + wsOutput;
+ } else {
+ wsOutput = L" " + wsOutput;
+ }
+ ccf--;
+ break;
+ case '\'':
+ wsOutput = FX_GetLiteralTextReverse(strf, ccf) + wsOutput;
+ ccf--;
+ break;
+ default:
+ wsOutput = CFX_WideStringC(strf[ccf]) + wsOutput;
+ ccf--;
+ }
+ }
+ if (cc >= 0) {
+ int nPos = dot_index % 3;
+ wsOutput.Empty();
+ for (int32_t i = 0; i < dot_index; i++) {
+ if (i % 3 == nPos && i != 0) {
+ wsOutput += wsGroupSymbol;
+ }
+ wsOutput += wsNumeric[i];
+ }
+ if (dot_index < len) {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsSymbol);
+ wsOutput += wsSymbol;
+ wsOutput += wsNumeric.Right(len - dot_index - 1);
+ }
+ if (bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput = wsMinusymbol + wsOutput;
+ }
+ return FALSE;
+ }
+ if (dot_index_f == wsNumFormat.GetLength()) {
+ if (!bAddNeg && bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput = wsMinusymbol + wsOutput;
+ }
+ return TRUE;
+ }
+ CFX_WideString wsDotSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Decimal, wsDotSymbol);
+ if (strf[dot_index_f] == 'V') {
+ wsOutput += wsDotSymbol;
+ } else if (strf[dot_index_f] == '.') {
+ if (dot_index < len) {
+ wsOutput += wsDotSymbol;
+ } else {
+ if (strf[dot_index_f + 1] == '9' || strf[dot_index_f + 1] == 'Z') {
+ wsOutput += wsDotSymbol;
+ }
+ }
+ }
+ ccf = dot_index_f + 1;
+ cc = dot_index + 1;
+ while (ccf < lenf) {
+ switch (strf[ccf]) {
+ case '\'':
+ wsOutput += FX_GetLiteralText(strf, ccf, lenf);
+ ccf++;
+ break;
+ case '9':
+ if (cc < len) {
+ wsOutput += str[cc];
+ cc++;
+ } else {
+ wsOutput += L'0';
+ }
+ ccf++;
+ break;
+ case 'z':
+ if (cc < len) {
+ wsOutput += str[cc];
+ cc++;
+ }
+ ccf++;
+ break;
+ case 'Z':
+ if (cc < len) {
+ wsOutput += str[cc];
+ cc++;
+ } else {
+ wsOutput += L'0';
+ }
+ ccf++;
+ break;
+ case 'E': {
+ CFX_WideString wsExp;
+ wsExp.Format(L"E%+d", exponent);
+ wsOutput += wsExp;
+ }
+ ccf++;
+ break;
+ case '$': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_CurrencySymbol, wsSymbol);
+ wsOutput += wsSymbol;
+ }
+ ccf++;
+ break;
+ case 'c':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'r') {
+ if (bNeg) {
+ wsOutput += L"CR";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'C':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'R') {
+ if (bNeg) {
+ wsOutput += L"CR";
+ } else {
+ wsOutput += L" ";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'd':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'b') {
+ if (bNeg) {
+ wsOutput += L"db";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case 'D':
+ if (ccf + 1 < lenf && strf[ccf + 1] == 'B') {
+ if (bNeg) {
+ wsOutput += L"DB";
+ } else {
+ wsOutput += L" ";
+ }
+ ccf += 2;
+ bAddNeg = TRUE;
+ }
+ break;
+ case '%': {
+ CFX_WideString wsSymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Percent, wsSymbol);
+ wsOutput += wsSymbol;
+ }
+ ccf++;
+ break;
+ case '8': {
+ while (ccf < lenf && strf[ccf] == '8') {
+ ccf++;
+ }
+ while (cc < len && FX_IsDigit(str[cc])) {
+ wsOutput += str[cc];
+ cc++;
+ }
+ } break;
+ case ',':
+ wsOutput += wsGroupSymbol;
+ ccf++;
+ break;
+ case '(':
+ if (bNeg) {
+ wsOutput += '(';
+ } else {
+ wsOutput += ' ';
+ }
+ bAddNeg = TRUE;
+ ccf++;
+ break;
+ case ')':
+ if (bNeg) {
+ wsOutput += ')';
+ } else {
+ wsOutput += ' ';
+ }
+ ccf++;
+ break;
+ default:
+ ccf++;
+ }
+ }
+ if (!bAddNeg && bNeg) {
+ CFX_WideString wsMinusymbol;
+ pLocale->GetNumbericSymbol(FX_LOCALENUMSYMBOL_Minus, wsMinusymbol);
+ wsOutput =
+ wsOutput[0] + wsMinusymbol + wsOutput.Mid(1, wsOutput.GetLength() - 1);
+ }
+ return TRUE;
+}
+FX_BOOL CFX_FormatString::FormatNum(const CFX_WideString& wsSrcNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) {
+ if (wsSrcNum.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ return FormatStrNum(wsSrcNum, wsPattern, wsOutput);
+}
+FX_BOOL CFX_FormatString::FormatNum(FX_FLOAT fNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) {
+ if (wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_LCNumeric lcNum(fNum);
+ return FormatLCNumeric(lcNum, wsPattern, wsOutput);
+}
+FX_BOOL FX_DateFromCanonical(const CFX_WideString& wsDate,
+ CFX_Unitime& datetime) {
+ int32_t year = 1900;
+ int32_t month = 1;
+ int32_t day = 1;
+ FX_WORD wYear = 0;
+ int cc_start = 0, cc = 0;
+ const FX_WCHAR* str = (const FX_WCHAR*)wsDate;
+ int len = wsDate.GetLength();
+ if (len > 10) {
+ return FALSE;
+ }
+ while (cc < len && cc < 4) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ wYear = wYear * 10 + str[cc++] - '0';
+ }
+ year = wYear;
+ if (cc < 4 || wYear < 1900) {
+ return FALSE;
+ }
+ if (cc < len) {
+ if (str[cc] == '-') {
+ cc++;
+ }
+ cc_start = cc;
+ uint8_t tmpM = 0;
+ while (cc < len && cc < cc_start + 2) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ tmpM = tmpM * 10 + str[cc++] - '0';
+ }
+ month = tmpM;
+ if (cc == cc_start + 1 || tmpM > 12 || tmpM < 1) {
+ return FALSE;
+ }
+ if (cc < len) {
+ if (str[cc] == '-') {
+ cc++;
+ }
+ uint8_t tmpD = 0;
+ cc_start = cc;
+ while (cc < len && cc < cc_start + 2) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ tmpD = tmpD * 10 + str[cc++] - '0';
+ }
+ day = tmpD;
+ if (tmpD < 1) {
+ return FALSE;
+ }
+ if ((tmpM == 1 || tmpM == 3 || tmpM == 5 || tmpM == 7 || tmpM == 8 ||
+ tmpM == 10 || tmpM == 12) &&
+ tmpD > 31) {
+ return FALSE;
+ }
+ if ((tmpM == 4 || tmpM == 6 || tmpM == 9 || tmpM == 11) && tmpD > 30) {
+ return FALSE;
+ }
+ FX_BOOL iLeapYear;
+ if ((wYear % 4 == 0 && wYear % 100 != 0) || wYear % 400 == 0) {
+ iLeapYear = TRUE;
+ } else {
+ iLeapYear = FALSE;
+ }
+ if ((iLeapYear && tmpM == 2 && tmpD > 29) ||
+ (!iLeapYear && tmpM == 2 && tmpD > 28)) {
+ return FALSE;
+ }
+ }
+ }
+ CFX_Unitime ut;
+ ut.Set(year, month, day);
+ datetime = datetime + ut;
+ return TRUE;
+}
+FX_BOOL FX_TimeFromCanonical(const CFX_WideStringC& wsTime,
+ CFX_Unitime& datetime,
+ IFX_Locale* pLocale) {
+ if (wsTime.GetLength() == 0) {
+ return FALSE;
+ }
+ uint8_t hour = 0;
+ uint8_t minute = 0;
+ uint8_t second = 0;
+ FX_WORD millisecond = 0;
+ int cc_start = 0, cc = cc_start;
+ const FX_WCHAR* str = (const FX_WCHAR*)wsTime.GetPtr();
+ int len = wsTime.GetLength();
+ while (cc < len && cc < 2) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ hour = hour * 10 + str[cc++] - '0';
+ }
+ if (cc < 2 || hour >= 24) {
+ return FALSE;
+ }
+ if (cc < len) {
+ if (str[cc] == ':') {
+ cc++;
+ }
+ cc_start = cc;
+ while (cc < len && cc < cc_start + 2) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ minute = minute * 10 + str[cc++] - '0';
+ }
+ if (cc == cc_start + 1 || minute >= 60) {
+ return FALSE;
+ }
+ if (cc < len) {
+ if (str[cc] == ':') {
+ cc++;
+ }
+ cc_start = cc;
+ while (cc < len && cc < cc_start + 2) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ second = second * 10 + str[cc++] - '0';
+ }
+ if (cc == cc_start + 1 || second >= 60) {
+ return FALSE;
+ }
+ if (cc < len) {
+ if (str[cc] == '.') {
+ cc++;
+ cc_start = cc;
+ while (cc < len && cc < cc_start + 3) {
+ if (!FX_IsDigit(str[cc])) {
+ return FALSE;
+ }
+ millisecond = millisecond * 10 + str[cc++] - '0';
+ }
+ if (cc < cc_start + 3 || millisecond >= 1000) {
+ return FALSE;
+ }
+ }
+ if (cc < len) {
+ FX_TIMEZONE tzDiff;
+ tzDiff.tzHour = 0;
+ tzDiff.tzMinute = 0;
+ if (str[cc] != 'Z') {
+ cc += FX_ParseTimeZone(str + cc, len - cc, tzDiff);
+ }
+ FX_ResolveZone(hour, minute, tzDiff, pLocale);
+ }
+ }
+ }
+ }
+ CFX_Unitime ut;
+ ut.Set(0, 0, 0, hour, minute, second, millisecond);
+ datetime = datetime + ut;
+ return TRUE;
+}
+static FX_WORD FX_GetSolarMonthDays(FX_WORD year, FX_WORD month) {
+ if (month % 2) {
+ return 31;
+ } else if (month == 2) {
+ return FX_IsLeapYear(year) ? 29 : 28;
+ }
+ return 30;
+}
+static FX_WORD FX_GetWeekDay(FX_WORD year, FX_WORD month, FX_WORD day) {
+ FX_WORD g_month_day[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
+ FX_WORD nDays =
+ (year - 1) % 7 + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
+ nDays += g_month_day[month - 1] + day;
+ if (FX_IsLeapYear(year) && month > 2) {
+ nDays++;
+ }
+ return nDays % 7;
+}
+static FX_WORD FX_GetWeekOfMonth(FX_WORD year, FX_WORD month, FX_WORD day) {
+ FX_WORD week_day = FX_GetWeekDay(year, month, 1);
+ FX_WORD week_index = 0;
+ week_index += day / 7;
+ day = day % 7;
+ if (week_day + day > 7) {
+ week_index++;
+ }
+ return week_index;
+}
+static FX_WORD FX_GetWeekOfYear(FX_WORD year, FX_WORD month, FX_WORD day) {
+ FX_WORD nDays = 0;
+ for (FX_WORD i = 1; i < month; i++) {
+ nDays += FX_GetSolarMonthDays(year, i);
+ }
+ nDays += day;
+ FX_WORD week_day = FX_GetWeekDay(year, 1, 1);
+ FX_WORD week_index = 1;
+ week_index += nDays / 7;
+ nDays = nDays % 7;
+ if (week_day + nDays > 7) {
+ week_index++;
+ }
+ return week_index;
+}
+static FX_BOOL FX_DateFormat(const CFX_WideString& wsDatePattern,
+ IFX_Locale* pLocale,
+ const CFX_Unitime& datetime,
+ CFX_WideString& wsResult) {
+ FX_BOOL bRet = TRUE;
+ int32_t year = datetime.GetYear();
+ uint8_t month = datetime.GetMonth();
+ uint8_t day = datetime.GetDay();
+ int32_t ccf = 0;
+ const FX_WCHAR* strf = (const FX_WCHAR*)wsDatePattern;
+ int32_t lenf = wsDatePattern.GetLength();
+ while (ccf < lenf) {
+ if (strf[ccf] == '\'') {
+ wsResult += FX_GetLiteralText(strf, ccf, lenf);
+ ccf++;
+ continue;
+ } else if (FX_Local_Find(gs_wsDateSymbols, strf[ccf]) < 0) {
+ wsResult += strf[ccf++];
+ continue;
+ }
+ FX_DWORD dwSymbolNum = 1;
+ FX_DWORD dwSymbol = strf[ccf++];
+ while (ccf < lenf && strf[ccf] == dwSymbol) {
+ ccf++;
+ dwSymbolNum++;
+ }
+ dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
+ if (dwSymbol == FXBSTR_ID(0, 0, 'D', '1')) {
+ CFX_WideString wsDay;
+ wsDay.Format(L"%d", day);
+ wsResult += wsDay;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'D', '2')) {
+ CFX_WideString wsDay;
+ wsDay.Format(L"%02d", day);
+ wsResult += wsDay;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '1')) {
+ FX_WORD nDays = 0;
+ for (int i = 1; i < month; i++) {
+ nDays += FX_GetSolarMonthDays(year, i);
+ }
+ nDays += day;
+ CFX_WideString wsDays;
+ wsDays.Format(L"%d", nDays);
+ wsResult += wsDays;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'J', '3')) {
+ FX_WORD nDays = 0;
+ for (int i = 1; i < month; i++) {
+ nDays += FX_GetSolarMonthDays(year, i);
+ }
+ nDays += day;
+ CFX_WideString wsDays;
+ wsDays.Format(L"%03d", nDays);
+ wsResult += wsDays;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
+ CFX_WideString wsMonth;
+ wsMonth.Format(L"%d", month);
+ wsResult += wsMonth;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
+ CFX_WideString wsMonth;
+ wsMonth.Format(L"%02d", month);
+ wsResult += wsMonth;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '3')) {
+ CFX_WideString wsTemp;
+ pLocale->GetMonthName(month - 1, wsTemp, TRUE);
+ wsResult += wsTemp;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '4')) {
+ CFX_WideString wsTemp;
+ pLocale->GetMonthName(month - 1, wsTemp, FALSE);
+ wsResult += wsTemp;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '1')) {
+ FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
+ CFX_WideString wsWeekDay;
+ wsWeekDay.Format(L"%d", wWeekDay + 1);
+ wsResult += wsWeekDay;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '3')) {
+ FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
+ CFX_WideString wsTemp;
+ pLocale->GetDayName(wWeekDay, wsTemp, TRUE);
+ wsResult += wsTemp;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'E', '4')) {
+ FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
+ if (pLocale) {
+ CFX_WideString wsTemp;
+ pLocale->GetDayName(wWeekDay, wsTemp, FALSE);
+ wsResult += wsTemp;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'e', '1')) {
+ FX_WORD wWeekDay = FX_GetWeekDay(year, month, day);
+ CFX_WideString wsWeekDay;
+ wsWeekDay.Format(L"%d", wWeekDay ? wWeekDay : 7);
+ wsResult += wsWeekDay;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'G', '1')) {
+ CFX_WideString wsTemp;
+ pLocale->GetEraName(wsTemp, year < 0);
+ wsResult += wsTemp;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '2')) {
+ CFX_WideString wsYear;
+ wsYear.Format(L"%02d", year % 100);
+ wsResult += wsYear;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Y', '4')) {
+ CFX_WideString wsYear;
+ wsYear.Format(L"%d", year);
+ wsResult += wsYear;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'w', '1')) {
+ FX_WORD week_index = FX_GetWeekOfMonth(year, month, day);
+ CFX_WideString wsWeekInMonth;
+ wsWeekInMonth.Format(L"%d", week_index);
+ wsResult += wsWeekInMonth;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'W', '2')) {
+ FX_WORD week_index = FX_GetWeekOfYear(year, month, day);
+ CFX_WideString wsWeekInYear;
+ wsWeekInYear.Format(L"%02d", week_index);
+ wsResult += wsWeekInYear;
+ }
+ }
+ return bRet;
+}
+static FX_BOOL FX_TimeFormat(const CFX_WideString& wsTimePattern,
+ IFX_Locale* pLocale,
+ const CFX_Unitime& datetime,
+ CFX_WideString& wsResult) {
+ FX_BOOL bGMT = FALSE;
+ FX_BOOL bRet = TRUE;
+ uint8_t hour = datetime.GetHour();
+ uint8_t minute = datetime.GetMinute();
+ uint8_t second = datetime.GetSecond();
+ FX_WORD millisecond = datetime.GetMillisecond();
+ int32_t ccf = 0;
+ const FX_WCHAR* strf = (const FX_WCHAR*)wsTimePattern;
+ int32_t lenf = wsTimePattern.GetLength();
+ FX_WORD wHour = hour;
+ FX_BOOL bPM = FALSE;
+ if (wsTimePattern.Find('A') != -1) {
+ if (wHour >= 12) {
+ bPM = TRUE;
+ }
+ }
+ while (ccf < lenf) {
+ if (strf[ccf] == '\'') {
+ wsResult += FX_GetLiteralText(strf, ccf, lenf);
+ ccf++;
+ continue;
+ } else if (FX_Local_Find(gs_wsTimeSymbols, strf[ccf]) < 0) {
+ wsResult += strf[ccf++];
+ continue;
+ }
+ FX_DWORD dwSymbolNum = 1;
+ FX_DWORD dwSymbol = strf[ccf++];
+ while (ccf < lenf && strf[ccf] == dwSymbol) {
+ ccf++;
+ dwSymbolNum++;
+ }
+ dwSymbol = (dwSymbol << 8) | (dwSymbolNum + '0');
+ if (dwSymbol == FXBSTR_ID(0, 0, 'h', '1')) {
+ if (wHour > 12) {
+ wHour -= 12;
+ }
+ CFX_WideString wsHour;
+ wsHour.Format(L"%d", wHour == 0 ? 12 : wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'h', '2')) {
+ if (wHour > 12) {
+ wHour -= 12;
+ }
+ CFX_WideString wsHour;
+ wsHour.Format(L"%02d", wHour == 0 ? 12 : wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'K', '1')) {
+ CFX_WideString wsHour;
+ wsHour.Format(L"%d", wHour == 0 ? 24 : wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'K', '2')) {
+ CFX_WideString wsHour;
+ wsHour.Format(L"%02d", wHour == 0 ? 24 : wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '1')) {
+ if (wHour > 12) {
+ wHour -= 12;
+ }
+ CFX_WideString wsHour;
+ wsHour.Format(L"%d", wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'H', '1')) {
+ CFX_WideString wsHour;
+ wsHour.Format(L"%d", wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'k', '2')) {
+ if (wHour > 12) {
+ wHour -= 12;
+ }
+ CFX_WideString wsHour;
+ wsHour.Format(L"%02d", wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'H', '2')) {
+ CFX_WideString wsHour;
+ wsHour.Format(L"%02d", wHour);
+ wsResult += wsHour;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '1')) {
+ CFX_WideString wsMinute;
+ wsMinute.Format(L"%d", minute);
+ wsResult += wsMinute;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'M', '2')) {
+ CFX_WideString wsMinute;
+ wsMinute.Format(L"%02d", minute);
+ wsResult += wsMinute;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '1')) {
+ CFX_WideString wsSecond;
+ wsSecond.Format(L"%d", second);
+ wsResult += wsSecond;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'S', '2')) {
+ CFX_WideString wsSecond;
+ wsSecond.Format(L"%02d", second);
+ wsResult += wsSecond;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'F', '3')) {
+ CFX_WideString wsMilliseconds;
+ wsMilliseconds.Format(L"%03d", millisecond);
+ wsResult += wsMilliseconds;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'A', '1')) {
+ CFX_WideString wsMeridiem;
+ pLocale->GetMeridiemName(wsMeridiem, !bPM);
+ wsResult += wsMeridiem;
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'Z', '1')) {
+ wsResult += FX_WSTRC(L"GMT");
+ FX_TIMEZONE tz;
+ pLocale->GetTimeZone(tz);
+ if (!bGMT && (tz.tzHour != 0 || tz.tzMinute != 0)) {
+ if (tz.tzHour < 0) {
+ wsResult += FX_WSTRC(L"-");
+ } else {
+ wsResult += FX_WSTRC(L"+");
+ }
+ CFX_WideString wsTimezone;
+ wsTimezone.Format(L"%02d:%02d", FXSYS_abs(tz.tzHour), tz.tzMinute);
+ wsResult += wsTimezone;
+ }
+ } else if (dwSymbol == FXBSTR_ID(0, 0, 'z', '1')) {
+ FX_TIMEZONE tz;
+ pLocale->GetTimeZone(tz);
+ if (!bGMT && tz.tzHour != 0 && tz.tzMinute != 0) {
+ if (tz.tzHour < 0) {
+ wsResult += FX_WSTRC(L"-");
+ } else {
+ wsResult += FX_WSTRC(L"+");
+ }
+ CFX_WideString wsTimezone;
+ wsTimezone.Format(L"%02d:%02d", FXSYS_abs(tz.tzHour), tz.tzMinute);
+ wsResult += wsTimezone;
+ }
+ }
+ }
+ return bRet;
+}
+static FX_BOOL FX_FormatDateTime(const CFX_Unitime& dt,
+ const CFX_WideString& wsDatePattern,
+ const CFX_WideString& wsTimePattern,
+ FX_BOOL bDateFirst,
+ IFX_Locale* pLocale,
+ CFX_WideString& wsOutput) {
+ FX_BOOL bRet = TRUE;
+ CFX_WideString wsDateOut, wsTimeOut;
+ if (!wsDatePattern.IsEmpty()) {
+ bRet &= FX_DateFormat(wsDatePattern, pLocale, dt, wsDateOut);
+ }
+ if (!wsTimePattern.IsEmpty()) {
+ bRet &= FX_TimeFormat(wsTimePattern, pLocale, dt, wsTimeOut);
+ }
+ wsOutput = bDateFirst ? wsDateOut + wsTimeOut : wsTimeOut + wsDateOut;
+ return bRet;
+}
+FX_BOOL CFX_FormatString::FormatDateTime(const CFX_WideString& wsSrcDateTime,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) {
+ if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsDatePattern, wsTimePattern;
+ IFX_Locale* pLocale = NULL;
+ FX_DATETIMETYPE eCategory =
+ GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
+ if (pLocale == NULL || eCategory == FX_DATETIMETYPE_Unknown) {
+ return FALSE;
+ }
+ CFX_Unitime dt(0);
+ int32_t iT = wsSrcDateTime.Find(L"T");
+ if (iT < 0) {
+ if (eCategory == FX_DATETIMETYPE_Date) {
+ FX_DateFromCanonical(wsSrcDateTime, dt);
+ } else if (eCategory == FX_DATETIMETYPE_Time) {
+ FX_TimeFromCanonical(wsSrcDateTime, dt, pLocale);
+ }
+ } else {
+ FX_DateFromCanonical(wsSrcDateTime.Left(iT), dt);
+ FX_TimeFromCanonical(
+ wsSrcDateTime.Right(wsSrcDateTime.GetLength() - iT - 1), dt, pLocale);
+ }
+ return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern,
+ eCategory != FX_DATETIMETYPE_TimeDate, pLocale,
+ wsOutput);
+}
+FX_BOOL CFX_FormatString::FormatDateTime(const CFX_WideString& wsSrcDateTime,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput,
+ FX_DATETIMETYPE eDateTimeType) {
+ if (wsSrcDateTime.IsEmpty() || wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsDatePattern, wsTimePattern;
+ IFX_Locale* pLocale = NULL;
+ FX_DATETIMETYPE eCategory =
+ GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
+ if (!pLocale) {
+ return FALSE;
+ }
+ if (eCategory == FX_DATETIMETYPE_Unknown) {
+ if (eDateTimeType == FX_DATETIMETYPE_Time) {
+ wsTimePattern = wsDatePattern;
+ wsDatePattern.Empty();
+ }
+ eCategory = eDateTimeType;
+ }
+ if (eCategory == FX_DATETIMETYPE_Unknown) {
+ return FALSE;
+ }
+ CFX_Unitime dt(0);
+ int32_t iT = wsSrcDateTime.Find(L"T");
+ if (iT < 0) {
+ if (eCategory == FX_DATETIMETYPE_Date &&
+ FX_DateFromCanonical(wsSrcDateTime, dt)) {
+ return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, TRUE, pLocale,
+ wsOutput);
+ } else if (eCategory == FX_DATETIMETYPE_Time &&
+ FX_TimeFromCanonical(wsSrcDateTime, dt, pLocale)) {
+ return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern, TRUE, pLocale,
+ wsOutput);
+ }
+ } else {
+ CFX_WideStringC wsSrcDate((const FX_WCHAR*)wsSrcDateTime, iT);
+ CFX_WideStringC wsSrcTime((const FX_WCHAR*)wsSrcDateTime + iT + 1,
+ wsSrcDateTime.GetLength() - iT - 1);
+ if (wsSrcDate.IsEmpty() || wsSrcTime.IsEmpty()) {
+ return FALSE;
+ }
+ if (FX_DateFromCanonical(wsSrcDate, dt) &&
+ FX_TimeFromCanonical(wsSrcTime, dt, pLocale)) {
+ return FX_FormatDateTime(dt, wsDatePattern, wsTimePattern,
+ eCategory != FX_DATETIMETYPE_TimeDate, pLocale,
+ wsOutput);
+ }
+ }
+ return FALSE;
+}
+FX_BOOL CFX_FormatString::FormatDateTime(const CFX_Unitime& dt,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) {
+ if (wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsDatePattern, wsTimePattern;
+ IFX_Locale* pLocale = NULL;
+ FX_DATETIMETYPE eCategory =
+ GetDateTimeFormat(wsPattern, pLocale, wsDatePattern, wsTimePattern);
+ if (!pLocale) {
+ return FALSE;
+ }
+ return FX_FormatDateTime(dt, wsPattern, wsTimePattern,
+ eCategory != FX_DATETIMETYPE_TimeDate, pLocale,
+ wsOutput);
+}
+FX_BOOL CFX_FormatString::FormatZero(const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) {
+ if (wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsTextFormat;
+ GetTextFormat(wsPattern, FX_WSTRC(L"zero"), wsTextFormat);
+ int32_t iPattern = 0;
+ const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
+ int32_t iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern) {
+ if (pStrPattern[iPattern] == '\'') {
+ wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ iPattern++;
+ continue;
+ } else {
+ wsOutput += pStrPattern[iPattern++];
+ continue;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL CFX_FormatString::FormatNull(const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) {
+ if (wsPattern.IsEmpty()) {
+ return FALSE;
+ }
+ CFX_WideString wsTextFormat;
+ GetTextFormat(wsPattern, FX_WSTRC(L"null"), wsTextFormat);
+ int32_t iPattern = 0;
+ const FX_WCHAR* pStrPattern = (const FX_WCHAR*)wsTextFormat;
+ int32_t iLenPattern = wsTextFormat.GetLength();
+ while (iPattern < iLenPattern) {
+ if (pStrPattern[iPattern] == '\'') {
+ wsOutput += FX_GetLiteralText(pStrPattern, iPattern, iLenPattern);
+ iPattern++;
+ continue;
+ } else {
+ wsOutput += pStrPattern[iPattern++];
+ continue;
+ }
+ }
+ return TRUE;
+}
+IFX_Locale* CFX_FormatString::GetPatternLocale(
+ const CFX_WideStringC& wsLocale) {
+ if (m_bUseLCID) {
+ }
+ return m_pLocaleMgr->GetLocaleByName(wsLocale);
+}
+#define FXMATH_DECIMAL_SCALELIMIT 0x1c
+#define FXMATH_DECIMAL_NEGMASK (0x80000000L)
+#define FXMATH_DECIMAL_FORCEBOOL(x) (!(!(x)))
+#define FXMATH_DECIMAL_MAKEFLAGS(NEG, SCALE) \
+ (((SCALE) << 0x10) | ((NEG) ? FXMATH_DECIMAL_NEGMASK : 0))
+#define FXMATH_DECIMAL_FLAGS2NEG(FLAGS) \
+ FXMATH_DECIMAL_FORCEBOOL((FLAGS)&FXMATH_DECIMAL_NEGMASK)
+#define FXMATH_DECIMAL_FLAGS2SCALE(FLAGS) \
+ ((uint8_t)(((FLAGS) & ~FXMATH_DECIMAL_NEGMASK) >> 0x10))
+#define FXMATH_DECIMAL_RSHIFT32BIT(x) ((x) >> 0x10 >> 0x10)
+#define FXMATH_DECIMAL_LSHIFT32BIT(x) ((x) << 0x10 << 0x10)
+static inline uint8_t fxmath_decimal_helper_div10(uint64_t& phi,
+ uint64_t& pmid,
+ uint64_t& plo) {
+ uint8_t retVal;
+ pmid += FXMATH_DECIMAL_LSHIFT32BIT(phi % 0xA);
+ phi /= 0xA;
+ plo += FXMATH_DECIMAL_LSHIFT32BIT(pmid % 0xA);
+ pmid /= 0xA;
+ retVal = plo % 0xA;
+ plo /= 0xA;
+ return retVal;
+}
+static inline uint8_t fxmath_decimal_helper_div10_any(uint64_t nums[],
+ uint8_t numcount) {
+ uint8_t retVal = 0;
+ for (int i = numcount - 1; i > 0; i--) {
+ nums[i - 1] += FXMATH_DECIMAL_LSHIFT32BIT(nums[i] % 0xA);
+ nums[i] /= 0xA;
+ }
+ if (numcount) {
+ retVal = nums[0] % 0xA;
+ nums[0] /= 0xA;
+ }
+ return retVal;
+}
+static inline void fxmath_decimal_helper_mul10(uint64_t& phi,
+ uint64_t& pmid,
+ uint64_t& plo) {
+ plo *= 0xA;
+ pmid = pmid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(plo);
+ plo = (uint32_t)plo;
+ phi = phi * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(pmid);
+ pmid = (uint32_t)pmid;
+}
+static inline void fxmath_decimal_helper_mul10_any(uint64_t nums[],
+ uint8_t numcount) {
+ nums[0] *= 0xA;
+ for (int i = 1; i < numcount; i++) {
+ nums[i] = nums[i] * 0xA + FXMATH_DECIMAL_RSHIFT32BIT(nums[i - 1]);
+ nums[i - 1] = (uint32_t)nums[i - 1];
+ }
+}
+static inline void fxmath_decimal_helper_normalize(uint64_t& phi,
+ uint64_t& pmid,
+ uint64_t& plo) {
+ phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid);
+ pmid = (uint32_t)pmid;
+ pmid += FXMATH_DECIMAL_RSHIFT32BIT(plo);
+ plo = (uint32_t)plo;
+ phi += FXMATH_DECIMAL_RSHIFT32BIT(pmid);
+ pmid = (uint32_t)pmid;
+}
+static inline void fxmath_decimal_helper_normalize_any(uint64_t nums[],
+ uint8_t len) {
+ {
+ for (int i = len - 2; i > 0; i--) {
+ nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]);
+ nums[i] = (uint32_t)nums[i];
+ }
+ }
+ {
+ for (int i = 0; i < len - 1; i++) {
+ nums[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(nums[i]);
+ nums[i] = (uint32_t)nums[i];
+ }
+ }
+}
+static inline int8_t fxmath_decimal_helper_raw_compare(uint32_t hi1,
+ uint32_t mid1,
+ uint32_t lo1,
+ uint32_t hi2,
+ uint32_t mid2,
+ uint32_t lo2) {
+ int8_t retVal = 0;
+ if (!retVal) {
+ retVal += (hi1 > hi2 ? 1 : (hi1 < hi2 ? -1 : 0));
+ }
+ if (!retVal) {
+ retVal += (mid1 > mid2 ? 1 : (mid1 < mid2 ? -1 : 0));
+ }
+ if (!retVal) {
+ retVal += (lo1 > lo2 ? 1 : (lo1 < lo2 ? -1 : 0));
+ }
+ return retVal;
+}
+static inline int8_t fxmath_decimal_helper_raw_compare_any(uint64_t a[],
+ uint8_t al,
+ uint64_t b[],
+ uint8_t bl) {
+ int8_t retVal = 0;
+ for (int i = std::max(al - 1, bl - 1); i >= 0; i--) {
+ uint64_t l = (i >= al ? 0 : a[i]), r = (i >= bl ? 0 : b[i]);
+ retVal += (l > r ? 1 : (l < r ? -1 : 0));
+ if (retVal) {
+ return retVal;
+ }
+ }
+ return retVal;
+}
+static inline void fxmath_decimal_helper_dec_any(uint64_t a[], uint8_t al) {
+ for (int i = 0; i < al; i++) {
+ if (a[i]--) {
+ return;
+ }
+ }
+}
+static inline void fxmath_decimal_helper_inc_any(uint64_t a[], uint8_t al) {
+ for (int i = 0; i < al; i++) {
+ a[i]++;
+ if ((uint32_t)a[i] == a[i]) {
+ return;
+ }
+ a[i] = 0;
+ }
+}
+static inline void fxmath_decimal_helper_raw_mul(uint64_t a[],
+ uint8_t al,
+ uint64_t b[],
+ uint8_t bl,
+ uint64_t c[],
+ uint8_t cl) {
+ assert(al + bl <= cl);
+ {
+ for (int i = 0; i < cl; i++) {
+ c[i] = 0;
+ }
+ }
+ {
+ for (int i = 0; i < al; i++) {
+ for (int j = 0; j < bl; j++) {
+ uint64_t m = (uint64_t)a[i] * b[j];
+ c[i + j] += (uint32_t)m;
+ c[i + j + 1] += FXMATH_DECIMAL_RSHIFT32BIT(m);
+ }
+ }
+ }
+ {
+ for (int i = 0; i < cl - 1; i++) {
+ c[i + 1] += FXMATH_DECIMAL_RSHIFT32BIT(c[i]);
+ c[i] = (uint32_t)c[i];
+ }
+ }
+ {
+ for (int i = 0; i < cl; i++) {
+ c[i] = (uint32_t)c[i];
+ }
+ }
+}
+static inline void fxmath_decimal_helper_raw_div(uint64_t a[],
+ uint8_t al,
+ uint64_t b[],
+ uint8_t bl,
+ uint64_t c[],
+ uint8_t cl) {
+ int i;
+ for (i = 0; i < cl; i++) {
+ c[i] = 0;
+ }
+ uint64_t left[16] = {0}, right[16] = {0};
+ left[0] = 0;
+ for (i = 0; i < al; i++) {
+ right[i] = a[i];
+ }
+ uint64_t tmp[16];
+ while (fxmath_decimal_helper_raw_compare_any(left, al, right, al) <= 0) {
+ uint64_t cur[16];
+ for (i = 0; i < al; i++) {
+ cur[i] = left[i] + right[i];
+ }
+ for (i = al - 1; i >= 0; i--) {
+ if (i) {
+ cur[i - 1] += FXMATH_DECIMAL_LSHIFT32BIT(cur[i] % 2);
+ }
+ cur[i] /= 2;
+ }
+ fxmath_decimal_helper_raw_mul(cur, al, b, bl, tmp, 16);
+ switch (fxmath_decimal_helper_raw_compare_any(tmp, 16, a, al)) {
+ case -1:
+ for (i = 0; i < 16; i++) {
+ left[i] = cur[i];
+ }
+ left[0]++;
+ fxmath_decimal_helper_normalize_any(left, al);
+ break;
+ case 1:
+ for (i = 0; i < 16; i++) {
+ right[i] = cur[i];
+ }
+ fxmath_decimal_helper_dec_any(right, al);
+ break;
+ case 0:
+ for (i = 0; i < std::min(al, cl); i++) {
+ c[i] = cur[i];
+ }
+ return;
+ }
+ }
+ for (i = 0; i < std::min(al, cl); i++) {
+ c[i] = left[i];
+ }
+}
+static inline FX_BOOL fxmath_decimal_helper_outofrange(uint64_t a[],
+ uint8_t al,
+ uint8_t goal) {
+ for (int i = goal; i < al; i++) {
+ if (a[i]) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+static inline void fxmath_decimal_helper_shrinkintorange(uint64_t a[],
+ uint8_t al,
+ uint8_t goal,
+ uint8_t& scale) {
+ FX_BOOL bRoundUp = FALSE;
+ while (scale != 0 && (scale > FXMATH_DECIMAL_SCALELIMIT ||
+ fxmath_decimal_helper_outofrange(a, al, goal))) {
+ bRoundUp = fxmath_decimal_helper_div10_any(a, al) >= 5;
+ scale--;
+ }
+ if (bRoundUp) {
+ fxmath_decimal_helper_normalize_any(a, goal);
+ fxmath_decimal_helper_inc_any(a, goal);
+ }
+}
+static inline void fxmath_decimal_helper_truncate(uint64_t& phi,
+ uint64_t& pmid,
+ uint64_t& plo,
+ uint8_t& scale,
+ uint8_t minscale = 0) {
+ while (scale > minscale) {
+ uint64_t thi = phi, tmid = pmid, tlo = plo;
+ if (fxmath_decimal_helper_div10(thi, tmid, tlo) != 0) {
+ break;
+ }
+ phi = thi, pmid = tmid, plo = tlo;
+ scale--;
+ }
+}
+CFX_Decimal::CFX_Decimal() {
+ m_uLo = m_uMid = m_uHi = m_uFlags = 0;
+}
+CFX_Decimal::CFX_Decimal(uint64_t val) {
+ m_uLo = (uint32_t)val;
+ m_uMid = (uint32_t)FXMATH_DECIMAL_RSHIFT32BIT(val);
+ m_uHi = 0;
+ m_uFlags = 0;
+}
+CFX_Decimal::CFX_Decimal(uint32_t val) {
+ m_uLo = (uint32_t)val;
+ m_uMid = m_uHi = 0;
+ m_uFlags = 0;
+}
+CFX_Decimal::CFX_Decimal(uint32_t lo,
+ uint32_t mid,
+ uint32_t hi,
+ FX_BOOL neg,
+ uint8_t scale) {
+ scale = (scale > FXMATH_DECIMAL_SCALELIMIT ? 0 : scale);
+ m_uLo = lo;
+ m_uMid = mid;
+ m_uHi = hi;
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(neg && IsNotZero(), scale);
+}
+CFX_Decimal::CFX_Decimal(int32_t val) {
+ if (val >= 0) {
+ *this = CFX_Decimal((uint32_t)val);
+ } else {
+ *this = CFX_Decimal((uint32_t)-val);
+ SetNegate();
+ }
+}
+CFX_Decimal::CFX_Decimal(int64_t val) {
+ if (val >= 0) {
+ *this = CFX_Decimal((uint64_t)val);
+ } else {
+ *this = CFX_Decimal((uint64_t)-val);
+ SetNegate();
+ }
+}
+CFX_Decimal::CFX_Decimal(FX_FLOAT val, uint8_t scale) {
+ FX_FLOAT newval = fabs(val);
+ uint64_t phi, pmid, plo;
+ plo = (uint64_t)newval;
+ pmid = (uint64_t)(newval / 1e32);
+ phi = (uint64_t)(newval / 1e64);
+ newval = FXSYS_fmod(newval, 1.0f);
+ for (uint8_t iter = 0; iter < scale; iter++) {
+ fxmath_decimal_helper_mul10(phi, pmid, plo);
+ newval *= 10;
+ plo += (uint64_t)newval;
+ newval = FXSYS_fmod(newval, 1.0f);
+ }
+ plo += FXSYS_round(newval);
+ fxmath_decimal_helper_normalize(phi, pmid, plo);
+ m_uHi = (uint32_t)phi;
+ m_uMid = (uint32_t)pmid;
+ m_uLo = (uint32_t)plo;
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(val < 0 && IsNotZero(), scale);
+}
+CFX_Decimal::CFX_Decimal(const CFX_WideStringC& strObj) {
+ const FX_WCHAR* str = strObj.GetPtr();
+ const FX_WCHAR* strBound = str + strObj.GetLength();
+ FX_BOOL pointmet = 0;
+ FX_BOOL negmet = 0;
+ uint8_t scale = 0;
+ m_uHi = m_uMid = m_uLo = 0;
+ while (str != strBound && *str == ' ') {
+ str++;
+ }
+ if (str != strBound && *str == '-') {
+ negmet = 1;
+ str++;
+ } else if (str != strBound && *str == '+') {
+ str++;
+ }
+ while (str != strBound && ((*str >= '0' && *str <= '9') || *str == '.') &&
+ scale < FXMATH_DECIMAL_SCALELIMIT) {
+ if (*str == '.') {
+ if (pointmet) {
+ goto cont;
+ }
+ pointmet = 1;
+ } else {
+ m_uHi = m_uHi * 0xA + FXMATH_DECIMAL_RSHIFT32BIT((uint64_t)m_uMid * 0xA);
+ m_uMid = m_uMid * 0xA + FXMATH_DECIMAL_RSHIFT32BIT((uint64_t)m_uLo * 0xA);
+ m_uLo = m_uLo * 0xA + (*str - '0');
+ if (pointmet) {
+ scale++;
+ }
+ }
+ cont:
+ str++;
+ }
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(negmet && IsNotZero(), scale);
+}
+
+CFX_Decimal::CFX_Decimal(const CFX_ByteStringC& strObj) {
+ *this = CFX_Decimal(CFX_WideString::FromLocal(strObj));
+}
+
+CFX_Decimal::operator CFX_WideString() const {
+ CFX_WideString retString;
+ CFX_WideString tmpbuf;
+ uint64_t phi = m_uHi, pmid = m_uMid, plo = m_uLo;
+ while (phi || pmid || plo) {
+ tmpbuf += fxmath_decimal_helper_div10(phi, pmid, plo) + '0';
+ }
+ uint8_t outputlen = (uint8_t)tmpbuf.GetLength();
+ uint8_t scale = (uint8_t)FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
+ while (scale >= outputlen) {
+ tmpbuf += '0';
+ outputlen++;
+ }
+ if (FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero()) {
+ retString += '-';
+ }
+ for (uint8_t idx = 0; idx < outputlen; idx++) {
+ if (idx == (outputlen - scale) && scale != 0) {
+ retString += '.';
+ }
+ retString += tmpbuf[outputlen - 1 - idx];
+ }
+ return retString;
+}
+CFX_Decimal::operator double() const {
+ double pow = (double)(1 << 16) * (1 << 16);
+ double base =
+ ((double)m_uHi) * pow * pow + ((double)m_uMid) * pow + ((double)m_uLo);
+ int8_t scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
+ FX_BOOL bNeg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags);
+ return (bNeg ? -1 : 1) * base * ::pow(10.0, -scale);
+}
+void CFX_Decimal::SetScale(uint8_t newscale) {
+ uint8_t oldscale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
+ if (newscale > oldscale) {
+ uint64_t phi = m_uHi, pmid = m_uMid, plo = m_uLo;
+ for (uint8_t iter = 0; iter < newscale - oldscale; iter++) {
+ fxmath_decimal_helper_mul10(phi, pmid, plo);
+ }
+ m_uHi = (uint32_t)phi;
+ m_uMid = (uint32_t)pmid;
+ m_uLo = (uint32_t)plo;
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(
+ FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale);
+ } else if (newscale < oldscale) {
+ uint64_t phi, pmid, plo;
+ phi = 0, pmid = 0, plo = 5;
+ {
+ for (uint8_t iter = 0; iter < oldscale - newscale - 1; iter++) {
+ fxmath_decimal_helper_mul10(phi, pmid, plo);
+ }
+ }
+ phi += m_uHi;
+ pmid += m_uMid;
+ plo += m_uLo;
+ fxmath_decimal_helper_normalize(phi, pmid, plo);
+ {
+ for (uint8_t iter = 0; iter < oldscale - newscale; iter++) {
+ fxmath_decimal_helper_div10(phi, pmid, plo);
+ }
+ }
+ m_uHi = (uint32_t)phi;
+ m_uMid = (uint32_t)pmid;
+ m_uLo = (uint32_t)plo;
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(
+ FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale);
+ }
+}
+uint8_t CFX_Decimal::GetScale() {
+ uint8_t oldscale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
+ return oldscale;
+}
+void CFX_Decimal::SetAbs() {
+ m_uFlags &= ~FXMATH_DECIMAL_NEGMASK;
+}
+void CFX_Decimal::SetNegate() {
+ if (IsNotZero()) {
+ m_uFlags ^= FXMATH_DECIMAL_NEGMASK;
+ }
+}
+void CFX_Decimal::FloorOrCeil(FX_BOOL bFloor) {
+ uint64_t nums[3] = {m_uLo, m_uMid, m_uHi};
+ FX_BOOL bDataLoss = FALSE;
+ for (int i = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); i > 0; i--) {
+ bDataLoss = fxmath_decimal_helper_div10_any(nums, 3) || bDataLoss;
+ }
+ if (bDataLoss && (bFloor ? FXMATH_DECIMAL_FLAGS2NEG(m_uFlags)
+ : !FXMATH_DECIMAL_FLAGS2NEG(m_uFlags))) {
+ fxmath_decimal_helper_inc_any(nums, 3);
+ }
+ m_uHi = (uint32_t)nums[2];
+ m_uMid = (uint32_t)nums[1];
+ m_uLo = (uint32_t)nums[0];
+ m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(
+ FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), 0);
+}
+void CFX_Decimal::SetFloor() {
+ FloorOrCeil(TRUE);
+}
+void CFX_Decimal::SetCeiling() {
+ FloorOrCeil(FALSE);
+}
+void CFX_Decimal::SetTruncate() {
+ FloorOrCeil(!FXMATH_DECIMAL_FLAGS2NEG(m_uFlags));
+}
+void CFX_Decimal::Swap(CFX_Decimal& val) {
+ uint32_t tmp;
+ tmp = m_uHi;
+ m_uHi = val.m_uHi;
+ val.m_uHi = tmp;
+ tmp = m_uMid;
+ m_uMid = val.m_uMid;
+ val.m_uMid = tmp;
+ tmp = m_uLo;
+ m_uLo = val.m_uLo;
+ val.m_uLo = tmp;
+ tmp = m_uFlags;
+ m_uFlags = val.m_uFlags;
+ val.m_uFlags = tmp;
+}
+int8_t CFX_Decimal::Compare(const CFX_Decimal& val) const {
+ CFX_Decimal lhs = *this, rhs = val;
+ int8_t retVal = 0;
+ if (FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) !=
+ FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)) {
+ uint8_t scale = std::min(FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags),
+ FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags));
+ lhs.SetScale(scale);
+ rhs.SetScale(scale);
+ }
+ retVal = -(FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) -
+ FXMATH_DECIMAL_FLAGS2NEG(rhs.m_uFlags));
+ if (retVal) {
+ return retVal;
+ }
+ retVal = fxmath_decimal_helper_raw_compare(lhs.m_uHi, lhs.m_uMid, lhs.m_uLo,
+ rhs.m_uHi, rhs.m_uMid, rhs.m_uLo);
+ return (FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) ? -retVal : retVal);
+}
+CFX_Decimal CFX_Decimal::AddOrMinus(const CFX_Decimal& val,
+ FX_BOOL isAdding) const {
+ CFX_Decimal lhs = *this, rhs = val;
+ if (FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) !=
+ FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags)) {
+ uint8_t scale = std::max(FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags),
+ FXMATH_DECIMAL_FLAGS2SCALE(rhs.m_uFlags));
+ lhs.SetScale(scale);
+ rhs.SetScale(scale);
+ }
+ if (!isAdding) {
+ rhs.SetNegate();
+ }
+ if (FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags) ==
+ FXMATH_DECIMAL_FLAGS2NEG(rhs.m_uFlags)) {
+ uint64_t phi = lhs.m_uHi, pmid = lhs.m_uMid, plo = lhs.m_uLo;
+ phi += rhs.m_uHi;
+ pmid += rhs.m_uMid;
+ plo += rhs.m_uLo;
+ fxmath_decimal_helper_normalize(phi, pmid, plo);
+ if (FXMATH_DECIMAL_RSHIFT32BIT(phi) &&
+ FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) != 0) {
+ fxmath_decimal_helper_div10(phi, pmid, plo);
+ lhs.m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(
+ FXMATH_DECIMAL_FLAGS2NEG(lhs.m_uFlags),
+ FXMATH_DECIMAL_FLAGS2SCALE(lhs.m_uFlags) - 1);
+ }
+ lhs.m_uHi = (uint32_t)phi;
+ lhs.m_uMid = (uint32_t)pmid;
+ lhs.m_uLo = (uint32_t)plo;
+ return lhs;
+ } else {
+ if (fxmath_decimal_helper_raw_compare(lhs.m_uHi, lhs.m_uMid, lhs.m_uLo,
+ rhs.m_uHi, rhs.m_uMid,
+ rhs.m_uLo) < 0) {
+ lhs.Swap(rhs);
+ }
+ lhs.m_uHi -= rhs.m_uHi;
+ if (lhs.m_uMid < rhs.m_uMid) {
+ lhs.m_uHi--;
+ }
+ lhs.m_uMid -= rhs.m_uMid;
+ if (lhs.m_uLo < rhs.m_uLo) {
+ if (!lhs.m_uMid) {
+ lhs.m_uHi--;
+ }
+ lhs.m_uMid--;
+ }
+ lhs.m_uLo -= rhs.m_uLo;
+ return lhs;
+ }
+}
+CFX_Decimal CFX_Decimal::Multiply(const CFX_Decimal& val) const {
+ uint64_t a[3] = {m_uLo, m_uMid, m_uHi},
+ b[3] = {val.m_uLo, val.m_uMid, val.m_uHi};
+ uint64_t c[6];
+ fxmath_decimal_helper_raw_mul(a, 3, b, 3, c, 6);
+ FX_BOOL neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^
+ FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags);
+ uint8_t scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) +
+ FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags);
+ fxmath_decimal_helper_shrinkintorange(c, 6, 3, scale);
+ return CFX_Decimal((uint32_t)c[0], (uint32_t)c[1], (uint32_t)c[2], neg,
+ scale);
+}
+CFX_Decimal CFX_Decimal::Divide(const CFX_Decimal& val) const {
+ if (!val.IsNotZero()) {
+ return CFX_Decimal();
+ }
+ FX_BOOL neg = FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) ^
+ FXMATH_DECIMAL_FLAGS2NEG(val.m_uFlags);
+ uint64_t a[7] = {m_uLo, m_uMid, m_uHi},
+ b[3] = {val.m_uLo, val.m_uMid, val.m_uHi}, c[7] = {0};
+ uint8_t scale = 0;
+ if (FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) <
+ FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags)) {
+ for (int i = FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags) -
+ FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags);
+ i > 0; i--) {
+ fxmath_decimal_helper_mul10_any(a, 7);
+ }
+ } else {
+ scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags) -
+ FXMATH_DECIMAL_FLAGS2SCALE(val.m_uFlags);
+ }
+ uint8_t minscale = scale;
+ if (!IsNotZero()) {
+ return CFX_Decimal(0, 0, 0, 0, minscale);
+ }
+ while (!a[6]) {
+ fxmath_decimal_helper_mul10_any(a, 7);
+ scale++;
+ }
+ fxmath_decimal_helper_div10_any(a, 7);
+ scale--;
+ fxmath_decimal_helper_raw_div(a, 6, b, 3, c, 7);
+ fxmath_decimal_helper_shrinkintorange(c, 6, 3, scale);
+ fxmath_decimal_helper_truncate(c[2], c[1], c[0], scale, minscale);
+ return CFX_Decimal((uint32_t)c[0], (uint32_t)c[1], (uint32_t)c[2], neg,
+ scale);
+}
+CFX_Decimal CFX_Decimal::Modulus(const CFX_Decimal& val) const {
+ CFX_Decimal lhs = *this, rhs_abs = val;
+ rhs_abs.SetAbs();
+ if (!rhs_abs.IsNotZero()) {
+ return *this;
+ }
+ while (TRUE) {
+ CFX_Decimal lhs_abs = lhs;
+ lhs_abs.SetAbs();
+ if (lhs_abs < rhs_abs) {
+ break;
+ }
+ CFX_Decimal quot = lhs / rhs_abs;
+ quot.SetTruncate();
+ lhs = lhs - quot * rhs_abs;
+ }
+ return lhs;
+}
+bool CFX_Decimal::operator==(const CFX_Decimal& val) const {
+ return Compare(val) == 0;
+}
+bool CFX_Decimal::operator<=(const CFX_Decimal& val) const {
+ return Compare(val) <= 0;
+}
+bool CFX_Decimal::operator>=(const CFX_Decimal& val) const {
+ return Compare(val) >= 0;
+}
+bool CFX_Decimal::operator!=(const CFX_Decimal& val) const {
+ return Compare(val) != 0;
+}
+bool CFX_Decimal::operator<(const CFX_Decimal& val) const {
+ return Compare(val) < 0;
+}
+bool CFX_Decimal::operator>(const CFX_Decimal& val) const {
+ return Compare(val) > 0;
+}
+CFX_Decimal CFX_Decimal::operator+(const CFX_Decimal& val) const {
+ return AddOrMinus(val, TRUE);
+}
+CFX_Decimal CFX_Decimal::operator-(const CFX_Decimal& val) const {
+ return AddOrMinus(val, FALSE);
+}
+CFX_Decimal CFX_Decimal::operator*(const CFX_Decimal& val) const {
+ return Multiply(val);
+}
+CFX_Decimal CFX_Decimal::operator/(const CFX_Decimal& val) const {
+ return Divide(val);
+}
+CFX_Decimal CFX_Decimal::operator%(const CFX_Decimal& val) const {
+ return Modulus(val);
+}
diff --git a/xfa/src/fgas/localization/fgas_locale.h b/xfa/src/fgas/localization/fgas_locale.h
new file mode 100644
index 0000000000..03dd518715
--- /dev/null
+++ b/xfa/src/fgas/localization/fgas_locale.h
@@ -0,0 +1,206 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_LOCALIZATION_FGAS_LOCALE_H_
+#define XFA_SRC_FGAS_LOCALIZATION_FGAS_LOCALE_H_
+
+#include "core/include/fxcrt/fx_xml.h"
+#include "xfa/src/fgas/localization/fgas_datetime.h"
+
+class CFX_Unitime;
+
+enum FX_LOCALENUMSYMBOL {
+ FX_LOCALENUMSYMBOL_Decimal,
+ FX_LOCALENUMSYMBOL_Grouping,
+ FX_LOCALENUMSYMBOL_Percent,
+ FX_LOCALENUMSYMBOL_Minus,
+ FX_LOCALENUMSYMBOL_Zero,
+ FX_LOCALENUMSYMBOL_CurrencySymbol,
+ FX_LOCALENUMSYMBOL_CurrencyName,
+};
+enum FX_LOCALEDATETIMESUBCATEGORY {
+ FX_LOCALEDATETIMESUBCATEGORY_Default,
+ FX_LOCALEDATETIMESUBCATEGORY_Short,
+ FX_LOCALEDATETIMESUBCATEGORY_Medium,
+ FX_LOCALEDATETIMESUBCATEGORY_Full,
+ FX_LOCALEDATETIMESUBCATEGORY_Long,
+};
+enum FX_LOCALENUMSUBCATEGORY {
+ FX_LOCALENUMPATTERN_Percent,
+ FX_LOCALENUMPATTERN_Currency,
+ FX_LOCALENUMPATTERN_Decimal,
+ FX_LOCALENUMPATTERN_Integer,
+};
+enum FX_LOCALECATEGORY {
+ FX_LOCALECATEGORY_Unknown,
+ FX_LOCALECATEGORY_Date,
+ FX_LOCALECATEGORY_Time,
+ FX_LOCALECATEGORY_DateTime,
+ FX_LOCALECATEGORY_Num,
+ FX_LOCALECATEGORY_Text,
+ FX_LOCALECATEGORY_Zero,
+ FX_LOCALECATEGORY_Null,
+};
+enum FX_DATETIMETYPE {
+ FX_DATETIMETYPE_Unknown,
+ FX_DATETIMETYPE_Date,
+ FX_DATETIMETYPE_Time,
+ FX_DATETIMETYPE_DateTime,
+ FX_DATETIMETYPE_TimeDate,
+};
+
+class IFX_Locale {
+ public:
+ static IFX_Locale* Create(CXML_Element* pLocaleData);
+
+ virtual ~IFX_Locale() {}
+ virtual void Release() = 0;
+
+ virtual CFX_WideString GetName() = 0;
+
+ virtual void GetNumbericSymbol(FX_LOCALENUMSYMBOL eType,
+ CFX_WideString& wsNumSymbol) const = 0;
+ virtual void GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const = 0;
+ virtual void GetMonthName(int32_t nMonth,
+ CFX_WideString& wsMonthName,
+ FX_BOOL bAbbr = TRUE) const = 0;
+ virtual void GetDayName(int32_t nWeek,
+ CFX_WideString& wsDayName,
+ FX_BOOL bAbbr = TRUE) const = 0;
+ virtual void GetMeridiemName(CFX_WideString& wsMeridiemName,
+ FX_BOOL bAM = TRUE) const = 0;
+ virtual void GetTimeZone(FX_TIMEZONE& tz) const = 0;
+ virtual void GetEraName(CFX_WideString& wsEraName,
+ FX_BOOL bAD = TRUE) const = 0;
+ virtual void GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
+ CFX_WideString& wsPattern) const = 0;
+ virtual void GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
+ CFX_WideString& wsPattern) const = 0;
+ virtual void GetNumPattern(FX_LOCALENUMSUBCATEGORY eType,
+ CFX_WideString& wsPattern) const = 0;
+};
+
+class IFX_LocaleMgr {
+ public:
+ virtual ~IFX_LocaleMgr() {}
+ virtual void Release() = 0;
+ virtual FX_WORD GetDefLocaleID() = 0;
+ virtual IFX_Locale* GetDefLocale() = 0;
+ virtual IFX_Locale* GetLocale(FX_WORD lcid) = 0;
+ virtual IFX_Locale* GetLocaleByName(const CFX_WideStringC& wsLocaleName) = 0;
+};
+IFX_LocaleMgr* FX_LocaleMgr_Create(const FX_WCHAR* pszLocalPath,
+ FX_WORD wDefaultLCID);
+void FX_ParseNumString(const CFX_WideString& wsNum, CFX_WideString& wsResult);
+FX_BOOL FX_DateFromCanonical(const CFX_WideString& wsDate,
+ CFX_Unitime& datetime);
+FX_BOOL FX_TimeFromCanonical(const CFX_WideStringC& wsTime,
+ CFX_Unitime& datetime,
+ IFX_Locale* pLocale);
+class IFX_FormatString {
+ public:
+ static IFX_FormatString* Create(IFX_LocaleMgr* pLocaleMgr, FX_BOOL bUseLCID);
+
+ virtual ~IFX_FormatString() {}
+ virtual void Release() = 0;
+ virtual void SplitFormatString(const CFX_WideString& wsFormatString,
+ CFX_WideStringArray& wsPatterns) = 0;
+ virtual FX_LOCALECATEGORY GetCategory(const CFX_WideString& wsPattern) = 0;
+ virtual FX_WORD GetLCID(const CFX_WideString& wsPattern) = 0;
+ virtual CFX_WideString GetLocaleName(const CFX_WideString& wsPattern) = 0;
+ virtual FX_BOOL ParseText(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsValue) = 0;
+ virtual FX_BOOL ParseNum(const CFX_WideString& wsSrcNum,
+ const CFX_WideString& wsPattern,
+ FX_FLOAT& fValue) = 0;
+ virtual FX_BOOL ParseNum(const CFX_WideString& wsSrcNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsValue) = 0;
+ virtual FX_BOOL ParseDateTime(const CFX_WideString& wsSrcDateTime,
+ const CFX_WideString& wsPattern,
+ FX_DATETIMETYPE eDateTimeType,
+ CFX_Unitime& dtValue) = 0;
+ virtual FX_BOOL ParseZero(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern) = 0;
+ virtual FX_BOOL ParseNull(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern) = 0;
+ virtual FX_BOOL FormatText(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) = 0;
+ virtual FX_BOOL FormatNum(const CFX_WideString& wsSrcNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) = 0;
+ virtual FX_BOOL FormatNum(FX_FLOAT fNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) = 0;
+ virtual FX_BOOL FormatDateTime(const CFX_WideString& wsSrcDateTime,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) = 0;
+ virtual FX_BOOL FormatDateTime(const CFX_WideString& wsSrcDateTime,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput,
+ FX_DATETIMETYPE eDateTimeType) = 0;
+ virtual FX_BOOL FormatDateTime(const CFX_Unitime& dt,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) = 0;
+ virtual FX_BOOL FormatZero(const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) = 0;
+ virtual FX_BOOL FormatNull(const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput) = 0;
+};
+class CFX_Decimal {
+ public:
+ CFX_Decimal();
+ CFX_Decimal(uint32_t val);
+ CFX_Decimal(uint64_t val);
+ CFX_Decimal(int32_t val);
+ CFX_Decimal(int64_t val);
+ CFX_Decimal(FX_FLOAT val, uint8_t scale = 3);
+ CFX_Decimal(const CFX_WideStringC& str);
+ CFX_Decimal(const CFX_ByteStringC& str);
+ operator CFX_WideString() const;
+ operator double() const;
+ bool operator==(const CFX_Decimal& val) const;
+ bool operator<=(const CFX_Decimal& val) const;
+ bool operator>=(const CFX_Decimal& val) const;
+ bool operator!=(const CFX_Decimal& val) const;
+ bool operator<(const CFX_Decimal& val) const;
+ bool operator>(const CFX_Decimal& val) const;
+ CFX_Decimal operator+(const CFX_Decimal& val) const;
+ CFX_Decimal operator-(const CFX_Decimal& val) const;
+ CFX_Decimal operator*(const CFX_Decimal& val) const;
+ CFX_Decimal operator/(const CFX_Decimal& val) const;
+ CFX_Decimal operator%(const CFX_Decimal& val) const;
+ void SetScale(uint8_t newScale);
+ uint8_t GetScale();
+ void SetAbs();
+ void SetNegate();
+ void SetFloor();
+ void SetCeiling();
+ void SetTruncate();
+
+ protected:
+ CFX_Decimal(uint32_t hi,
+ uint32_t mid,
+ uint32_t lo,
+ FX_BOOL neg,
+ uint8_t scale);
+ inline FX_BOOL IsNotZero() const { return m_uHi || m_uMid || m_uLo; }
+ inline int8_t Compare(const CFX_Decimal& val) const;
+ inline void Swap(CFX_Decimal& val);
+ inline void FloorOrCeil(FX_BOOL bFloor);
+ CFX_Decimal AddOrMinus(const CFX_Decimal& val, FX_BOOL isAdding) const;
+ CFX_Decimal Multiply(const CFX_Decimal& val) const;
+ CFX_Decimal Divide(const CFX_Decimal& val) const;
+ CFX_Decimal Modulus(const CFX_Decimal& val) const;
+ uint32_t m_uFlags;
+ uint32_t m_uHi;
+ uint32_t m_uLo;
+ uint32_t m_uMid;
+};
+
+#endif // XFA_SRC_FGAS_LOCALIZATION_FGAS_LOCALE_H_
diff --git a/xfa/src/fgas/localization/fgas_localeimp.h b/xfa/src/fgas/localization/fgas_localeimp.h
new file mode 100644
index 0000000000..5da8b51208
--- /dev/null
+++ b/xfa/src/fgas/localization/fgas_localeimp.h
@@ -0,0 +1,122 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_LOCALIZATION_FGAS_LOCALEIMP_H_
+#define XFA_SRC_FGAS_LOCALIZATION_FGAS_LOCALEIMP_H_
+
+#include "xfa/src/fgas/localization/fgas_locale.h"
+
+class CFX_LCNumeric;
+
+class CFX_Locale : public IFX_Locale {
+ public:
+ CFX_Locale(CXML_Element* pLocaleData);
+ virtual void Release() { delete this; }
+
+ virtual CFX_WideString GetName();
+ virtual void GetNumbericSymbol(FX_LOCALENUMSYMBOL eType,
+ CFX_WideString& wsNumSymbol) const;
+
+ virtual void GetDateTimeSymbols(CFX_WideString& wsDtSymbol) const;
+ virtual void GetMonthName(int32_t nMonth,
+ CFX_WideString& wsMonthName,
+ FX_BOOL bAbbr = TRUE) const;
+ virtual void GetDayName(int32_t nWeek,
+ CFX_WideString& wsDayName,
+ FX_BOOL bAbbr = TRUE) const;
+ virtual void GetMeridiemName(CFX_WideString& wsMeridiemName,
+ FX_BOOL bAM = TRUE) const;
+ virtual void GetTimeZone(FX_TIMEZONE& tz) const;
+ virtual void GetEraName(CFX_WideString& wsEraName, FX_BOOL bAD = TRUE) const;
+
+ virtual void GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
+ CFX_WideString& wsPattern) const;
+ virtual void GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY eType,
+ CFX_WideString& wsPattern) const;
+ virtual void GetNumPattern(FX_LOCALENUMSUBCATEGORY eType,
+ CFX_WideString& wsPattern) const;
+
+ protected:
+ virtual ~CFX_Locale();
+ CXML_Element* m_pElement;
+};
+
+class CFX_FormatString : public IFX_FormatString {
+ public:
+ CFX_FormatString(IFX_LocaleMgr* pLocaleMgr, FX_BOOL bUseLCID);
+ virtual void Release() { delete this; }
+
+ virtual void SplitFormatString(const CFX_WideString& wsFormatString,
+ CFX_WideStringArray& wsPatterns);
+ virtual FX_LOCALECATEGORY GetCategory(const CFX_WideString& wsPattern);
+ virtual FX_WORD GetLCID(const CFX_WideString& wsPattern);
+ virtual CFX_WideString GetLocaleName(const CFX_WideString& wsPattern);
+ virtual FX_BOOL ParseText(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsValue);
+ virtual FX_BOOL ParseNum(const CFX_WideString& wsSrcNum,
+ const CFX_WideString& wsPattern,
+ FX_FLOAT& fValue);
+ virtual FX_BOOL ParseNum(const CFX_WideString& wsSrcNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsValue);
+ virtual FX_BOOL ParseDateTime(const CFX_WideString& wsSrcDateTime,
+ const CFX_WideString& wsPattern,
+ FX_DATETIMETYPE eDateTimeType,
+ CFX_Unitime& dtValue);
+ virtual FX_BOOL ParseZero(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern);
+ virtual FX_BOOL ParseNull(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern);
+ virtual FX_BOOL FormatText(const CFX_WideString& wsSrcText,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatNum(const CFX_WideString& wsSrcNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatNum(FX_FLOAT fNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatDateTime(const CFX_WideString& wsSrcDateTime,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatDateTime(const CFX_WideString& wsSrcDateTime,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput,
+ FX_DATETIMETYPE eDateTimeType);
+ virtual FX_BOOL FormatDateTime(const CFX_Unitime& dt,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatZero(const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput);
+ virtual FX_BOOL FormatNull(const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput);
+
+ protected:
+ virtual ~CFX_FormatString();
+ IFX_Locale* GetTextFormat(const CFX_WideString& wsPattern,
+ const CFX_WideStringC& wsCategory,
+ CFX_WideString& wsPurgePattern);
+ IFX_Locale* GetNumericFormat(const CFX_WideString& wsPattern,
+ int32_t& iDotIndex,
+ FX_DWORD& dwStyle,
+ CFX_WideString& wsPurgePattern);
+ FX_BOOL FormatStrNum(const CFX_WideStringC& wsInputNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput);
+ FX_BOOL FormatLCNumeric(CFX_LCNumeric& lcNum,
+ const CFX_WideString& wsPattern,
+ CFX_WideString& wsOutput);
+ FX_DATETIMETYPE GetDateTimeFormat(const CFX_WideString& wsPattern,
+ IFX_Locale*& pLocale,
+ CFX_WideString& wsDatePattern,
+ CFX_WideString& wsTimePattern);
+ IFX_Locale* GetPatternLocale(const CFX_WideStringC& wsLocale);
+ IFX_LocaleMgr* m_pLocaleMgr;
+ FX_BOOL m_bUseLCID;
+};
+
+#endif // XFA_SRC_FGAS_LOCALIZATION_FGAS_LOCALEIMP_H_
diff --git a/xfa/src/fgas/localization/fgas_localemgr.cpp b/xfa/src/fgas/localization/fgas_localemgr.cpp
new file mode 100644
index 0000000000..81dbfd3885
--- /dev/null
+++ b/xfa/src/fgas/localization/fgas_localemgr.cpp
@@ -0,0 +1,97 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/src/fgas/localization/fgas_localemgr.h"
+
+#include "core/include/fxcrt/fx_xml.h"
+
+IFX_LocaleMgr* FX_LocaleMgr_Create(const FX_WCHAR* pszLocalPath,
+ FX_WORD wDefaultLCID) {
+ void* pPathHandle = FX_OpenFolder(pszLocalPath);
+ if (!pPathHandle) {
+ return NULL;
+ }
+ CFX_LocaleMgr* pLocaleMgr = new CFX_LocaleMgr(wDefaultLCID);
+ CFX_WideString wsFileName;
+ FX_BOOL bFolder = FALSE;
+ while (FX_GetNextFile(pPathHandle, wsFileName, bFolder)) {
+ if (!bFolder) {
+ if (wsFileName.GetLength() < 4) {
+ continue;
+ }
+ CFX_WideString wsExt = wsFileName.Right(4);
+ wsExt.MakeLower();
+ if (wsExt != L".xml") {
+ continue;
+ }
+ CFX_WideString wsFullPath(pszLocalPath);
+ wsFullPath += L"\\" + wsFileName;
+ IFX_FileRead* pRead = FX_CreateFileRead(wsFullPath);
+ if (!pRead) {
+ continue;
+ }
+ CXML_Element* pXmlLocale = CXML_Element::Parse(pRead);
+ pRead->Release();
+ CFX_ByteString bssp = pXmlLocale->GetNamespace();
+ if (bssp == "http://www.foxitsoftware.com/localization") {
+ CFX_WideString wsLCID = pXmlLocale->GetAttrValue("", "lcid");
+ wchar_t* pEnd = NULL;
+ FX_DWORD dwLCID = wcstol(wsLCID, &pEnd, 16);
+ if (pLocaleMgr->m_lcid2xml.GetValueAt((void*)(uintptr_t)dwLCID)) {
+ delete pXmlLocale;
+ } else {
+ pLocaleMgr->m_lcid2xml.SetAt((void*)(uintptr_t)dwLCID, pXmlLocale);
+ }
+ } else {
+ delete pXmlLocale;
+ }
+ }
+ }
+ FX_CloseFolder(pPathHandle);
+ return pLocaleMgr;
+}
+CFX_LocaleMgr::CFX_LocaleMgr(FX_WORD wDefLCID) : m_wDefLCID(wDefLCID) {}
+CFX_LocaleMgr::~CFX_LocaleMgr() {
+ FX_POSITION ps = m_lcid2locale.GetStartPosition();
+ while (ps) {
+ void* plcid;
+ IFX_Locale* pLocale = NULL;
+ m_lcid2locale.GetNextAssoc(ps, plcid, (void*&)pLocale);
+ pLocale->Release();
+ }
+ m_lcid2locale.RemoveAll();
+ ps = m_lcid2xml.GetStartPosition();
+ while (ps) {
+ void* plcid;
+ CXML_Element* pxml = NULL;
+ m_lcid2xml.GetNextAssoc(ps, plcid, (void*&)pxml);
+ delete pxml;
+ }
+ m_lcid2xml.RemoveAll();
+}
+FX_WORD CFX_LocaleMgr::GetDefLocaleID() {
+ return m_wDefLCID;
+}
+IFX_Locale* CFX_LocaleMgr::GetDefLocale() {
+ return GetLocale(m_wDefLCID);
+}
+IFX_Locale* CFX_LocaleMgr::GetLocale(FX_WORD lcid) {
+ IFX_Locale* pLocale =
+ (IFX_Locale*)m_lcid2locale.GetValueAt((void*)(uintptr_t)lcid);
+ if (!pLocale) {
+ CXML_Element* pxml =
+ (CXML_Element*)m_lcid2xml.GetValueAt((void*)(uintptr_t)lcid);
+ if (pxml) {
+ pLocale = IFX_Locale::Create(pxml);
+ m_lcid2locale.SetAt((void*)(uintptr_t)lcid, pLocale);
+ }
+ }
+ return pLocale;
+}
+IFX_Locale* CFX_LocaleMgr::GetLocaleByName(
+ const CFX_WideStringC& wsLocaleName) {
+ return NULL;
+}
diff --git a/xfa/src/fgas/localization/fgas_localemgr.h b/xfa/src/fgas/localization/fgas_localemgr.h
new file mode 100644
index 0000000000..f2693c7f60
--- /dev/null
+++ b/xfa/src/fgas/localization/fgas_localemgr.h
@@ -0,0 +1,28 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef XFA_SRC_FGAS_LOCALIZATION_FGAS_LOCALEMGR_H_
+#define XFA_SRC_FGAS_LOCALIZATION_FGAS_LOCALEMGR_H_
+
+#include "xfa/src/fgas/localization/fgas_locale.h"
+
+class CFX_LocaleMgr : public IFX_LocaleMgr {
+ public:
+ CFX_LocaleMgr(FX_WORD wDefLCID);
+ virtual void Release() { delete this; }
+ virtual FX_WORD GetDefLocaleID();
+ virtual IFX_Locale* GetDefLocale();
+ virtual IFX_Locale* GetLocale(FX_WORD lcid);
+ virtual IFX_Locale* GetLocaleByName(const CFX_WideStringC& wsLocaleName);
+ CFX_MapPtrToPtr m_lcid2xml;
+
+ protected:
+ ~CFX_LocaleMgr();
+ CFX_MapPtrToPtr m_lcid2locale;
+ FX_WORD m_wDefLCID;
+};
+
+#endif // XFA_SRC_FGAS_LOCALIZATION_FGAS_LOCALEMGR_H_