// 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 "core/fxcrt/fx_basic.h" #include "core/fxcrt/fx_ext.h" #include <algorithm> #include <cctype> #include <limits> #include <memory> bool FX_atonum(const CFX_ByteStringC& strc, void* pData) { if (strc.Find('.') != -1) { FX_FLOAT* pFloat = static_cast<FX_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_toDecimalDigit(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 FX_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); } FX_FLOAT FXSYS_FractionalScale(size_t scale_factor, int value) { return fraction_scales[scale_factor] * value; } FX_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++; } FX_FLOAT value = 0; while (cc < len) { if (strc[cc] == '.') break; value = value * 10 + FXSYS_toDecimalDigit(strc.CharAt(cc)); cc++; } int scale = 0; if (cc < len && strc[cc] == '.') { cc++; while (cc < len) { value += FXSYS_FractionalScale(scale, FXSYS_toDecimalDigit(strc.CharAt(cc))); scale++; if (scale == FXSYS_FractionalScaleCount()) break; cc++; } } return bNegative ? -value : value; } #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 FX_CHAR* path) { #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ std::unique_ptr<CFindFileDataA> pData(new 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 } FX_WCHAR FX_GetFolderSeparator() { #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ return '\\'; #else return '/'; #endif } CFX_Matrix_3by3 CFX_Matrix_3by3::Inverse() { FX_FLOAT det = a * (e * i - f * h) - b * (i * d - f * g) + c * (d * h - e * g); if (FXSYS_fabs(det) < 0.0000001) return CFX_Matrix_3by3(); return CFX_Matrix_3by3( (e * i - f * h) / det, -(b * i - c * h) / det, (b * f - c * e) / det, -(d * i - f * g) / det, (a * i - c * g) / det, -(a * f - c * d) / det, (d * h - e * g) / det, -(a * h - b * g) / det, (a * e - b * d) / det); } CFX_Matrix_3by3 CFX_Matrix_3by3::Multiply(const CFX_Matrix_3by3& m) { return CFX_Matrix_3by3( a * m.a + b * m.d + c * m.g, a * m.b + b * m.e + c * m.h, a * m.c + b * m.f + c * m.i, d * m.a + e * m.d + f * m.g, d * m.b + e * m.e + f * m.h, d * m.c + e * m.f + f * m.i, g * m.a + h * m.d + i * m.g, g * m.b + h * m.e + i * m.h, g * m.c + h * m.f + i * m.i); } CFX_Vector_3by1 CFX_Matrix_3by3::TransformVector(const CFX_Vector_3by1& v) { return CFX_Vector_3by1(a * v.a + b * v.b + c * v.c, d * v.a + e * v.b + f * v.c, g * v.a + h * v.b + i * v.c); } 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; }