Home | History | Annotate | Download | only in fxcrt
      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