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 "../../include/fxcrt/fx_basic.h" 8#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ 9#include <sys/types.h> 10#include <dirent.h> 11#else 12#include <direct.h> 13#endif 14CFX_PrivateData::~CFX_PrivateData() 15{ 16 ClearAll(); 17} 18void FX_PRIVATEDATA::FreeData() 19{ 20 if (m_pData == NULL) { 21 return; 22 } 23 if (m_bSelfDestruct) { 24 delete (CFX_DestructObject*)m_pData; 25 } else if (m_pCallback) { 26 m_pCallback(m_pData); 27 } 28} 29void CFX_PrivateData::AddData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback, FX_BOOL bSelfDestruct) 30{ 31 if (pModuleId == NULL) { 32 return; 33 } 34 FX_PRIVATEDATA* pList = m_DataList.GetData(); 35 int count = m_DataList.GetSize(); 36 for (int i = 0; i < count; i ++) { 37 if (pList[i].m_pModuleId == pModuleId) { 38 pList[i].FreeData(); 39 pList[i].m_pData = pData; 40 pList[i].m_pCallback = callback; 41 return; 42 } 43 } 44 FX_PRIVATEDATA data = {pModuleId, pData, callback, bSelfDestruct}; 45 m_DataList.Add(data); 46} 47void CFX_PrivateData::SetPrivateData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback) 48{ 49 AddData(pModuleId, pData, callback, FALSE); 50} 51void CFX_PrivateData::SetPrivateObj(FX_LPVOID pModuleId, CFX_DestructObject* pObj) 52{ 53 AddData(pModuleId, pObj, NULL, TRUE); 54} 55FX_BOOL CFX_PrivateData::RemovePrivateData(FX_LPVOID pModuleId) 56{ 57 if (pModuleId == NULL) { 58 return FALSE; 59 } 60 FX_PRIVATEDATA* pList = m_DataList.GetData(); 61 int count = m_DataList.GetSize(); 62 for (int i = 0; i < count; i ++) { 63 if (pList[i].m_pModuleId == pModuleId) { 64 m_DataList.RemoveAt(i); 65 return TRUE; 66 } 67 } 68 return FALSE; 69} 70FX_LPVOID CFX_PrivateData::GetPrivateData(FX_LPVOID pModuleId) 71{ 72 if (pModuleId == NULL) { 73 return NULL; 74 } 75 FX_PRIVATEDATA* pList = m_DataList.GetData(); 76 int count = m_DataList.GetSize(); 77 for (int i = 0; i < count; i ++) { 78 if (pList[i].m_pModuleId == pModuleId) { 79 return pList[i].m_pData; 80 } 81 } 82 return NULL; 83} 84void CFX_PrivateData::ClearAll() 85{ 86 FX_PRIVATEDATA* pList = m_DataList.GetData(); 87 int count = m_DataList.GetSize(); 88 for (int i = 0; i < count; i ++) { 89 pList[i].FreeData(); 90 } 91 m_DataList.RemoveAll(); 92} 93void FX_atonum(FX_BSTR strc, FX_BOOL& bInteger, void* pData) 94{ 95 if (FXSYS_memchr(strc.GetPtr(), '.', strc.GetLength()) == NULL) { 96 bInteger = TRUE; 97 int cc = 0, integer = 0; 98 FX_LPCSTR str = strc.GetCStr(); 99 int len = strc.GetLength(); 100 FX_BOOL bNegative = FALSE; 101 if (str[0] == '+') { 102 cc++; 103 } else if (str[0] == '-') { 104 bNegative = TRUE; 105 cc++; 106 } 107 while (cc < len) { 108 if (str[cc] < '0' || str[cc] > '9') { 109 break; 110 } 111 integer = integer * 10 + str[cc] - '0'; 112 if (integer < 0) { 113 break; 114 } 115 cc ++; 116 } 117 if (bNegative) { 118 integer = -integer; 119 } 120 *(int*)pData = integer; 121 } else { 122 bInteger = FALSE; 123 *(FX_FLOAT*)pData = FX_atof(strc); 124 } 125} 126FX_FLOAT FX_atof(FX_BSTR strc) 127{ 128 if (strc.GetLength() == 0) { 129 return 0.0; 130 } 131 int cc = 0; 132 FX_BOOL bNegative = FALSE; 133 FX_LPCSTR str = strc.GetCStr(); 134 int len = strc.GetLength(); 135 if (str[0] == '+') { 136 cc++; 137 } else if (str[0] == '-') { 138 bNegative = TRUE; 139 cc++; 140 } 141 while (cc < len) { 142 if (str[cc] != '+' && str[cc] != '-') { 143 break; 144 } 145 cc ++; 146 } 147 FX_FLOAT value = 0; 148 while (cc < len) { 149 if (str[cc] == '.') { 150 break; 151 } 152 value = value * 10 + str[cc] - '0'; 153 cc ++; 154 } 155 static const FX_FLOAT fraction_scales[] = {0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 156 0.0000001f, 0.00000001f, 0.000000001f, 0.0000000001f, 0.00000000001f 157 }; 158 int scale = 0; 159 if (cc < len && str[cc] == '.') { 160 cc ++; 161 while (cc < len) { 162 value += fraction_scales[scale] * (str[cc] - '0'); 163 scale ++; 164 if (scale == sizeof fraction_scales / sizeof(FX_FLOAT)) { 165 break; 166 } 167 cc ++; 168 } 169 } 170 return bNegative ? -value : value; 171} 172 173#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900 174void FXSYS_snprintf(char *str, size_t size, _Printf_format_string_ const char* fmt, ...) 175{ 176 va_list ap; 177 va_start(ap, fmt); 178 FXSYS_vsnprintf(str, size, fmt, ap); 179 va_end(ap); 180} 181void FXSYS_vsnprintf(char *str, size_t size, const char* fmt, va_list ap) 182{ 183 (void) _vsnprintf(str, size, fmt, ap); 184 if (size) { 185 str[size - 1] = 0; 186 } 187} 188#endif // _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900 189 190static FX_BOOL FX_IsDigit(FX_BYTE ch) 191{ 192 return (ch >= '0' && ch <= '9') ? TRUE : FALSE; 193} 194static FX_BOOL FX_IsXDigit(FX_BYTE ch) 195{ 196 return (FX_IsDigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) ? TRUE : FALSE; 197} 198static FX_BYTE FX_MakeUpper(FX_BYTE ch) 199{ 200 if (ch < 'a' || ch > 'z') { 201 return ch; 202 } 203 return ch - 32; 204} 205static int FX_HexToI(FX_BYTE ch) 206{ 207 ch = FX_MakeUpper(ch); 208 return FX_IsDigit(ch) ? (ch - '0') : (ch - 55); 209} 210static const unsigned char url_encodeTable[128] = { 211 1, 1, 1, 1, 1, 1, 1, 1, 212 1, 1, 1, 1, 1, 1, 1, 1, 213 1, 1, 1, 1, 1, 1, 1, 1, 214 1, 1, 1, 1, 1, 1, 1, 1, 215 1, 0, 1, 1, 0, 1, 0, 0, 216 0, 0, 0, 0, 0, 0, 0, 0, 217 0, 0, 0, 0, 0, 0, 0, 0, 218 0, 0, 0, 0, 1, 0, 1, 0, 219 0, 0, 0, 0, 0, 0, 0, 0, 220 0, 0, 0, 0, 0, 0, 0, 0, 221 0, 0, 0, 0, 0, 0, 0, 0, 222 0, 0, 0, 1, 1, 1, 1, 0, 223 1, 0, 0, 0, 0, 0, 0, 0, 224 0, 0, 0, 0, 0, 0, 0, 0, 225 0, 0, 0, 0, 0, 0, 0, 0, 226 0, 0, 0, 1, 1, 1, 1, 1, 227}; 228CFX_ByteString FX_UrlEncode(const CFX_WideString& wsUrl) 229{ 230 const char arDigits[] = "0123456789ABCDEF"; 231 CFX_ByteString rUrl; 232 int nLength = wsUrl.GetLength(); 233 for (int i = 0; i < nLength; i++) { 234 FX_DWORD word = wsUrl.GetAt(i); 235 if (word > 0x7F || url_encodeTable[word] == 1) { 236 CFX_ByteString bsUri = CFX_ByteString::FromUnicode((FX_WORD)word); 237 int nByte = bsUri.GetLength(); 238 for (int j = 0; j < nByte; j++) { 239 rUrl += '%'; 240 FX_BYTE code = bsUri.GetAt(j); 241 rUrl += arDigits[code >> 4]; 242 rUrl += arDigits[code & 0x0F]; 243 } 244 } else { 245 rUrl += CFX_ByteString::FromUnicode((FX_WORD)word); 246 } 247 } 248 return rUrl; 249} 250CFX_WideString FX_UrlDecode(const CFX_ByteString& bsUrl) 251{ 252 CFX_ByteString rUrl; 253 int nLength = bsUrl.GetLength(); 254 for (int i = 0; i < nLength; i++) { 255 if (i < nLength - 2 && bsUrl[i] == '%' && FX_IsXDigit(bsUrl[i + 1]) && FX_IsXDigit(bsUrl[i + 2])) { 256 rUrl += (FX_HexToI(bsUrl[i + 1]) << 4 | FX_HexToI(bsUrl[i + 2])); 257 i += 2; 258 } else { 259 rUrl += bsUrl[i]; 260 } 261 } 262 return CFX_WideString::FromLocal(rUrl); 263} 264CFX_ByteString FX_EncodeURI(const CFX_WideString& wsURI) 265{ 266 const char arDigits[] = "0123456789ABCDEF"; 267 CFX_ByteString rURI; 268 CFX_ByteString bsUri = wsURI.UTF8Encode(); 269 int nLength = bsUri.GetLength(); 270 for (int i = 0; i < nLength; i++) { 271 FX_BYTE code = bsUri.GetAt(i); 272 if (code > 0x7F || url_encodeTable[code] == 1) { 273 rURI += '%'; 274 rURI += arDigits[code >> 4]; 275 rURI += arDigits[code & 0x0F]; 276 } else { 277 rURI += code; 278 } 279 } 280 return rURI; 281} 282CFX_WideString FX_DecodeURI(const CFX_ByteString& bsURI) 283{ 284 CFX_ByteString rURI; 285 int nLength = bsURI.GetLength(); 286 for (int i = 0; i < nLength; i++) { 287 if (i < nLength - 2 && bsURI[i] == '%' && FX_IsXDigit(bsURI[i + 1]) && FX_IsXDigit(bsURI[i + 2])) { 288 rURI += (FX_HexToI(bsURI[i + 1]) << 4 | FX_HexToI(bsURI[i + 2])); 289 i += 2; 290 } else { 291 rURI += bsURI[i]; 292 } 293 } 294 return CFX_WideString::FromUTF8(rURI, rURI.GetLength()); 295} 296#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 297class CFindFileData 298{ 299public: 300 virtual ~CFindFileData() {} 301 HANDLE m_Handle; 302 FX_BOOL m_bEnd; 303}; 304class CFindFileDataA : public CFindFileData 305{ 306public: 307 virtual ~CFindFileDataA() {} 308 WIN32_FIND_DATAA m_FindData; 309}; 310class CFindFileDataW : public CFindFileData 311{ 312public: 313 virtual ~CFindFileDataW() {} 314 WIN32_FIND_DATAW m_FindData; 315}; 316#endif 317void* FX_OpenFolder(FX_LPCSTR path) 318{ 319#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 320#ifndef _WIN32_WCE 321 CFindFileDataA* pData = new CFindFileDataA; 322#ifdef _FX_WINAPI_PARTITION_DESKTOP_ 323 pData->m_Handle = FindFirstFileA(CFX_ByteString(path) + "/*.*", &pData->m_FindData); 324#else 325 pData->m_Handle = FindFirstFileExA(CFX_ByteString(path) + "/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0); 326#endif 327#else 328 CFindFileDataW* pData = new CFindFileDataW; 329 pData->m_Handle = FindFirstFileW(CFX_WideString::FromLocal(path) + L"/*.*", &pData->m_FindData); 330#endif 331 if (pData->m_Handle == INVALID_HANDLE_VALUE) { 332 delete pData; 333 return NULL; 334 } 335 pData->m_bEnd = FALSE; 336 return pData; 337#else 338 DIR* dir = opendir(path); 339 return dir; 340#endif 341} 342void* FX_OpenFolder(FX_LPCWSTR path) 343{ 344#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 345 CFindFileDataW* pData = new CFindFileDataW; 346#ifdef _FX_WINAPI_PARTITION_DESKTOP_ 347 pData->m_Handle = FindFirstFileW((CFX_WideString(path) + L"/*.*").c_str(), &pData->m_FindData); 348#else 349 pData->m_Handle = FindFirstFileExW((CFX_WideString(path) + L"/*.*").c_str(), FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0); 350#endif 351 if (pData->m_Handle == INVALID_HANDLE_VALUE) { 352 delete pData; 353 return NULL; 354 } 355 pData->m_bEnd = FALSE; 356 return pData; 357#else 358 DIR* dir = opendir(CFX_ByteString::FromUnicode(path)); 359 return dir; 360#endif 361} 362FX_BOOL FX_GetNextFile(void* handle, CFX_ByteString& filename, FX_BOOL& bFolder) 363{ 364 if (handle == NULL) { 365 return FALSE; 366 } 367#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 368#ifndef _WIN32_WCE 369 CFindFileDataA* pData = (CFindFileDataA*)handle; 370 if (pData->m_bEnd) { 371 return FALSE; 372 } 373 filename = pData->m_FindData.cFileName; 374 bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; 375 if (!FindNextFileA(pData->m_Handle, &pData->m_FindData)) { 376 pData->m_bEnd = TRUE; 377 } 378 return TRUE; 379#else 380 CFindFileDataW* pData = (CFindFileDataW*)handle; 381 if (pData->m_bEnd) { 382 return FALSE; 383 } 384 filename = CFX_ByteString::FromUnicode(pData->m_FindData.cFileName); 385 bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; 386 if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) { 387 pData->m_bEnd = TRUE; 388 } 389 return TRUE; 390#endif 391#elif defined(__native_client__) 392 abort(); 393 return FALSE; 394#else 395 struct dirent *de = readdir((DIR*)handle); 396 if (de == NULL) { 397 return FALSE; 398 } 399 filename = de->d_name; 400 bFolder = de->d_type == DT_DIR; 401 return TRUE; 402#endif 403} 404FX_BOOL FX_GetNextFile(void* handle, CFX_WideString& filename, FX_BOOL& bFolder) 405{ 406 if (handle == NULL) { 407 return FALSE; 408 } 409#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 410 CFindFileDataW* pData = (CFindFileDataW*)handle; 411 if (pData->m_bEnd) { 412 return FALSE; 413 } 414 filename = pData->m_FindData.cFileName; 415 bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; 416 if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) { 417 pData->m_bEnd = TRUE; 418 } 419 return TRUE; 420#elif defined(__native_client__) 421 abort(); 422 return FALSE; 423#else 424 struct dirent *de = readdir((DIR*)handle); 425 if (de == NULL) { 426 return FALSE; 427 } 428 filename = CFX_WideString::FromLocal(de->d_name); 429 bFolder = de->d_type == DT_DIR; 430 return TRUE; 431#endif 432} 433void FX_CloseFolder(void* handle) 434{ 435 if (handle == NULL) { 436 return; 437 } 438#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 439 CFindFileData* pData = (CFindFileData*)handle; 440 FindClose(pData->m_Handle); 441 delete pData; 442#else 443 closedir((DIR*)handle); 444#endif 445} 446FX_WCHAR FX_GetFolderSeparator() 447{ 448#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 449 return '\\'; 450#else 451 return '/'; 452#endif 453} 454 455CFX_Matrix_3by3 CFX_Matrix_3by3::Inverse() 456{ 457 FX_FLOAT det = a*(e*i - f*h) - b*(i*d - f*g) + c*(d*h - e*g); 458 if (FXSYS_fabs(det) < 0.0000001) 459 return CFX_Matrix_3by3(); 460 else 461 return CFX_Matrix_3by3( 462 (e*i - f*h) / det, 463 -(b*i - c*h) / det, 464 (b*f - c*e) / det, 465 -(d*i - f*g) / det, 466 (a*i - c*g) / det, 467 -(a*f - c*d) / det, 468 (d*h - e*g) / det, 469 -(a*h - b*g) / det, 470 (a*e - b*d) / det 471 ); 472} 473 474CFX_Matrix_3by3 CFX_Matrix_3by3::Multiply(const CFX_Matrix_3by3 &m) 475{ 476 return CFX_Matrix_3by3( 477 a*m.a + b*m.d + c*m.g, 478 a*m.b + b*m.e + c*m.h, 479 a*m.c + b*m.f + c*m.i, 480 d*m.a + e*m.d + f*m.g, 481 d*m.b + e*m.e + f*m.h, 482 d*m.c + e*m.f + f*m.i, 483 g*m.a + h*m.d + i*m.g, 484 g*m.b + h*m.e + i*m.h, 485 g*m.c + h*m.f + i*m.i 486 ); 487} 488 489CFX_Vector_3by1 CFX_Matrix_3by3::TransformVector(const CFX_Vector_3by1 &v) 490{ 491 return CFX_Vector_3by1( 492 a * v.a + b * v.b + c * v.c, 493 d * v.a + e * v.b + f * v.c, 494 g * v.a + h * v.b + i * v.c 495 ); 496} 497