// 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 "../../include/fxcrt/fx_basic.h" #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ #include #include #else #include #endif CFX_PrivateData::~CFX_PrivateData() { ClearAll(); } void FX_PRIVATEDATA::FreeData() { if (m_pData == NULL) { return; } if (m_bSelfDestruct) { delete (CFX_DestructObject*)m_pData; } else if (m_pCallback) { m_pCallback(m_pData); } } void CFX_PrivateData::AddData(void* pModuleId, void* pData, PD_CALLBACK_FREEDATA callback, FX_BOOL bSelfDestruct) { if (pModuleId == NULL) { return; } FX_PRIVATEDATA* pList = m_DataList.GetData(); int count = m_DataList.GetSize(); for (int i = 0; i < count; i ++) { if (pList[i].m_pModuleId == pModuleId) { pList[i].FreeData(); pList[i].m_pData = pData; pList[i].m_pCallback = callback; return; } } FX_PRIVATEDATA data = {pModuleId, pData, callback, bSelfDestruct}; m_DataList.Add(data); } void CFX_PrivateData::SetPrivateData(void* pModuleId, void* pData, PD_CALLBACK_FREEDATA callback) { AddData(pModuleId, pData, callback, FALSE); } void CFX_PrivateData::SetPrivateObj(void* pModuleId, CFX_DestructObject* pObj) { AddData(pModuleId, pObj, NULL, TRUE); } FX_BOOL CFX_PrivateData::RemovePrivateData(void* pModuleId) { if (pModuleId == NULL) { return FALSE; } FX_PRIVATEDATA* pList = m_DataList.GetData(); int count = m_DataList.GetSize(); for (int i = 0; i < count; i ++) { if (pList[i].m_pModuleId == pModuleId) { m_DataList.RemoveAt(i); return TRUE; } } return FALSE; } void* CFX_PrivateData::GetPrivateData(void* pModuleId) { if (pModuleId == NULL) { return NULL; } FX_PRIVATEDATA* pList = m_DataList.GetData(); int count = m_DataList.GetSize(); for (int i = 0; i < count; i ++) { if (pList[i].m_pModuleId == pModuleId) { return pList[i].m_pData; } } return NULL; } void CFX_PrivateData::ClearAll() { FX_PRIVATEDATA* pList = m_DataList.GetData(); int count = m_DataList.GetSize(); for (int i = 0; i < count; i ++) { pList[i].FreeData(); } m_DataList.RemoveAll(); } void FX_atonum(const CFX_ByteStringC& strc, FX_BOOL& bInteger, void* pData) { if (FXSYS_memchr(strc.GetPtr(), '.', strc.GetLength()) == NULL) { bInteger = TRUE; int cc = 0, integer = 0; const FX_CHAR* str = strc.GetCStr(); int len = strc.GetLength(); FX_BOOL bNegative = FALSE; if (str[0] == '+') { cc++; } else if (str[0] == '-') { bNegative = TRUE; cc++; } while (cc < len) { if (str[cc] < '0' || str[cc] > '9') { break; } integer = integer * 10 + str[cc] - '0'; if (integer < 0) { break; } cc ++; } if (bNegative) { integer = -integer; } *(int*)pData = integer; } else { bInteger = FALSE; *(FX_FLOAT*)pData = FX_atof(strc); } } FX_FLOAT FX_atof(const CFX_ByteStringC& strc) { if (strc.GetLength() == 0) { return 0.0; } int cc = 0; FX_BOOL bNegative = FALSE; const FX_CHAR* str = strc.GetCStr(); int len = strc.GetLength(); if (str[0] == '+') { cc++; } else if (str[0] == '-') { bNegative = TRUE; cc++; } while (cc < len) { if (str[cc] != '+' && str[cc] != '-') { break; } cc ++; } FX_FLOAT value = 0; while (cc < len) { if (str[cc] == '.') { break; } value = value * 10 + str[cc] - '0'; cc ++; } 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 scale = 0; if (cc < len && str[cc] == '.') { cc ++; while (cc < len) { value += fraction_scales[scale] * (str[cc] - '0'); scale ++; if (scale == sizeof fraction_scales / sizeof(FX_FLOAT)) { 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 static FX_BOOL FX_IsDigit(uint8_t ch) { return (ch >= '0' && ch <= '9') ? TRUE : FALSE; } static FX_BOOL FX_IsXDigit(uint8_t ch) { return (FX_IsDigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) ? TRUE : FALSE; } static uint8_t FX_MakeUpper(uint8_t ch) { if (ch < 'a' || ch > 'z') { return ch; } return ch - 32; } static int FX_HexToI(uint8_t ch) { ch = FX_MakeUpper(ch); return FX_IsDigit(ch) ? (ch - '0') : (ch - 55); } static const unsigned char url_encodeTable[128] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, }; CFX_ByteString FX_UrlEncode(const CFX_WideString& wsUrl) { const char arDigits[] = "0123456789ABCDEF"; CFX_ByteString rUrl; int nLength = wsUrl.GetLength(); for (int i = 0; i < nLength; i++) { FX_DWORD word = wsUrl.GetAt(i); if (word > 0x7F || url_encodeTable[word] == 1) { CFX_ByteString bsUri = CFX_ByteString::FromUnicode((FX_WORD)word); int nByte = bsUri.GetLength(); for (int j = 0; j < nByte; j++) { rUrl += '%'; uint8_t code = bsUri.GetAt(j); rUrl += arDigits[code >> 4]; rUrl += arDigits[code & 0x0F]; } } else { rUrl += CFX_ByteString::FromUnicode((FX_WORD)word); } } return rUrl; } CFX_WideString FX_UrlDecode(const CFX_ByteString& bsUrl) { CFX_ByteString rUrl; int nLength = bsUrl.GetLength(); for (int i = 0; i < nLength; i++) { if (i < nLength - 2 && bsUrl[i] == '%' && FX_IsXDigit(bsUrl[i + 1]) && FX_IsXDigit(bsUrl[i + 2])) { rUrl += (FX_HexToI(bsUrl[i + 1]) << 4 | FX_HexToI(bsUrl[i + 2])); i += 2; } else { rUrl += bsUrl[i]; } } return CFX_WideString::FromLocal(rUrl); } CFX_ByteString FX_EncodeURI(const CFX_WideString& wsURI) { const char arDigits[] = "0123456789ABCDEF"; CFX_ByteString rURI; CFX_ByteString bsUri = wsURI.UTF8Encode(); int nLength = bsUri.GetLength(); for (int i = 0; i < nLength; i++) { uint8_t code = bsUri.GetAt(i); if (code > 0x7F || url_encodeTable[code] == 1) { rURI += '%'; rURI += arDigits[code >> 4]; rURI += arDigits[code & 0x0F]; } else { rURI += code; } } return rURI; } CFX_WideString FX_DecodeURI(const CFX_ByteString& bsURI) { CFX_ByteString rURI; int nLength = bsURI.GetLength(); for (int i = 0; i < nLength; i++) { if (i < nLength - 2 && bsURI[i] == '%' && FX_IsXDigit(bsURI[i + 1]) && FX_IsXDigit(bsURI[i + 2])) { rURI += (FX_HexToI(bsURI[i + 1]) << 4 | FX_HexToI(bsURI[i + 2])); i += 2; } else { rURI += bsURI[i]; } } return CFX_WideString::FromUTF8(rURI, rURI.GetLength()); } #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ class CFindFileData { public: virtual ~CFindFileData() {} HANDLE m_Handle; FX_BOOL m_bEnd; }; class CFindFileDataA : public CFindFileData { public: virtual ~CFindFileDataA() {} WIN32_FIND_DATAA m_FindData; }; class CFindFileDataW : public CFindFileData { public: virtual ~CFindFileDataW() {} WIN32_FIND_DATAW m_FindData; }; #endif void* FX_OpenFolder(const FX_CHAR* path) { #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ #ifndef _WIN32_WCE CFindFileDataA* pData = new CFindFileDataA; #ifdef _FX_WINAPI_PARTITION_DESKTOP_ pData->m_Handle = FindFirstFileA(CFX_ByteString(path) + "/*.*", &pData->m_FindData); #else pData->m_Handle = FindFirstFileExA(CFX_ByteString(path) + "/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0); #endif #else CFindFileDataW* pData = new CFindFileDataW; pData->m_Handle = FindFirstFileW(CFX_WideString::FromLocal(path) + L"/*.*", &pData->m_FindData); #endif if (pData->m_Handle == INVALID_HANDLE_VALUE) { delete pData; return NULL; } pData->m_bEnd = FALSE; return pData; #else DIR* dir = opendir(path); return dir; #endif } void* FX_OpenFolder(const FX_WCHAR* path) { #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ CFindFileDataW* pData = new CFindFileDataW; #ifdef _FX_WINAPI_PARTITION_DESKTOP_ pData->m_Handle = FindFirstFileW((CFX_WideString(path) + L"/*.*").c_str(), &pData->m_FindData); #else pData->m_Handle = FindFirstFileExW((CFX_WideString(path) + L"/*.*").c_str(), FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0); #endif if (pData->m_Handle == INVALID_HANDLE_VALUE) { delete pData; return NULL; } pData->m_bEnd = FALSE; return pData; #else DIR* dir = opendir(CFX_ByteString::FromUnicode(path)); return dir; #endif } FX_BOOL FX_GetNextFile(void* handle, CFX_ByteString& filename, FX_BOOL& bFolder) { if (handle == NULL) { return FALSE; } #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ #ifndef _WIN32_WCE CFindFileDataA* pData = (CFindFileDataA*)handle; if (pData->m_bEnd) { return FALSE; } filename = pData->m_FindData.cFileName; bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; if (!FindNextFileA(pData->m_Handle, &pData->m_FindData)) { pData->m_bEnd = TRUE; } return TRUE; #else CFindFileDataW* pData = (CFindFileDataW*)handle; if (pData->m_bEnd) { return FALSE; } filename = CFX_ByteString::FromUnicode(pData->m_FindData.cFileName); bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) { pData->m_bEnd = TRUE; } return TRUE; #endif #elif defined(__native_client__) abort(); return FALSE; #else struct dirent *de = readdir((DIR*)handle); if (de == NULL) { return FALSE; } filename = de->d_name; bFolder = de->d_type == DT_DIR; return TRUE; #endif } FX_BOOL FX_GetNextFile(void* handle, CFX_WideString& filename, FX_BOOL& bFolder) { if (handle == NULL) { return FALSE; } #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ CFindFileDataW* pData = (CFindFileDataW*)handle; if (pData->m_bEnd) { return FALSE; } filename = pData->m_FindData.cFileName; bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) { pData->m_bEnd = TRUE; } return TRUE; #elif defined(__native_client__) abort(); return FALSE; #else struct dirent *de = readdir((DIR*)handle); if (de == NULL) { return FALSE; } filename = CFX_WideString::FromLocal(de->d_name); bFolder = de->d_type == DT_DIR; return TRUE; #endif } void FX_CloseFolder(void* handle) { if (handle == NULL) { return; } #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ CFindFileData* pData = (CFindFileData*)handle; FindClose(pData->m_Handle); delete pData; #else closedir((DIR*)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(); else 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 ); }