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 "../../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
     14 CFX_PrivateData::~CFX_PrivateData()
     15 {
     16     ClearAll();
     17 }
     18 void 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 }
     29 void 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 }
     47 void CFX_PrivateData::SetPrivateData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback)
     48 {
     49     AddData(pModuleId, pData, callback, FALSE);
     50 }
     51 void CFX_PrivateData::SetPrivateObj(FX_LPVOID pModuleId, CFX_DestructObject* pObj)
     52 {
     53     AddData(pModuleId, pObj, NULL, TRUE);
     54 }
     55 FX_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 }
     70 FX_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 }
     84 void 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 }
     93 void 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 }
    126 FX_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
    174 void 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 }
    181 void 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 
    190 static FX_BOOL FX_IsDigit(FX_BYTE ch)
    191 {
    192     return (ch >= '0' && ch <= '9') ? TRUE : FALSE;
    193 }
    194 static FX_BOOL FX_IsXDigit(FX_BYTE ch)
    195 {
    196     return (FX_IsDigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) ? TRUE : FALSE;
    197 }
    198 static FX_BYTE FX_MakeUpper(FX_BYTE ch)
    199 {
    200     if (ch < 'a' || ch > 'z') {
    201         return ch;
    202     }
    203     return ch - 32;
    204 }
    205 static int FX_HexToI(FX_BYTE ch)
    206 {
    207     ch = FX_MakeUpper(ch);
    208     return FX_IsDigit(ch) ? (ch - '0') : (ch - 55);
    209 }
    210 static 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 };
    228 CFX_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 }
    250 CFX_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 }
    264 CFX_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 }
    282 CFX_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_
    297 class CFindFileData
    298 {
    299 public:
    300     virtual ~CFindFileData() {}
    301     HANDLE				m_Handle;
    302     FX_BOOL				m_bEnd;
    303 };
    304 class CFindFileDataA : public CFindFileData
    305 {
    306 public:
    307     virtual ~CFindFileDataA() {}
    308     WIN32_FIND_DATAA	m_FindData;
    309 };
    310 class CFindFileDataW : public CFindFileData
    311 {
    312 public:
    313     virtual ~CFindFileDataW() {}
    314     WIN32_FIND_DATAW	m_FindData;
    315 };
    316 #endif
    317 void* 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 }
    342 void* 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 }
    362 FX_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 }
    404 FX_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 }
    433 void 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 }
    446 FX_WCHAR FX_GetFolderSeparator()
    447 {
    448 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    449     return '\\';
    450 #else
    451     return '/';
    452 #endif
    453 }
    454 
    455 CFX_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 
    474 CFX_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 
    489 CFX_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