Home | History | Annotate | Download | only in fxcrt
      1 // Copyright 2014 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 "core/fxcrt/fx_basic.h"
      8 #include "core/fxcrt/fx_ext.h"
      9 
     10 #include <algorithm>
     11 #include <cctype>
     12 #include <limits>
     13 #include <memory>
     14 
     15 bool FX_atonum(const CFX_ByteStringC& strc, void* pData) {
     16   if (strc.Find('.') != -1) {
     17     FX_FLOAT* pFloat = static_cast<FX_FLOAT*>(pData);
     18     *pFloat = FX_atof(strc);
     19     return false;
     20   }
     21 
     22   // Note, numbers in PDF are typically of the form 123, -123, etc. But,
     23   // for things like the Permissions on the encryption hash the number is
     24   // actually an unsigned value. We use a uint32_t so we can deal with the
     25   // unsigned and then check for overflow if the user actually signed the value.
     26   // The Permissions flag is listed in Table 3.20 PDF 1.7 spec.
     27   pdfium::base::CheckedNumeric<uint32_t> integer = 0;
     28   bool bNegative = false;
     29   bool bSigned = false;
     30   int cc = 0;
     31   if (strc[0] == '+') {
     32     cc++;
     33     bSigned = true;
     34   } else if (strc[0] == '-') {
     35     bNegative = true;
     36     bSigned = true;
     37     cc++;
     38   }
     39 
     40   while (cc < strc.GetLength() && std::isdigit(strc[cc])) {
     41     integer = integer * 10 + FXSYS_toDecimalDigit(strc.CharAt(cc));
     42     if (!integer.IsValid())
     43       break;
     44     cc++;
     45   }
     46 
     47   // We have a sign, and the value was greater then a regular integer
     48   // we've overflowed, reset to the default value.
     49   if (bSigned) {
     50     if (bNegative) {
     51       if (integer.ValueOrDefault(0) >
     52           static_cast<uint32_t>(std::numeric_limits<int>::max()) + 1) {
     53         integer = 0;
     54       }
     55     } else if (integer.ValueOrDefault(0) >
     56                static_cast<uint32_t>(std::numeric_limits<int>::max())) {
     57       integer = 0;
     58     }
     59   }
     60 
     61   // Switch back to the int space so we can flip to a negative if we need.
     62   uint32_t uValue = integer.ValueOrDefault(0);
     63   int32_t value = static_cast<int>(uValue);
     64   if (bNegative)
     65     value = -value;
     66 
     67   int* pInt = static_cast<int*>(pData);
     68   *pInt = value;
     69   return true;
     70 }
     71 
     72 static const FX_FLOAT fraction_scales[] = {
     73     0.1f,         0.01f,         0.001f,        0.0001f,
     74     0.00001f,     0.000001f,     0.0000001f,    0.00000001f,
     75     0.000000001f, 0.0000000001f, 0.00000000001f};
     76 
     77 int FXSYS_FractionalScaleCount() {
     78   return FX_ArraySize(fraction_scales);
     79 }
     80 
     81 FX_FLOAT FXSYS_FractionalScale(size_t scale_factor, int value) {
     82   return fraction_scales[scale_factor] * value;
     83 }
     84 
     85 FX_FLOAT FX_atof(const CFX_ByteStringC& strc) {
     86   if (strc.IsEmpty())
     87     return 0.0;
     88 
     89   int cc = 0;
     90   bool bNegative = false;
     91   int len = strc.GetLength();
     92   if (strc[0] == '+') {
     93     cc++;
     94   } else if (strc[0] == '-') {
     95     bNegative = true;
     96     cc++;
     97   }
     98   while (cc < len) {
     99     if (strc[cc] != '+' && strc[cc] != '-')
    100       break;
    101     cc++;
    102   }
    103   FX_FLOAT value = 0;
    104   while (cc < len) {
    105     if (strc[cc] == '.')
    106       break;
    107     value = value * 10 + FXSYS_toDecimalDigit(strc.CharAt(cc));
    108     cc++;
    109   }
    110   int scale = 0;
    111   if (cc < len && strc[cc] == '.') {
    112     cc++;
    113     while (cc < len) {
    114       value +=
    115           FXSYS_FractionalScale(scale, FXSYS_toDecimalDigit(strc.CharAt(cc)));
    116       scale++;
    117       if (scale == FXSYS_FractionalScaleCount())
    118         break;
    119       cc++;
    120     }
    121   }
    122   return bNegative ? -value : value;
    123 }
    124 
    125 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900
    126 void FXSYS_snprintf(char* str,
    127                     size_t size,
    128                     _Printf_format_string_ const char* fmt,
    129                     ...) {
    130   va_list ap;
    131   va_start(ap, fmt);
    132   FXSYS_vsnprintf(str, size, fmt, ap);
    133   va_end(ap);
    134 }
    135 
    136 void FXSYS_vsnprintf(char* str, size_t size, const char* fmt, va_list ap) {
    137   (void)_vsnprintf(str, size, fmt, ap);
    138   if (size)
    139     str[size - 1] = 0;
    140 }
    141 #endif  // _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900
    142 
    143 FX_FileHandle* FX_OpenFolder(const FX_CHAR* path) {
    144 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    145   std::unique_ptr<CFindFileDataA> pData(new CFindFileDataA);
    146   pData->m_Handle = FindFirstFileExA((CFX_ByteString(path) + "/*.*").c_str(),
    147                                      FindExInfoStandard, &pData->m_FindData,
    148                                      FindExSearchNameMatch, nullptr, 0);
    149   if (pData->m_Handle == INVALID_HANDLE_VALUE)
    150     return nullptr;
    151 
    152   pData->m_bEnd = false;
    153   return pData.release();
    154 #else
    155   return opendir(path);
    156 #endif
    157 }
    158 
    159 bool FX_GetNextFile(FX_FileHandle* handle,
    160                     CFX_ByteString* filename,
    161                     bool* bFolder) {
    162   if (!handle)
    163     return false;
    164 
    165 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    166   if (handle->m_bEnd)
    167     return false;
    168 
    169   *filename = handle->m_FindData.cFileName;
    170   *bFolder =
    171       (handle->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
    172   if (!FindNextFileA(handle->m_Handle, &handle->m_FindData))
    173     handle->m_bEnd = true;
    174   return true;
    175 #elif defined(__native_client__)
    176   abort();
    177   return false;
    178 #else
    179   struct dirent* de = readdir(handle);
    180   if (!de)
    181     return false;
    182   *filename = de->d_name;
    183   *bFolder = de->d_type == DT_DIR;
    184   return true;
    185 #endif
    186 }
    187 
    188 void FX_CloseFolder(FX_FileHandle* handle) {
    189   if (!handle)
    190     return;
    191 
    192 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    193   FindClose(handle->m_Handle);
    194   delete handle;
    195 #else
    196   closedir(handle);
    197 #endif
    198 }
    199 
    200 FX_WCHAR FX_GetFolderSeparator() {
    201 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    202   return '\\';
    203 #else
    204   return '/';
    205 #endif
    206 }
    207 
    208 CFX_Matrix_3by3 CFX_Matrix_3by3::Inverse() {
    209   FX_FLOAT det =
    210       a * (e * i - f * h) - b * (i * d - f * g) + c * (d * h - e * g);
    211   if (FXSYS_fabs(det) < 0.0000001)
    212     return CFX_Matrix_3by3();
    213 
    214   return CFX_Matrix_3by3(
    215       (e * i - f * h) / det, -(b * i - c * h) / det, (b * f - c * e) / det,
    216       -(d * i - f * g) / det, (a * i - c * g) / det, -(a * f - c * d) / det,
    217       (d * h - e * g) / det, -(a * h - b * g) / det, (a * e - b * d) / det);
    218 }
    219 
    220 CFX_Matrix_3by3 CFX_Matrix_3by3::Multiply(const CFX_Matrix_3by3& m) {
    221   return CFX_Matrix_3by3(
    222       a * m.a + b * m.d + c * m.g, a * m.b + b * m.e + c * m.h,
    223       a * m.c + b * m.f + c * m.i, d * m.a + e * m.d + f * m.g,
    224       d * m.b + e * m.e + f * m.h, d * m.c + e * m.f + f * m.i,
    225       g * m.a + h * m.d + i * m.g, g * m.b + h * m.e + i * m.h,
    226       g * m.c + h * m.f + i * m.i);
    227 }
    228 
    229 CFX_Vector_3by1 CFX_Matrix_3by3::TransformVector(const CFX_Vector_3by1& v) {
    230   return CFX_Vector_3by1(a * v.a + b * v.b + c * v.c,
    231                          d * v.a + e * v.b + f * v.c,
    232                          g * v.a + h * v.b + i * v.c);
    233 }
    234 
    235 uint32_t GetBits32(const uint8_t* pData, int bitpos, int nbits) {
    236   ASSERT(0 < nbits && nbits <= 32);
    237   const uint8_t* dataPtr = &pData[bitpos / 8];
    238   int bitShift;
    239   int bitMask;
    240   int dstShift;
    241   int bitCount = bitpos & 0x07;
    242   if (nbits < 8 && nbits + bitCount <= 8) {
    243     bitShift = 8 - nbits - bitCount;
    244     bitMask = (1 << nbits) - 1;
    245     dstShift = 0;
    246   } else {
    247     bitShift = 0;
    248     int bitOffset = 8 - bitCount;
    249     bitMask = (1 << std::min(bitOffset, nbits)) - 1;
    250     dstShift = nbits - bitOffset;
    251   }
    252   uint32_t result =
    253       static_cast<uint32_t>((*dataPtr++ >> bitShift & bitMask) << dstShift);
    254   while (dstShift >= 8) {
    255     dstShift -= 8;
    256     result |= *dataPtr++ << dstShift;
    257   }
    258   if (dstShift > 0) {
    259     bitShift = 8 - dstShift;
    260     bitMask = (1 << dstShift) - 1;
    261     result |= *dataPtr++ >> bitShift & bitMask;
    262   }
    263   return result;
    264 }
    265