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