diff options
Diffstat (limited to 'core/fxcrt')
-rw-r--r-- | core/fxcrt/cfx_datetime.cpp | 129 | ||||
-rw-r--r-- | core/fxcrt/cfx_datetime.h | 103 | ||||
-rw-r--r-- | core/fxcrt/cfx_decimal.cpp | 471 | ||||
-rw-r--r-- | core/fxcrt/cfx_decimal.h | 42 | ||||
-rw-r--r-- | core/fxcrt/ifx_locale.h | 76 |
5 files changed, 821 insertions, 0 deletions
diff --git a/core/fxcrt/cfx_datetime.cpp b/core/fxcrt/cfx_datetime.cpp new file mode 100644 index 0000000000..dcf25d5463 --- /dev/null +++ b/core/fxcrt/cfx_datetime.cpp @@ -0,0 +1,129 @@ +// 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/fxcrt/cfx_datetime.h" +#include "core/fxcrt/fx_system.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 + +namespace { + +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; + +int32_t DaysBeforeMonthInYear(int32_t iYear, uint8_t iMonth) { + ASSERT(iYear != 0); + ASSERT(iMonth >= 1 && iMonth <= 12); + + const int32_t* p = + FX_IsLeapYear(iYear) ? g_FXDaysBeforeLeapMonth : g_FXDaysBeforeMonth; + return p[iMonth - 1]; +} + +int32_t DaysInYear(int32_t iYear) { + ASSERT(iYear != 0); + return FX_IsLeapYear(iYear) ? g_FXDaysPerLeapYear : g_FXDaysPerYear; +} + +int64_t DateToDays(int32_t iYear, + uint8_t iMonth, + uint8_t iDay, + bool bIncludeThisDay) { + ASSERT(iYear != 0); + ASSERT(iMonth >= 1 && iMonth <= 12); + ASSERT(iDay >= 1 && iDay <= FX_DaysInMonth(iYear, iMonth)); + + int64_t iDays = DaysBeforeMonthInYear(iYear, iMonth); + iDays += iDay; + if (!bIncludeThisDay) + iDays--; + + if (iYear > 0) { + iYear--; + } else { + iDays -= DaysInYear(iYear); + iYear++; + } + return iDays + static_cast<int64_t>(iYear) * 365 + iYear / 4 - iYear / 100 + + iYear / 400; +} + +struct FXUT_SYSTEMTIME { + uint16_t wYear; + uint16_t wMonth; + uint16_t wDayOfWeek; + uint16_t wDay; + uint16_t wHour; + uint16_t wMinute; + uint16_t wSecond; + uint16_t wMillisecond; +}; + +} // namespace + +uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth) { + ASSERT(iYear != 0); + ASSERT(iMonth >= 1 && iMonth <= 12); + + const uint8_t* p = + FX_IsLeapYear(iYear) ? g_FXDaysPerLeapMonth : g_FXDaysPerMonth; + return p[iMonth - 1]; +} + +bool FX_IsLeapYear(int32_t iYear) { + ASSERT(iYear != 0); + return ((iYear % 4) == 0 && (iYear % 100) != 0) || (iYear % 400) == 0; +} + +void CFX_DateTime::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_ + timeval curTime; + gettimeofday(&curTime, nullptr); + + 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.wMillisecond = curTime.tv_usec / 1000; +#endif // _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN32_MOBILE_ || \ + // _FX_OS_ == _FX_WIN64_ + + year_ = utLocal.wYear; + month_ = static_cast<uint8_t>(utLocal.wMonth); + day_ = static_cast<uint8_t>(utLocal.wDay); + hour_ = static_cast<uint8_t>(utLocal.wHour); + minute_ = static_cast<uint8_t>(utLocal.wMinute); + second_ = static_cast<uint8_t>(utLocal.wSecond); + millisecond_ = static_cast<uint16_t>(utLocal.wMillisecond); +} + +int32_t CFX_DateTime::GetDayOfWeek() const { + int32_t v = static_cast<int32_t>(DateToDays(year_, month_, day_, true) % 7); + if (v < 0) + v += 7; + return v; +} diff --git a/core/fxcrt/cfx_datetime.h b/core/fxcrt/cfx_datetime.h new file mode 100644 index 0000000000..2de75c4e38 --- /dev/null +++ b/core/fxcrt/cfx_datetime.h @@ -0,0 +1,103 @@ +// 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 CORE_FXCRT_CFX_DATETIME_H_ +#define CORE_FXCRT_CFX_DATETIME_H_ + +#include "core/fxcrt/fx_system.h" + +bool FX_IsLeapYear(int32_t iYear); +uint8_t FX_DaysInMonth(int32_t iYear, uint8_t iMonth); + +class CFX_DateTime { + public: + CFX_DateTime() + : year_(0), + month_(0), + day_(0), + hour_(0), + minute_(0), + second_(0), + millisecond_(0) {} + CFX_DateTime(int32_t year, + uint8_t month, + uint8_t day, + uint8_t hour, + uint8_t minute, + uint8_t second, + uint16_t millisecond) + : year_(year), + month_(month), + day_(day), + hour_(hour), + minute_(minute), + second_(second), + millisecond_(millisecond) {} + + void Now(); + + void Reset() { + year_ = 0; + month_ = 0; + day_ = 0; + hour_ = 0; + minute_ = 0; + second_ = 0; + millisecond_ = 0; + } + + bool IsSet() const { + return year_ != 0 || month_ != 0 || day_ != 0 || hour_ != 0 || + minute_ != 0 || second_ != 0 || millisecond_ != 0; + } + + void SetDate(int32_t year, uint8_t month, uint8_t day) { + year_ = year; + month_ = month; + day_ = day; + } + + void SetTime(uint8_t hour, + uint8_t minute, + uint8_t second, + uint16_t millisecond) { + hour_ = hour; + minute_ = minute; + second_ = second; + millisecond_ = millisecond; + } + + int32_t GetYear() const { return year_; } + uint8_t GetMonth() const { return month_; } + uint8_t GetDay() const { return day_; } + uint8_t GetHour() const { return hour_; } + uint8_t GetMinute() const { return minute_; } + uint8_t GetSecond() const { return second_; } + uint16_t GetMillisecond() const { return millisecond_; } + int32_t GetDayOfWeek() const; + + private: + int32_t year_; + uint8_t month_; + uint8_t day_; + uint8_t hour_; + uint8_t minute_; + uint8_t second_; + uint16_t millisecond_; +}; + +#if _FX_OS_ != _FX_ANDROID_ +#pragma pack(push, 1) +#endif +struct FX_TIMEZONE { + int8_t tzHour; + uint8_t tzMinute; +}; +#if _FX_OS_ != _FX_ANDROID_ +#pragma pack(pop) +#endif + +#endif // CORE_FXCRT_CFX_DATETIME_H_ diff --git a/core/fxcrt/cfx_decimal.cpp b/core/fxcrt/cfx_decimal.cpp new file mode 100644 index 0000000000..1baa6896a3 --- /dev/null +++ b/core/fxcrt/cfx_decimal.cpp @@ -0,0 +1,471 @@ +// Copyright 2017 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/fxcrt/cfx_decimal.h" + +#include <algorithm> +#include <utility> + +#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) + +namespace { + +inline uint8_t 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; +} + +inline uint8_t 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; +} + +inline void 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; +} + +inline void 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]; + } +} + +inline void 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; +} + +inline void 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]; + } +} + +inline int8_t 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; +} + +inline void decimal_helper_dec_any(uint64_t a[], uint8_t al) { + for (int i = 0; i < al; i++) { + if (a[i]--) + return; + } +} + +inline void 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; + } +} + +inline void 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]; +} + +inline void decimal_helper_raw_div(uint64_t a[], + uint8_t al, + uint64_t b[], + uint8_t bl, + uint64_t c[], + uint8_t cl) { + for (int i = 0; i < cl; i++) + c[i] = 0; + + uint64_t left[16] = {0}; + uint64_t right[16] = {0}; + left[0] = 0; + for (int i = 0; i < al; i++) + right[i] = a[i]; + + uint64_t tmp[16]; + while (decimal_helper_raw_compare_any(left, al, right, al) <= 0) { + uint64_t cur[16]; + for (int i = 0; i < al; i++) + cur[i] = left[i] + right[i]; + + for (int i = al - 1; i >= 0; i--) { + if (i) + cur[i - 1] += FXMATH_DECIMAL_LSHIFT32BIT(cur[i] % 2); + cur[i] /= 2; + } + + decimal_helper_raw_mul(cur, al, b, bl, tmp, 16); + switch (decimal_helper_raw_compare_any(tmp, 16, a, al)) { + case -1: + for (int i = 0; i < 16; i++) + left[i] = cur[i]; + + left[0]++; + decimal_helper_normalize_any(left, al); + break; + case 1: + for (int i = 0; i < 16; i++) + right[i] = cur[i]; + decimal_helper_dec_any(right, al); + break; + case 0: + for (int i = 0; i < std::min(al, cl); i++) + c[i] = cur[i]; + return; + } + } + for (int i = 0; i < std::min(al, cl); i++) + c[i] = left[i]; +} + +inline bool 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; +} + +inline void decimal_helper_shrinkintorange(uint64_t a[], + uint8_t al, + uint8_t goal, + uint8_t& scale) { + bool bRoundUp = false; + while (scale != 0 && (scale > FXMATH_DECIMAL_SCALELIMIT || + decimal_helper_outofrange(a, al, goal))) { + bRoundUp = decimal_helper_div10_any(a, al) >= 5; + scale--; + } + if (bRoundUp) { + decimal_helper_normalize_any(a, goal); + decimal_helper_inc_any(a, goal); + } +} + +inline void 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 (decimal_helper_div10(thi, tmid, tlo) != 0) + break; + + phi = thi; + pmid = tmid; + plo = tlo; + scale--; + } +} + +} // namespace + +CFX_Decimal::CFX_Decimal() : m_uHi(0), m_uLo(0), m_uMid(0), m_uFlags(0) {} + +CFX_Decimal::CFX_Decimal(uint64_t val) + : m_uHi(0), + m_uLo(static_cast<uint32_t>(val)), + m_uMid(static_cast<uint32_t>(FXMATH_DECIMAL_RSHIFT32BIT(val))), + m_uFlags(0) {} + +CFX_Decimal::CFX_Decimal(uint32_t val) + : m_uHi(0), m_uLo(static_cast<uint32_t>(val)), m_uMid(0), m_uFlags(0) {} + +CFX_Decimal::CFX_Decimal(uint32_t lo, + uint32_t mid, + uint32_t hi, + bool neg, + uint8_t scale) + : m_uHi(hi), + m_uLo(lo), + m_uMid(mid), + m_uFlags(FXMATH_DECIMAL_MAKEFLAGS( + neg && IsNotZero(), + (scale > FXMATH_DECIMAL_SCALELIMIT ? 0 : scale))) {} + +CFX_Decimal::CFX_Decimal(int32_t val) { + if (val >= 0) { + *this = CFX_Decimal(static_cast<uint32_t>(val)); + } else { + *this = CFX_Decimal(static_cast<uint32_t>(-val)); + SetNegate(); + } +} + +CFX_Decimal::CFX_Decimal(float val, uint8_t scale) { + float newval = fabs(val); + uint64_t phi; + uint64_t pmid; + uint64_t plo; + plo = static_cast<uint64_t>(newval); + pmid = static_cast<uint64_t>(newval / 1e32); + phi = static_cast<uint64_t>(newval / 1e64); + newval = FXSYS_fmod(newval, 1.0f); + for (uint8_t iter = 0; iter < scale; iter++) { + decimal_helper_mul10(phi, pmid, plo); + newval *= 10; + plo += static_cast<uint64_t>(newval); + newval = FXSYS_fmod(newval, 1.0f); + } + + plo += FXSYS_round(newval); + decimal_helper_normalize(phi, pmid, plo); + m_uHi = static_cast<uint32_t>(phi); + m_uMid = static_cast<uint32_t>(pmid); + m_uLo = static_cast<uint32_t>(plo); + m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(val < 0 && IsNotZero(), scale); +} + +CFX_Decimal::CFX_Decimal(const CFX_WideStringC& strObj) { + const wchar_t* str = strObj.c_str(); + const wchar_t* strBound = str + strObj.GetLength(); + bool pointmet = false; + bool negmet = false; + uint8_t scale = 0; + m_uHi = 0; + m_uMid = 0; + 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) + 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++; + } + str++; + } + m_uFlags = FXMATH_DECIMAL_MAKEFLAGS(negmet && IsNotZero(), scale); +} + +CFX_Decimal::operator CFX_WideString() const { + CFX_WideString retString; + CFX_WideString tmpbuf; + uint64_t phi = m_uHi; + uint64_t pmid = m_uMid; + uint64_t plo = m_uLo; + while (phi || pmid || plo) + tmpbuf += 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 = static_cast<double>(m_uHi) * pow * pow + + static_cast<double>(m_uMid) * pow + static_cast<double>(m_uLo); + int8_t scale = FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); + 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; + uint64_t pmid = m_uMid; + uint64_t plo = m_uLo; + for (uint8_t iter = 0; iter < newscale - oldscale; iter++) + decimal_helper_mul10(phi, pmid, plo); + + m_uHi = static_cast<uint32_t>(phi); + m_uMid = static_cast<uint32_t>(pmid); + m_uLo = static_cast<uint32_t>(plo); + m_uFlags = FXMATH_DECIMAL_MAKEFLAGS( + FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale); + } else if (newscale < oldscale) { + uint64_t phi; + uint64_t pmid; + uint64_t plo; + phi = 0; + pmid = 0; + plo = 5; + for (uint8_t iter = 0; iter < oldscale - newscale - 1; iter++) + decimal_helper_mul10(phi, pmid, plo); + + phi += m_uHi; + pmid += m_uMid; + plo += m_uLo; + decimal_helper_normalize(phi, pmid, plo); + for (uint8_t iter = 0; iter < oldscale - newscale; iter++) + decimal_helper_div10(phi, pmid, plo); + + m_uHi = static_cast<uint32_t>(phi); + m_uMid = static_cast<uint32_t>(pmid); + m_uLo = static_cast<uint32_t>(plo); + m_uFlags = FXMATH_DECIMAL_MAKEFLAGS( + FXMATH_DECIMAL_FLAGS2NEG(m_uFlags) && IsNotZero(), newscale); + } +} + +uint8_t CFX_Decimal::GetScale() { + return FXMATH_DECIMAL_FLAGS2SCALE(m_uFlags); +} + +void CFX_Decimal::SetNegate() { + if (IsNotZero()) + m_uFlags ^= FXMATH_DECIMAL_NEGMASK; +} + +void CFX_Decimal::Swap(CFX_Decimal& val) { + std::swap(m_uHi, val.m_uHi); + std::swap(m_uMid, val.m_uMid); + std::swap(m_uLo, val.m_uLo); + std::swap(m_uFlags, val.m_uFlags); +} + +CFX_Decimal CFX_Decimal::operator*(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]; + decimal_helper_raw_mul(a, 3, b, 3, c, 6); + 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); + decimal_helper_shrinkintorange(c, 6, 3, scale); + return CFX_Decimal(static_cast<uint32_t>(c[0]), static_cast<uint32_t>(c[1]), + static_cast<uint32_t>(c[2]), neg, scale); +} + +CFX_Decimal CFX_Decimal::operator/(const CFX_Decimal& val) const { + if (!val.IsNotZero()) + return CFX_Decimal(); + + 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--) { + 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]) { + decimal_helper_mul10_any(a, 7); + scale++; + } + + decimal_helper_div10_any(a, 7); + scale--; + decimal_helper_raw_div(a, 6, b, 3, c, 7); + decimal_helper_shrinkintorange(c, 6, 3, scale); + decimal_helper_truncate(c[2], c[1], c[0], scale, minscale); + return CFX_Decimal(static_cast<uint32_t>(c[0]), static_cast<uint32_t>(c[1]), + static_cast<uint32_t>(c[2]), neg, scale); +} diff --git a/core/fxcrt/cfx_decimal.h b/core/fxcrt/cfx_decimal.h new file mode 100644 index 0000000000..544280444a --- /dev/null +++ b/core/fxcrt/cfx_decimal.h @@ -0,0 +1,42 @@ +// Copyright 2017 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 CORE_FXCRT_CFX_DECIMAL_H_ +#define CORE_FXCRT_CFX_DECIMAL_H_ + +#include "core/fxcrt/fx_string.h" + +class CFX_Decimal { + public: + CFX_Decimal(); + explicit CFX_Decimal(uint32_t val); + explicit CFX_Decimal(uint64_t val); + explicit CFX_Decimal(int32_t val); + CFX_Decimal(float val, uint8_t scale); + explicit CFX_Decimal(const CFX_WideStringC& str); + + operator CFX_WideString() const; + operator double() 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 SetNegate(); + + private: + CFX_Decimal(uint32_t hi, uint32_t mid, uint32_t lo, bool neg, uint8_t scale); + bool IsNotZero() const { return m_uHi || m_uMid || m_uLo; } + void Swap(CFX_Decimal& val); + + uint32_t m_uHi; + uint32_t m_uLo; + uint32_t m_uMid; + uint32_t m_uFlags; +}; + +#endif // CORE_FXCRT_CFX_DECIMAL_H_ diff --git a/core/fxcrt/ifx_locale.h b/core/fxcrt/ifx_locale.h new file mode 100644 index 0000000000..5039aec6f0 --- /dev/null +++ b/core/fxcrt/ifx_locale.h @@ -0,0 +1,76 @@ +// 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 CORE_FXCRT_IFX_LOCALE_H_ +#define CORE_FXCRT_IFX_LOCALE_H_ + +#include "core/fxcrt/cfx_datetime.h" +#include "core/fxcrt/fx_string.h" + +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: + virtual ~IFX_Locale() {} + + virtual CFX_WideString GetName() const = 0; + virtual CFX_WideString GetNumbericSymbol(FX_LOCALENUMSYMBOL eType) const = 0; + virtual CFX_WideString GetDateTimeSymbols() const = 0; + virtual CFX_WideString GetMonthName(int32_t nMonth, bool bAbbr) const = 0; + virtual CFX_WideString GetDayName(int32_t nWeek, bool bAbbr) const = 0; + virtual CFX_WideString GetMeridiemName(bool bAM) const = 0; + virtual FX_TIMEZONE GetTimeZone() const = 0; + virtual CFX_WideString GetEraName(bool bAD) const = 0; + virtual CFX_WideString GetDatePattern( + FX_LOCALEDATETIMESUBCATEGORY eType) const = 0; + virtual CFX_WideString GetTimePattern( + FX_LOCALEDATETIMESUBCATEGORY eType) const = 0; + virtual CFX_WideString GetNumPattern(FX_LOCALENUMSUBCATEGORY eType) const = 0; +}; + +#endif // CORE_FXCRT_IFX_LOCALE_H_ |