• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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