Kill CFX_Object.
[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(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 = FX_NEW CFindFileDataA;
322     if (!pData) {
323         return NULL;
324     }
325 #ifdef _FX_WINAPI_PARTITION_DESKTOP_
326     pData->m_Handle = FindFirstFileA(CFX_ByteString(path) + "/*.*", &pData->m_FindData);
327 #else
328     pData->m_Handle = FindFirstFileExA(CFX_ByteString(path) + "/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0);
329 #endif
330 #else
331     CFindFileDataW* pData = FX_NEW CFindFileDataW;
332     if (!pData) {
333         return NULL;
334     }
335     pData->m_Handle = FindFirstFileW(CFX_WideString::FromLocal(path) + L"/*.*", &pData->m_FindData);
336 #endif
337     if (pData->m_Handle == INVALID_HANDLE_VALUE) {
338         delete pData;
339         return NULL;
340     }
341     pData->m_bEnd = FALSE;
342     return pData;
343 #else
344     DIR* dir = opendir(path);
345     return dir;
346 #endif
347 }
348 void* FX_OpenFolder(FX_LPCWSTR path)
349 {
350 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
351     CFindFileDataW* pData = FX_NEW CFindFileDataW;
352     if (!pData) {
353         return NULL;
354     }
355 #ifdef _FX_WINAPI_PARTITION_DESKTOP_
356     pData->m_Handle = FindFirstFileW(CFX_WideString(path) + L"/*.*", &pData->m_FindData);
357 #else
358     pData->m_Handle = FindFirstFileExW(CFX_WideString(path) + L"/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0);
359 #endif
360     if (pData->m_Handle == INVALID_HANDLE_VALUE) {
361         delete pData;
362         return NULL;
363     }
364     pData->m_bEnd = FALSE;
365     return pData;
366 #else
367     DIR* dir = opendir(CFX_ByteString::FromUnicode(path));
368     return dir;
369 #endif
370 }
371 FX_BOOL FX_GetNextFile(void* handle, CFX_ByteString& filename, FX_BOOL& bFolder)
372 {
373     if (handle == NULL) {
374         return FALSE;
375     }
376 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
377 #ifndef _WIN32_WCE
378     CFindFileDataA* pData = (CFindFileDataA*)handle;
379     if (pData->m_bEnd) {
380         return FALSE;
381     }
382     filename = pData->m_FindData.cFileName;
383     bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
384     if (!FindNextFileA(pData->m_Handle, &pData->m_FindData)) {
385         pData->m_bEnd = TRUE;
386     }
387     return TRUE;
388 #else
389     CFindFileDataW* pData = (CFindFileDataW*)handle;
390     if (pData->m_bEnd) {
391         return FALSE;
392     }
393     filename = CFX_ByteString::FromUnicode(pData->m_FindData.cFileName);
394     bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
395     if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
396         pData->m_bEnd = TRUE;
397     }
398     return TRUE;
399 #endif
400 #elif defined(__native_client__)
401     abort();
402     return FALSE;
403 #else
404     struct dirent *de = readdir((DIR*)handle);
405     if (de == NULL) {
406         return FALSE;
407     }
408     filename = de->d_name;
409     bFolder = de->d_type == DT_DIR;
410     return TRUE;
411 #endif
412 }
413 FX_BOOL FX_GetNextFile(void* handle, CFX_WideString& filename, FX_BOOL& bFolder)
414 {
415     if (handle == NULL) {
416         return FALSE;
417     }
418 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
419     CFindFileDataW* pData = (CFindFileDataW*)handle;
420     if (pData->m_bEnd) {
421         return FALSE;
422     }
423     filename = pData->m_FindData.cFileName;
424     bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
425     if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
426         pData->m_bEnd = TRUE;
427     }
428     return TRUE;
429 #elif defined(__native_client__)
430     abort();
431     return FALSE;
432 #else
433     struct dirent *de = readdir((DIR*)handle);
434     if (de == NULL) {
435         return FALSE;
436     }
437     filename = CFX_WideString::FromLocal(de->d_name);
438     bFolder = de->d_type == DT_DIR;
439     return TRUE;
440 #endif
441 }
442 void FX_CloseFolder(void* handle)
443 {
444     if (handle == NULL) {
445         return;
446     }
447 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
448     CFindFileData* pData = (CFindFileData*)handle;
449     FindClose(pData->m_Handle);
450     delete pData;
451 #else
452     closedir((DIR*)handle);
453 #endif
454 }
455 FX_WCHAR FX_GetFolderSeparator()
456 {
457 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
458     return '\\';
459 #else
460     return '/';
461 #endif
462 }
463
464 CFX_Matrix_3by3 CFX_Matrix_3by3::Inverse()
465 {
466     FX_FLOAT det = a*(e*i - f*h) - b*(i*d - f*g) + c*(d*h - e*g);
467     if (FXSYS_fabs(det) < 0.0000001)
468         return CFX_Matrix_3by3();
469     else
470         return CFX_Matrix_3by3(
471             (e*i - f*h) / det,
472             -(b*i - c*h) / det,
473             (b*f - c*e) / det,
474             -(d*i - f*g) / det,
475             (a*i - c*g) / det,
476             -(a*f - c*d) / det,
477             (d*h - e*g) / det,
478             -(a*h - b*g) / det,
479             (a*e - b*d) / det
480         );
481 }
482
483 CFX_Matrix_3by3 CFX_Matrix_3by3::Multiply(const CFX_Matrix_3by3 &m)
484 {
485     return CFX_Matrix_3by3(
486         a*m.a + b*m.d + c*m.g,
487         a*m.b + b*m.e + c*m.h,
488         a*m.c + b*m.f + c*m.i,
489         d*m.a + e*m.d + f*m.g,
490         d*m.b + e*m.e + f*m.h,
491         d*m.c + e*m.f + f*m.i,
492         g*m.a + h*m.d + i*m.g,
493         g*m.b + h*m.e + i*m.h,
494         g*m.c + h*m.f + i*m.i
495       );
496 }
497
498 CFX_Vector_3by1 CFX_Matrix_3by3::TransformVector(const CFX_Vector_3by1 &v)
499 {
500     return CFX_Vector_3by1(
501         a * v.a + b * v.b + c * v.c,
502         d * v.a + e * v.b + f * v.c,
503         g * v.a + h * v.b + i * v.c
504     );
505 }