1 // Copyright 2017 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 <limits>
8 #include <vector>
9
10 #include "core/fxcrt/fx_extension.h"
11 #include "core/fxcrt/fx_string.h"
12
13 namespace {
14
15 class CFX_UTF8Encoder {
16 public:
CFX_UTF8Encoder()17 CFX_UTF8Encoder() {}
~CFX_UTF8Encoder()18 ~CFX_UTF8Encoder() {}
19
Input(wchar_t unicodeAsWchar)20 void Input(wchar_t unicodeAsWchar) {
21 uint32_t unicode = static_cast<uint32_t>(unicodeAsWchar);
22 if (unicode < 0x80) {
23 m_Buffer.push_back(unicode);
24 } else {
25 if (unicode >= 0x80000000)
26 return;
27
28 int nbytes = 0;
29 if (unicode < 0x800)
30 nbytes = 2;
31 else if (unicode < 0x10000)
32 nbytes = 3;
33 else if (unicode < 0x200000)
34 nbytes = 4;
35 else if (unicode < 0x4000000)
36 nbytes = 5;
37 else
38 nbytes = 6;
39
40 static uint8_t prefix[] = {0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
41 int order = 1 << ((nbytes - 1) * 6);
42 int code = unicodeAsWchar;
43 m_Buffer.push_back(prefix[nbytes - 2] | (code / order));
44 for (int i = 0; i < nbytes - 1; i++) {
45 code = code % order;
46 order >>= 6;
47 m_Buffer.push_back(0x80 | (code / order));
48 }
49 }
50 }
51
52 // The data returned by GetResult() is invalidated when this is modified by
53 // appending any data.
GetResult() const54 ByteStringView GetResult() const {
55 return ByteStringView(m_Buffer.data(), m_Buffer.size());
56 }
57
58 private:
59 std::vector<uint8_t> m_Buffer;
60 };
61
62 } // namespace
63
FX_UTF8Encode(const WideStringView & wsStr)64 ByteString FX_UTF8Encode(const WideStringView& wsStr) {
65 size_t len = wsStr.GetLength();
66 const wchar_t* pStr = wsStr.unterminated_c_str();
67 CFX_UTF8Encoder encoder;
68 while (len-- > 0)
69 encoder.Input(*pStr++);
70
71 return ByteString(encoder.GetResult());
72 }
73
74 namespace {
75
76 const float fraction_scales[] = {0.1f, 0.01f, 0.001f,
77 0.0001f, 0.00001f, 0.000001f,
78 0.0000001f, 0.00000001f, 0.000000001f,
79 0.0000000001f, 0.00000000001f};
80
FractionalScale(size_t scale_factor,int value)81 float FractionalScale(size_t scale_factor, int value) {
82 return fraction_scales[scale_factor] * value;
83 }
84
85 } // namespace
86
FX_atonum(const ByteStringView & strc,void * pData)87 bool FX_atonum(const ByteStringView& strc, void* pData) {
88 if (strc.Contains('.')) {
89 float* pFloat = static_cast<float*>(pData);
90 *pFloat = FX_atof(strc);
91 return false;
92 }
93
94 // Note, numbers in PDF are typically of the form 123, -123, etc. But,
95 // for things like the Permissions on the encryption hash the number is
96 // actually an unsigned value. We use a uint32_t so we can deal with the
97 // unsigned and then check for overflow if the user actually signed the value.
98 // The Permissions flag is listed in Table 3.20 PDF 1.7 spec.
99 pdfium::base::CheckedNumeric<uint32_t> integer = 0;
100 bool bNegative = false;
101 bool bSigned = false;
102 size_t cc = 0;
103 if (strc[0] == '+') {
104 cc++;
105 bSigned = true;
106 } else if (strc[0] == '-') {
107 bNegative = true;
108 bSigned = true;
109 cc++;
110 }
111
112 while (cc < strc.GetLength() && std::isdigit(strc[cc])) {
113 integer = integer * 10 + FXSYS_DecimalCharToInt(strc.CharAt(cc));
114 if (!integer.IsValid())
115 break;
116 cc++;
117 }
118
119 // We have a sign, and the value was greater then a regular integer
120 // we've overflowed, reset to the default value.
121 if (bSigned) {
122 if (bNegative) {
123 if (integer.ValueOrDefault(0) >
124 static_cast<uint32_t>(std::numeric_limits<int>::max()) + 1) {
125 integer = 0;
126 }
127 } else if (integer.ValueOrDefault(0) >
128 static_cast<uint32_t>(std::numeric_limits<int>::max())) {
129 integer = 0;
130 }
131 }
132
133 // Switch back to the int space so we can flip to a negative if we need.
134 uint32_t uValue = integer.ValueOrDefault(0);
135 int32_t value = static_cast<int>(uValue);
136 if (bNegative)
137 value = -value;
138
139 int* pInt = static_cast<int*>(pData);
140 *pInt = value;
141 return true;
142 }
143
FX_atof(const ByteStringView & strc)144 float FX_atof(const ByteStringView& strc) {
145 if (strc.IsEmpty())
146 return 0.0;
147
148 int cc = 0;
149 bool bNegative = false;
150 int len = strc.GetLength();
151 if (strc[0] == '+') {
152 cc++;
153 } else if (strc[0] == '-') {
154 bNegative = true;
155 cc++;
156 }
157 while (cc < len) {
158 if (strc[cc] != '+' && strc[cc] != '-')
159 break;
160 cc++;
161 }
162 float value = 0;
163 while (cc < len) {
164 if (strc[cc] == '.')
165 break;
166 value = value * 10 + FXSYS_DecimalCharToInt(strc.CharAt(cc));
167 cc++;
168 }
169 int scale = 0;
170 if (cc < len && strc[cc] == '.') {
171 cc++;
172 while (cc < len) {
173 value += FractionalScale(scale, FXSYS_DecimalCharToInt(strc.CharAt(cc)));
174 scale++;
175 if (scale == FX_ArraySize(fraction_scales))
176 break;
177 cc++;
178 }
179 }
180 return bNegative ? -value : value;
181 }
182
FX_atof(const WideStringView & wsStr)183 float FX_atof(const WideStringView& wsStr) {
184 return FX_atof(FX_UTF8Encode(wsStr).c_str());
185 }
186
FX_ftoa(float d,char * buf)187 size_t FX_ftoa(float d, char* buf) {
188 buf[0] = '0';
189 buf[1] = '\0';
190 if (d == 0.0f) {
191 return 1;
192 }
193 bool bNegative = false;
194 if (d < 0) {
195 bNegative = true;
196 d = -d;
197 }
198 int scale = 1;
199 int scaled = FXSYS_round(d);
200 while (scaled < 100000) {
201 if (scale == 1000000) {
202 break;
203 }
204 scale *= 10;
205 scaled = FXSYS_round(d * scale);
206 }
207 if (scaled == 0) {
208 return 1;
209 }
210 char buf2[32];
211 size_t buf_size = 0;
212 if (bNegative) {
213 buf[buf_size++] = '-';
214 }
215 int i = scaled / scale;
216 FXSYS_itoa(i, buf2, 10);
217 size_t len = strlen(buf2);
218 memcpy(buf + buf_size, buf2, len);
219 buf_size += len;
220 int fraction = scaled % scale;
221 if (fraction == 0) {
222 return buf_size;
223 }
224 buf[buf_size++] = '.';
225 scale /= 10;
226 while (fraction) {
227 buf[buf_size++] = '0' + fraction / scale;
228 fraction %= scale;
229 scale /= 10;
230 }
231 return buf_size;
232 }
233