1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxcrt/fx_extension.h"
8 
9 #include <algorithm>
10 #include <cwctype>
11 #include <limits>
12 
13 #include "third_party/base/compiler_specific.h"
14 
15 namespace {
16 
DefaultTimeFunction()17 time_t DefaultTimeFunction() {
18   return time(nullptr);
19 }
20 
DefaultLocaltimeFunction(const time_t * tp)21 struct tm* DefaultLocaltimeFunction(const time_t* tp) {
22   return localtime(tp);
23 }
24 
25 time_t (*g_time_func)() = DefaultTimeFunction;
26 struct tm* (*g_localtime_func)(const time_t*) = DefaultLocaltimeFunction;
27 
28 }  // namespace
29 
FXSYS_wcstof(const wchar_t * pwsStr,int32_t iLength,int32_t * pUsedLen)30 float FXSYS_wcstof(const wchar_t* pwsStr, int32_t iLength, int32_t* pUsedLen) {
31   ASSERT(pwsStr);
32 
33   if (iLength < 0)
34     iLength = static_cast<int32_t>(wcslen(pwsStr));
35   if (iLength == 0)
36     return 0.0f;
37 
38   int32_t iUsedLen = 0;
39   bool bNegtive = false;
40   switch (pwsStr[iUsedLen]) {
41     case '-':
42       bNegtive = true;
43       FALLTHROUGH;
44     case '+':
45       iUsedLen++;
46       break;
47   }
48 
49   float fValue = 0.0f;
50   while (iUsedLen < iLength) {
51     wchar_t wch = pwsStr[iUsedLen];
52     if (!FXSYS_IsDecimalDigit(wch))
53       break;
54 
55     fValue = fValue * 10.0f + (wch - L'0');
56     iUsedLen++;
57   }
58 
59   if (iUsedLen < iLength && pwsStr[iUsedLen] == L'.') {
60     float fPrecise = 0.1f;
61     while (++iUsedLen < iLength) {
62       wchar_t wch = pwsStr[iUsedLen];
63       if (!FXSYS_IsDecimalDigit(wch))
64         break;
65 
66       fValue += (wch - L'0') * fPrecise;
67       fPrecise *= 0.1f;
68     }
69   }
70 
71   if (iUsedLen < iLength &&
72       (pwsStr[iUsedLen] == 'e' || pwsStr[iUsedLen] == 'E')) {
73     ++iUsedLen;
74 
75     bool negative_exponent = false;
76     if (iUsedLen < iLength &&
77         (pwsStr[iUsedLen] == '-' || pwsStr[iUsedLen] == '+')) {
78       negative_exponent = pwsStr[iUsedLen] == '-';
79       ++iUsedLen;
80     }
81 
82     int32_t exp_value = 0;
83     while (iUsedLen < iLength) {
84       wchar_t wch = pwsStr[iUsedLen];
85       if (!FXSYS_IsDecimalDigit(wch))
86         break;
87 
88       exp_value = exp_value * 10.0f + (wch - L'0');
89       // Exponent is outside the valid range, fail.
90       if ((negative_exponent &&
91            -exp_value < std::numeric_limits<float>::min_exponent10) ||
92           (!negative_exponent &&
93            exp_value > std::numeric_limits<float>::max_exponent10)) {
94         if (pUsedLen)
95           *pUsedLen = 0;
96         return 0.0f;
97       }
98 
99       ++iUsedLen;
100     }
101 
102     for (size_t i = exp_value; i > 0; --i) {
103       if (exp_value > 0) {
104         if (negative_exponent)
105           fValue /= 10;
106         else
107           fValue *= 10;
108       }
109     }
110   }
111 
112   if (pUsedLen)
113     *pUsedLen = iUsedLen;
114 
115   return bNegtive ? -fValue : fValue;
116 }
117 
FXSYS_wcsncpy(wchar_t * dstStr,const wchar_t * srcStr,size_t count)118 wchar_t* FXSYS_wcsncpy(wchar_t* dstStr, const wchar_t* srcStr, size_t count) {
119   ASSERT(dstStr);
120   ASSERT(srcStr);
121   ASSERT(count > 0);
122 
123   for (size_t i = 0; i < count; ++i)
124     if ((dstStr[i] = srcStr[i]) == L'\0')
125       break;
126   return dstStr;
127 }
128 
FXSYS_wcsnicmp(const wchar_t * s1,const wchar_t * s2,size_t count)129 int32_t FXSYS_wcsnicmp(const wchar_t* s1, const wchar_t* s2, size_t count) {
130   ASSERT(s1);
131   ASSERT(s2);
132   ASSERT(count > 0);
133 
134   wchar_t wch1 = 0, wch2 = 0;
135   while (count-- > 0) {
136     wch1 = static_cast<wchar_t>(FXSYS_towlower(*s1++));
137     wch2 = static_cast<wchar_t>(FXSYS_towlower(*s2++));
138     if (wch1 != wch2)
139       break;
140   }
141   return wch1 - wch2;
142 }
143 
FXSYS_IntToTwoHexChars(uint8_t n,char * buf)144 void FXSYS_IntToTwoHexChars(uint8_t n, char* buf) {
145   static const char kHex[] = "0123456789ABCDEF";
146   buf[0] = kHex[n / 16];
147   buf[1] = kHex[n % 16];
148 }
149 
FXSYS_IntToFourHexChars(uint16_t n,char * buf)150 void FXSYS_IntToFourHexChars(uint16_t n, char* buf) {
151   FXSYS_IntToTwoHexChars(n / 256, buf);
152   FXSYS_IntToTwoHexChars(n % 256, buf + 2);
153 }
154 
FXSYS_ToUTF16BE(uint32_t unicode,char * buf)155 size_t FXSYS_ToUTF16BE(uint32_t unicode, char* buf) {
156   ASSERT(unicode <= 0xD7FF || (unicode > 0xDFFF && unicode <= 0x10FFFF));
157   if (unicode <= 0xFFFF) {
158     FXSYS_IntToFourHexChars(unicode, buf);
159     return 4;
160   }
161   unicode -= 0x010000;
162   // High ten bits plus 0xD800
163   FXSYS_IntToFourHexChars(0xD800 + unicode / 0x400, buf);
164   // Low ten bits plus 0xDC00
165   FXSYS_IntToFourHexChars(0xDC00 + unicode % 0x400, buf + 4);
166   return 8;
167 }
168 
FXSYS_SetTimeFunction(time_t (* func)())169 void FXSYS_SetTimeFunction(time_t (*func)()) {
170   g_time_func = func ? func : DefaultTimeFunction;
171 }
172 
FXSYS_SetLocaltimeFunction(struct tm * (* func)(const time_t *))173 void FXSYS_SetLocaltimeFunction(struct tm* (*func)(const time_t*)) {
174   g_localtime_func = func ? func : DefaultLocaltimeFunction;
175 }
176 
FXSYS_time(time_t * tloc)177 time_t FXSYS_time(time_t* tloc) {
178   time_t ret_val = g_time_func();
179   if (tloc)
180     *tloc = ret_val;
181   return ret_val;
182 }
183 
FXSYS_localtime(const time_t * tp)184 struct tm* FXSYS_localtime(const time_t* tp) {
185   return g_localtime_func(tp);
186 }
187