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