| // Copyright 2014 PDFium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| |
| #include <algorithm> |
| #include <cctype> |
| #include <limits> |
| #include <memory> |
| |
| #include "core/fxcrt/fx_basic.h" |
| #include "core/fxcrt/fx_extension.h" |
| #include "third_party/base/ptr_util.h" |
| |
| bool FX_atonum(const CFX_ByteStringC& strc, void* pData) { |
| if (strc.Find('.') != FX_STRNPOS) { |
| float* pFloat = static_cast<float*>(pData); |
| *pFloat = FX_atof(strc); |
| return false; |
| } |
| |
| // Note, numbers in PDF are typically of the form 123, -123, etc. But, |
| // for things like the Permissions on the encryption hash the number is |
| // actually an unsigned value. We use a uint32_t so we can deal with the |
| // unsigned and then check for overflow if the user actually signed the value. |
| // The Permissions flag is listed in Table 3.20 PDF 1.7 spec. |
| pdfium::base::CheckedNumeric<uint32_t> integer = 0; |
| bool bNegative = false; |
| bool bSigned = false; |
| int cc = 0; |
| if (strc[0] == '+') { |
| cc++; |
| bSigned = true; |
| } else if (strc[0] == '-') { |
| bNegative = true; |
| bSigned = true; |
| cc++; |
| } |
| |
| while (cc < strc.GetLength() && std::isdigit(strc[cc])) { |
| integer = integer * 10 + FXSYS_DecimalCharToInt(strc.CharAt(cc)); |
| if (!integer.IsValid()) |
| break; |
| cc++; |
| } |
| |
| // We have a sign, and the value was greater then a regular integer |
| // we've overflowed, reset to the default value. |
| if (bSigned) { |
| if (bNegative) { |
| if (integer.ValueOrDefault(0) > |
| static_cast<uint32_t>(std::numeric_limits<int>::max()) + 1) { |
| integer = 0; |
| } |
| } else if (integer.ValueOrDefault(0) > |
| static_cast<uint32_t>(std::numeric_limits<int>::max())) { |
| integer = 0; |
| } |
| } |
| |
| // Switch back to the int space so we can flip to a negative if we need. |
| uint32_t uValue = integer.ValueOrDefault(0); |
| int32_t value = static_cast<int>(uValue); |
| if (bNegative) |
| value = -value; |
| |
| int* pInt = static_cast<int*>(pData); |
| *pInt = value; |
| return true; |
| } |
| |
| static const float fraction_scales[] = { |
| 0.1f, 0.01f, 0.001f, 0.0001f, |
| 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, |
| 0.000000001f, 0.0000000001f, 0.00000000001f}; |
| |
| int FXSYS_FractionalScaleCount() { |
| return FX_ArraySize(fraction_scales); |
| } |
| |
| float FXSYS_FractionalScale(size_t scale_factor, int value) { |
| return fraction_scales[scale_factor] * value; |
| } |
| |
| float FX_atof(const CFX_ByteStringC& strc) { |
| if (strc.IsEmpty()) |
| return 0.0; |
| |
| int cc = 0; |
| bool bNegative = false; |
| int len = strc.GetLength(); |
| if (strc[0] == '+') { |
| cc++; |
| } else if (strc[0] == '-') { |
| bNegative = true; |
| cc++; |
| } |
| while (cc < len) { |
| if (strc[cc] != '+' && strc[cc] != '-') |
| break; |
| cc++; |
| } |
| float value = 0; |
| while (cc < len) { |
| if (strc[cc] == '.') |
| break; |
| value = value * 10 + FXSYS_DecimalCharToInt(strc.CharAt(cc)); |
| cc++; |
| } |
| int scale = 0; |
| if (cc < len && strc[cc] == '.') { |
| cc++; |
| while (cc < len) { |
| value += |
| FXSYS_FractionalScale(scale, FXSYS_DecimalCharToInt(strc.CharAt(cc))); |
| scale++; |
| if (scale == FXSYS_FractionalScaleCount()) |
| break; |
| cc++; |
| } |
| } |
| return bNegative ? -value : value; |
| } |
| |
| float FX_atof(const CFX_WideStringC& wsStr) { |
| return FX_atof(FX_UTF8Encode(wsStr).c_str()); |
| } |
| |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900 |
| void FXSYS_snprintf(char* str, |
| size_t size, |
| _Printf_format_string_ const char* fmt, |
| ...) { |
| va_list ap; |
| va_start(ap, fmt); |
| FXSYS_vsnprintf(str, size, fmt, ap); |
| va_end(ap); |
| } |
| |
| void FXSYS_vsnprintf(char* str, size_t size, const char* fmt, va_list ap) { |
| (void)_vsnprintf(str, size, fmt, ap); |
| if (size) |
| str[size - 1] = 0; |
| } |
| #endif // _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900 |
| |
| FX_FileHandle* FX_OpenFolder(const char* path) { |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ |
| auto pData = pdfium::MakeUnique<CFindFileDataA>(); |
| pData->m_Handle = FindFirstFileExA((CFX_ByteString(path) + "/*.*").c_str(), |
| FindExInfoStandard, &pData->m_FindData, |
| FindExSearchNameMatch, nullptr, 0); |
| if (pData->m_Handle == INVALID_HANDLE_VALUE) |
| return nullptr; |
| |
| pData->m_bEnd = false; |
| return pData.release(); |
| #else |
| return opendir(path); |
| #endif |
| } |
| |
| bool FX_GetNextFile(FX_FileHandle* handle, |
| CFX_ByteString* filename, |
| bool* bFolder) { |
| if (!handle) |
| return false; |
| |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ |
| if (handle->m_bEnd) |
| return false; |
| |
| *filename = handle->m_FindData.cFileName; |
| *bFolder = |
| (handle->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; |
| if (!FindNextFileA(handle->m_Handle, &handle->m_FindData)) |
| handle->m_bEnd = true; |
| return true; |
| #elif defined(__native_client__) |
| abort(); |
| return false; |
| #else |
| struct dirent* de = readdir(handle); |
| if (!de) |
| return false; |
| *filename = de->d_name; |
| *bFolder = de->d_type == DT_DIR; |
| return true; |
| #endif |
| } |
| |
| void FX_CloseFolder(FX_FileHandle* handle) { |
| if (!handle) |
| return; |
| |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ |
| FindClose(handle->m_Handle); |
| delete handle; |
| #else |
| closedir(handle); |
| #endif |
| } |
| |
| wchar_t FX_GetFolderSeparator() { |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ |
| return '\\'; |
| #else |
| return '/'; |
| #endif |
| } |
| |
| uint32_t GetBits32(const uint8_t* pData, int bitpos, int nbits) { |
| ASSERT(0 < nbits && nbits <= 32); |
| const uint8_t* dataPtr = &pData[bitpos / 8]; |
| int bitShift; |
| int bitMask; |
| int dstShift; |
| int bitCount = bitpos & 0x07; |
| if (nbits < 8 && nbits + bitCount <= 8) { |
| bitShift = 8 - nbits - bitCount; |
| bitMask = (1 << nbits) - 1; |
| dstShift = 0; |
| } else { |
| bitShift = 0; |
| int bitOffset = 8 - bitCount; |
| bitMask = (1 << std::min(bitOffset, nbits)) - 1; |
| dstShift = nbits - bitOffset; |
| } |
| uint32_t result = |
| static_cast<uint32_t>((*dataPtr++ >> bitShift & bitMask) << dstShift); |
| while (dstShift >= 8) { |
| dstShift -= 8; |
| result |= *dataPtr++ << dstShift; |
| } |
| if (dstShift > 0) { |
| bitShift = 8 - dstShift; |
| bitMask = (1 << dstShift) - 1; |
| result |= *dataPtr++ >> bitShift & bitMask; |
| } |
| return result; |
| } |