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 "core/include/fxcrt/fx_basic.h"
8 #include "core/include/fxcrt/fx_ext.h"
9 
10 #include <cctype>
11 
12 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
13 #include <sys/types.h>
14 #include <dirent.h>
15 #else
16 #include <direct.h>
17 #endif
18 
~CFX_PrivateData()19 CFX_PrivateData::~CFX_PrivateData() {
20   ClearAll();
21 }
FreeData()22 void FX_PRIVATEDATA::FreeData() {
23   if (!m_pData) {
24     return;
25   }
26   if (m_bSelfDestruct) {
27     delete (CFX_DestructObject*)m_pData;
28   } else if (m_pCallback) {
29     m_pCallback(m_pData);
30   }
31 }
AddData(void * pModuleId,void * pData,PD_CALLBACK_FREEDATA callback,FX_BOOL bSelfDestruct)32 void CFX_PrivateData::AddData(void* pModuleId,
33                               void* pData,
34                               PD_CALLBACK_FREEDATA callback,
35                               FX_BOOL bSelfDestruct) {
36   if (!pModuleId) {
37     return;
38   }
39   FX_PRIVATEDATA* pList = m_DataList.GetData();
40   int count = m_DataList.GetSize();
41   for (int i = 0; i < count; i++) {
42     if (pList[i].m_pModuleId == pModuleId) {
43       pList[i].FreeData();
44       pList[i].m_pData = pData;
45       pList[i].m_pCallback = callback;
46       return;
47     }
48   }
49   FX_PRIVATEDATA data = {pModuleId, pData, callback, bSelfDestruct};
50   m_DataList.Add(data);
51 }
SetPrivateData(void * pModuleId,void * pData,PD_CALLBACK_FREEDATA callback)52 void CFX_PrivateData::SetPrivateData(void* pModuleId,
53                                      void* pData,
54                                      PD_CALLBACK_FREEDATA callback) {
55   AddData(pModuleId, pData, callback, FALSE);
56 }
SetPrivateObj(void * pModuleId,CFX_DestructObject * pObj)57 void CFX_PrivateData::SetPrivateObj(void* pModuleId, CFX_DestructObject* pObj) {
58   AddData(pModuleId, pObj, NULL, TRUE);
59 }
RemovePrivateData(void * pModuleId)60 FX_BOOL CFX_PrivateData::RemovePrivateData(void* pModuleId) {
61   if (!pModuleId) {
62     return FALSE;
63   }
64   FX_PRIVATEDATA* pList = m_DataList.GetData();
65   int count = m_DataList.GetSize();
66   for (int i = 0; i < count; i++) {
67     if (pList[i].m_pModuleId == pModuleId) {
68       m_DataList.RemoveAt(i);
69       return TRUE;
70     }
71   }
72   return FALSE;
73 }
GetPrivateData(void * pModuleId)74 void* CFX_PrivateData::GetPrivateData(void* pModuleId) {
75   if (!pModuleId) {
76     return NULL;
77   }
78   FX_PRIVATEDATA* pList = m_DataList.GetData();
79   int count = m_DataList.GetSize();
80   for (int i = 0; i < count; i++) {
81     if (pList[i].m_pModuleId == pModuleId) {
82       return pList[i].m_pData;
83     }
84   }
85   return NULL;
86 }
ClearAll()87 void CFX_PrivateData::ClearAll() {
88   FX_PRIVATEDATA* pList = m_DataList.GetData();
89   int count = m_DataList.GetSize();
90   for (int i = 0; i < count; i++) {
91     pList[i].FreeData();
92   }
93   m_DataList.RemoveAll();
94 }
FX_atonum(const CFX_ByteStringC & strc,FX_BOOL & bInteger,void * pData)95 void FX_atonum(const CFX_ByteStringC& strc, FX_BOOL& bInteger, void* pData) {
96   if (!FXSYS_memchr(strc.GetPtr(), '.', strc.GetLength())) {
97     bInteger = TRUE;
98     int cc = 0, integer = 0;
99     const FX_CHAR* str = strc.GetCStr();
100     int len = strc.GetLength();
101     FX_BOOL bNegative = FALSE;
102     if (str[0] == '+') {
103       cc++;
104     } else if (str[0] == '-') {
105       bNegative = TRUE;
106       cc++;
107     }
108     while (cc < len && std::isdigit(str[cc])) {
109       // TODO(dsinclair): This is not the right way to handle overflow.
110       integer = integer * 10 + FXSYS_toDecimalDigit(str[cc]);
111       if (integer < 0)
112         break;
113       cc++;
114     }
115     if (bNegative) {
116       integer = -integer;
117     }
118     *(int*)pData = integer;
119   } else {
120     bInteger = FALSE;
121     *(FX_FLOAT*)pData = FX_atof(strc);
122   }
123 }
FX_atof(const CFX_ByteStringC & strc)124 FX_FLOAT FX_atof(const CFX_ByteStringC& strc) {
125   if (strc.GetLength() == 0) {
126     return 0.0;
127   }
128   int cc = 0;
129   FX_BOOL bNegative = FALSE;
130   const FX_CHAR* str = strc.GetCStr();
131   int len = strc.GetLength();
132   if (str[0] == '+') {
133     cc++;
134   } else if (str[0] == '-') {
135     bNegative = TRUE;
136     cc++;
137   }
138   while (cc < len) {
139     if (str[cc] != '+' && str[cc] != '-') {
140       break;
141     }
142     cc++;
143   }
144   FX_FLOAT value = 0;
145   while (cc < len) {
146     if (str[cc] == '.') {
147       break;
148     }
149     value = value * 10 + FXSYS_toDecimalDigit(str[cc]);
150     cc++;
151   }
152   static const FX_FLOAT fraction_scales[] = {
153       0.1f,         0.01f,         0.001f,        0.0001f,
154       0.00001f,     0.000001f,     0.0000001f,    0.00000001f,
155       0.000000001f, 0.0000000001f, 0.00000000001f};
156   int scale = 0;
157   if (cc < len && str[cc] == '.') {
158     cc++;
159     while (cc < len) {
160       value += fraction_scales[scale] * FXSYS_toDecimalDigit(str[cc]);
161       scale++;
162       if (scale == sizeof fraction_scales / sizeof(FX_FLOAT)) {
163         break;
164       }
165       cc++;
166     }
167   }
168   return bNegative ? -value : value;
169 }
170 
171 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900
FXSYS_snprintf(char * str,size_t size,_Printf_format_string_ const char * fmt,...)172 void FXSYS_snprintf(char* str,
173                     size_t size,
174                     _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 }
FXSYS_vsnprintf(char * str,size_t size,const char * fmt,va_list ap)181 void FXSYS_vsnprintf(char* str, size_t size, const char* fmt, va_list ap) {
182   (void)_vsnprintf(str, size, fmt, ap);
183   if (size) {
184     str[size - 1] = 0;
185   }
186 }
187 #endif  // _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900
188 
189 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
190 class CFindFileData {
191  public:
~CFindFileData()192   virtual ~CFindFileData() {}
193   HANDLE m_Handle;
194   FX_BOOL m_bEnd;
195 };
196 class CFindFileDataA : public CFindFileData {
197  public:
~CFindFileDataA()198   virtual ~CFindFileDataA() {}
199   WIN32_FIND_DATAA m_FindData;
200 };
201 class CFindFileDataW : public CFindFileData {
202  public:
~CFindFileDataW()203   virtual ~CFindFileDataW() {}
204   WIN32_FIND_DATAW m_FindData;
205 };
206 #endif
FX_OpenFolder(const FX_CHAR * path)207 void* FX_OpenFolder(const FX_CHAR* path) {
208 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
209 #ifndef _WIN32_WCE
210   CFindFileDataA* pData = new CFindFileDataA;
211 #ifdef _FX_WINAPI_PARTITION_DESKTOP_
212   pData->m_Handle =
213       FindFirstFileA(CFX_ByteString(path) + "/*.*", &pData->m_FindData);
214 #else
215   pData->m_Handle =
216       FindFirstFileExA(CFX_ByteString(path) + "/*.*", FindExInfoStandard,
217                        &pData->m_FindData, FindExSearchNameMatch, NULL, 0);
218 #endif
219 #else
220   CFindFileDataW* pData = new CFindFileDataW;
221   pData->m_Handle = FindFirstFileW(CFX_WideString::FromLocal(path) + L"/*.*",
222                                    &pData->m_FindData);
223 #endif
224   if (pData->m_Handle == INVALID_HANDLE_VALUE) {
225     delete pData;
226     return NULL;
227   }
228   pData->m_bEnd = FALSE;
229   return pData;
230 #else
231   DIR* dir = opendir(path);
232   return dir;
233 #endif
234 }
FX_OpenFolder(const FX_WCHAR * path)235 void* FX_OpenFolder(const FX_WCHAR* path) {
236 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
237   CFindFileDataW* pData = new CFindFileDataW;
238 #ifdef _FX_WINAPI_PARTITION_DESKTOP_
239   pData->m_Handle = FindFirstFileW((CFX_WideString(path) + L"/*.*").c_str(),
240                                    &pData->m_FindData);
241 #else
242   pData->m_Handle = FindFirstFileExW((CFX_WideString(path) + L"/*.*").c_str(),
243                                      FindExInfoStandard, &pData->m_FindData,
244                                      FindExSearchNameMatch, NULL, 0);
245 #endif
246   if (pData->m_Handle == INVALID_HANDLE_VALUE) {
247     delete pData;
248     return NULL;
249   }
250   pData->m_bEnd = FALSE;
251   return pData;
252 #else
253   DIR* dir = opendir(CFX_ByteString::FromUnicode(path));
254   return dir;
255 #endif
256 }
FX_GetNextFile(void * handle,CFX_ByteString & filename,FX_BOOL & bFolder)257 FX_BOOL FX_GetNextFile(void* handle,
258                        CFX_ByteString& filename,
259                        FX_BOOL& bFolder) {
260   if (!handle) {
261     return FALSE;
262   }
263 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
264 #ifndef _WIN32_WCE
265   CFindFileDataA* pData = (CFindFileDataA*)handle;
266   if (pData->m_bEnd) {
267     return FALSE;
268   }
269   filename = pData->m_FindData.cFileName;
270   bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
271   if (!FindNextFileA(pData->m_Handle, &pData->m_FindData)) {
272     pData->m_bEnd = TRUE;
273   }
274   return TRUE;
275 #else
276   CFindFileDataW* pData = (CFindFileDataW*)handle;
277   if (pData->m_bEnd) {
278     return FALSE;
279   }
280   filename = CFX_ByteString::FromUnicode(pData->m_FindData.cFileName);
281   bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
282   if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
283     pData->m_bEnd = TRUE;
284   }
285   return TRUE;
286 #endif
287 #elif defined(__native_client__)
288   abort();
289   return FALSE;
290 #else
291   struct dirent* de = readdir((DIR*)handle);
292   if (!de) {
293     return FALSE;
294   }
295   filename = de->d_name;
296   bFolder = de->d_type == DT_DIR;
297   return TRUE;
298 #endif
299 }
FX_GetNextFile(void * handle,CFX_WideString & filename,FX_BOOL & bFolder)300 FX_BOOL FX_GetNextFile(void* handle,
301                        CFX_WideString& filename,
302                        FX_BOOL& bFolder) {
303   if (!handle) {
304     return FALSE;
305   }
306 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
307   CFindFileDataW* pData = (CFindFileDataW*)handle;
308   if (pData->m_bEnd) {
309     return FALSE;
310   }
311   filename = pData->m_FindData.cFileName;
312   bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
313   if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
314     pData->m_bEnd = TRUE;
315   }
316   return TRUE;
317 #elif defined(__native_client__)
318   abort();
319   return FALSE;
320 #else
321   struct dirent* de = readdir((DIR*)handle);
322   if (!de) {
323     return FALSE;
324   }
325   filename = CFX_WideString::FromLocal(de->d_name);
326   bFolder = de->d_type == DT_DIR;
327   return TRUE;
328 #endif
329 }
FX_CloseFolder(void * handle)330 void FX_CloseFolder(void* handle) {
331   if (!handle) {
332     return;
333   }
334 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
335   CFindFileData* pData = (CFindFileData*)handle;
336   FindClose(pData->m_Handle);
337   delete pData;
338 #else
339   closedir((DIR*)handle);
340 #endif
341 }
FX_GetFolderSeparator()342 FX_WCHAR FX_GetFolderSeparator() {
343 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
344   return '\\';
345 #else
346   return '/';
347 #endif
348 }
349 
Inverse()350 CFX_Matrix_3by3 CFX_Matrix_3by3::Inverse() {
351   FX_FLOAT det =
352       a * (e * i - f * h) - b * (i * d - f * g) + c * (d * h - e * g);
353   if (FXSYS_fabs(det) < 0.0000001)
354     return CFX_Matrix_3by3();
355 
356   return CFX_Matrix_3by3(
357       (e * i - f * h) / det, -(b * i - c * h) / det, (b * f - c * e) / det,
358       -(d * i - f * g) / det, (a * i - c * g) / det, -(a * f - c * d) / det,
359       (d * h - e * g) / det, -(a * h - b * g) / det, (a * e - b * d) / det);
360 }
361 
Multiply(const CFX_Matrix_3by3 & m)362 CFX_Matrix_3by3 CFX_Matrix_3by3::Multiply(const CFX_Matrix_3by3& m) {
363   return CFX_Matrix_3by3(
364       a * m.a + b * m.d + c * m.g, a * m.b + b * m.e + c * m.h,
365       a * m.c + b * m.f + c * m.i, d * m.a + e * m.d + f * m.g,
366       d * m.b + e * m.e + f * m.h, d * m.c + e * m.f + f * m.i,
367       g * m.a + h * m.d + i * m.g, g * m.b + h * m.e + i * m.h,
368       g * m.c + h * m.f + i * m.i);
369 }
370 
TransformVector(const CFX_Vector_3by1 & v)371 CFX_Vector_3by1 CFX_Matrix_3by3::TransformVector(const CFX_Vector_3by1& v) {
372   return CFX_Vector_3by1(a * v.a + b * v.b + c * v.c,
373                          d * v.a + e * v.b + f * v.c,
374                          g * v.a + h * v.b + i * v.c);
375 }
376