Use stdint.h types throughout PDFium.
[pdfium.git] / core / src / fxcrt / fx_basic_util.cpp
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(uint8_t ch)
191 {
192     return (ch >= '0' && ch <= '9') ? TRUE : FALSE;
193 }
194 static FX_BOOL FX_IsXDigit(uint8_t ch)
195 {
196     return (FX_IsDigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) ? TRUE : FALSE;
197 }
198 static uint8_t FX_MakeUpper(uint8_t ch)
199 {
200     if (ch < 'a' || ch > 'z') {
201         return ch;
202     }
203     return ch - 32;
204 }
205 static int FX_HexToI(uint8_t 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                 uint8_t 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         uint8_t 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 }