Fix incorrect CPDFSDK_PageView::CountAnnots().
[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 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
188 class CFindFileData {
189  public:
190   virtual ~CFindFileData() {}
191   HANDLE m_Handle;
192   FX_BOOL m_bEnd;
193 };
194 class CFindFileDataA : public CFindFileData {
195  public:
196   virtual ~CFindFileDataA() {}
197   WIN32_FIND_DATAA m_FindData;
198 };
199 class CFindFileDataW : public CFindFileData {
200  public:
201   virtual ~CFindFileDataW() {}
202   WIN32_FIND_DATAW m_FindData;
203 };
204 #endif
205 void* FX_OpenFolder(const FX_CHAR* path) {
206 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
207 #ifndef _WIN32_WCE
208   CFindFileDataA* pData = new CFindFileDataA;
209 #ifdef _FX_WINAPI_PARTITION_DESKTOP_
210   pData->m_Handle =
211       FindFirstFileA(CFX_ByteString(path) + "/*.*", &pData->m_FindData);
212 #else
213   pData->m_Handle =
214       FindFirstFileExA(CFX_ByteString(path) + "/*.*", FindExInfoStandard,
215                        &pData->m_FindData, FindExSearchNameMatch, NULL, 0);
216 #endif
217 #else
218   CFindFileDataW* pData = new CFindFileDataW;
219   pData->m_Handle = FindFirstFileW(CFX_WideString::FromLocal(path) + L"/*.*",
220                                    &pData->m_FindData);
221 #endif
222   if (pData->m_Handle == INVALID_HANDLE_VALUE) {
223     delete pData;
224     return NULL;
225   }
226   pData->m_bEnd = FALSE;
227   return pData;
228 #else
229   DIR* dir = opendir(path);
230   return dir;
231 #endif
232 }
233 void* FX_OpenFolder(const FX_WCHAR* path) {
234 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
235   CFindFileDataW* pData = new CFindFileDataW;
236 #ifdef _FX_WINAPI_PARTITION_DESKTOP_
237   pData->m_Handle = FindFirstFileW((CFX_WideString(path) + L"/*.*").c_str(),
238                                    &pData->m_FindData);
239 #else
240   pData->m_Handle = FindFirstFileExW((CFX_WideString(path) + L"/*.*").c_str(),
241                                      FindExInfoStandard, &pData->m_FindData,
242                                      FindExSearchNameMatch, NULL, 0);
243 #endif
244   if (pData->m_Handle == INVALID_HANDLE_VALUE) {
245     delete pData;
246     return NULL;
247   }
248   pData->m_bEnd = FALSE;
249   return pData;
250 #else
251   DIR* dir = opendir(CFX_ByteString::FromUnicode(path));
252   return dir;
253 #endif
254 }
255 FX_BOOL FX_GetNextFile(void* handle,
256                        CFX_ByteString& filename,
257                        FX_BOOL& bFolder) {
258   if (handle == NULL) {
259     return FALSE;
260   }
261 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
262 #ifndef _WIN32_WCE
263   CFindFileDataA* pData = (CFindFileDataA*)handle;
264   if (pData->m_bEnd) {
265     return FALSE;
266   }
267   filename = pData->m_FindData.cFileName;
268   bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
269   if (!FindNextFileA(pData->m_Handle, &pData->m_FindData)) {
270     pData->m_bEnd = TRUE;
271   }
272   return TRUE;
273 #else
274   CFindFileDataW* pData = (CFindFileDataW*)handle;
275   if (pData->m_bEnd) {
276     return FALSE;
277   }
278   filename = CFX_ByteString::FromUnicode(pData->m_FindData.cFileName);
279   bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
280   if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
281     pData->m_bEnd = TRUE;
282   }
283   return TRUE;
284 #endif
285 #elif defined(__native_client__)
286   abort();
287   return FALSE;
288 #else
289   struct dirent* de = readdir((DIR*)handle);
290   if (de == NULL) {
291     return FALSE;
292   }
293   filename = de->d_name;
294   bFolder = de->d_type == DT_DIR;
295   return TRUE;
296 #endif
297 }
298 FX_BOOL FX_GetNextFile(void* handle,
299                        CFX_WideString& filename,
300                        FX_BOOL& bFolder) {
301   if (handle == NULL) {
302     return FALSE;
303   }
304 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
305   CFindFileDataW* pData = (CFindFileDataW*)handle;
306   if (pData->m_bEnd) {
307     return FALSE;
308   }
309   filename = pData->m_FindData.cFileName;
310   bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
311   if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
312     pData->m_bEnd = TRUE;
313   }
314   return TRUE;
315 #elif defined(__native_client__)
316   abort();
317   return FALSE;
318 #else
319   struct dirent* de = readdir((DIR*)handle);
320   if (de == NULL) {
321     return FALSE;
322   }
323   filename = CFX_WideString::FromLocal(de->d_name);
324   bFolder = de->d_type == DT_DIR;
325   return TRUE;
326 #endif
327 }
328 void FX_CloseFolder(void* handle) {
329   if (handle == NULL) {
330     return;
331   }
332 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
333   CFindFileData* pData = (CFindFileData*)handle;
334   FindClose(pData->m_Handle);
335   delete pData;
336 #else
337   closedir((DIR*)handle);
338 #endif
339 }
340 FX_WCHAR FX_GetFolderSeparator() {
341 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
342   return '\\';
343 #else
344   return '/';
345 #endif
346 }
347
348 CFX_Matrix_3by3 CFX_Matrix_3by3::Inverse() {
349   FX_FLOAT det =
350       a * (e * i - f * h) - b * (i * d - f * g) + c * (d * h - e * g);
351   if (FXSYS_fabs(det) < 0.0000001)
352     return CFX_Matrix_3by3();
353
354   return CFX_Matrix_3by3(
355       (e * i - f * h) / det, -(b * i - c * h) / det, (b * f - c * e) / det,
356       -(d * i - f * g) / det, (a * i - c * g) / det, -(a * f - c * d) / det,
357       (d * h - e * g) / det, -(a * h - b * g) / det, (a * e - b * d) / det);
358 }
359
360 CFX_Matrix_3by3 CFX_Matrix_3by3::Multiply(const CFX_Matrix_3by3& m) {
361   return CFX_Matrix_3by3(
362       a * m.a + b * m.d + c * m.g, a * m.b + b * m.e + c * m.h,
363       a * m.c + b * m.f + c * m.i, d * m.a + e * m.d + f * m.g,
364       d * m.b + e * m.e + f * m.h, d * m.c + e * m.f + f * m.i,
365       g * m.a + h * m.d + i * m.g, g * m.b + h * m.e + i * m.h,
366       g * m.c + h * m.f + i * m.i);
367 }
368
369 CFX_Vector_3by1 CFX_Matrix_3by3::TransformVector(const CFX_Vector_3by1& v) {
370   return CFX_Vector_3by1(a * v.a + b * v.b + c * v.c,
371                          d * v.a + e * v.b + f * v.c,
372                          g * v.a + h * v.b + i * v.c);
373 }