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: 17 CFX_UTF8Encoder() {} 18 ~CFX_UTF8Encoder() {} 19 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. 54 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 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 81 float FractionalScale(size_t scale_factor, int value) { 82 return fraction_scales[scale_factor] * value; 83 } 84 85 } // namespace 86 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 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 183 float FX_atof(const WideStringView& wsStr) { 184 return FX_atof(FX_UTF8Encode(wsStr).c_str()); 185 } 186 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