clang-format all pdfium code.
[pdfium.git] / core / src / fxcrt / fx_extension.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 #include "../../include/fxcrt/fx_ext.h"
9 #include "extension.h"
10 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
11 #include <wincrypt.h>
12 #else
13 #include <ctime>
14 #endif
15
16 IFX_FileStream* FX_CreateFileStream(const FX_CHAR* filename, FX_DWORD dwModes) {
17   IFXCRT_FileAccess* pFA = FXCRT_FileAccess_Create();
18   if (!pFA) {
19     return NULL;
20   }
21   if (!pFA->Open(filename, dwModes)) {
22     pFA->Release();
23     return NULL;
24   }
25   return new CFX_CRTFileStream(pFA);
26 }
27 IFX_FileStream* FX_CreateFileStream(const FX_WCHAR* filename,
28                                     FX_DWORD dwModes) {
29   IFXCRT_FileAccess* pFA = FXCRT_FileAccess_Create();
30   if (!pFA) {
31     return NULL;
32   }
33   if (!pFA->Open(filename, dwModes)) {
34     pFA->Release();
35     return NULL;
36   }
37   return new CFX_CRTFileStream(pFA);
38 }
39 IFX_FileWrite* FX_CreateFileWrite(const FX_CHAR* filename) {
40   return FX_CreateFileStream(filename, FX_FILEMODE_Truncate);
41 }
42 IFX_FileWrite* FX_CreateFileWrite(const FX_WCHAR* filename) {
43   return FX_CreateFileStream(filename, FX_FILEMODE_Truncate);
44 }
45 IFX_FileRead* FX_CreateFileRead(const FX_CHAR* filename) {
46   return FX_CreateFileStream(filename, FX_FILEMODE_ReadOnly);
47 }
48 IFX_FileRead* FX_CreateFileRead(const FX_WCHAR* filename) {
49   return FX_CreateFileStream(filename, FX_FILEMODE_ReadOnly);
50 }
51 IFX_MemoryStream* FX_CreateMemoryStream(uint8_t* pBuffer,
52                                         size_t dwSize,
53                                         FX_BOOL bTakeOver) {
54   return new CFX_MemoryStream(pBuffer, dwSize, bTakeOver);
55 }
56 IFX_MemoryStream* FX_CreateMemoryStream(FX_BOOL bConsecutive) {
57   return new CFX_MemoryStream(bConsecutive);
58 }
59 #ifdef __cplusplus
60 extern "C" {
61 #endif
62 FX_FLOAT FXSYS_tan(FX_FLOAT a) {
63   return (FX_FLOAT)tan(a);
64 }
65 FX_FLOAT FXSYS_logb(FX_FLOAT b, FX_FLOAT x) {
66   return FXSYS_log(x) / FXSYS_log(b);
67 }
68 FX_FLOAT FXSYS_strtof(const FX_CHAR* pcsStr,
69                       int32_t iLength,
70                       int32_t* pUsedLen) {
71   FXSYS_assert(pcsStr != NULL);
72   if (iLength < 0) {
73     iLength = (int32_t)FXSYS_strlen(pcsStr);
74   }
75   CFX_WideString ws = CFX_WideString::FromLocal(pcsStr, iLength);
76   return FXSYS_wcstof(ws.c_str(), iLength, pUsedLen);
77 }
78 FX_FLOAT FXSYS_wcstof(const FX_WCHAR* pwsStr,
79                       int32_t iLength,
80                       int32_t* pUsedLen) {
81   FXSYS_assert(pwsStr != NULL);
82   if (iLength < 0) {
83     iLength = (int32_t)FXSYS_wcslen(pwsStr);
84   }
85   if (iLength == 0) {
86     return 0.0f;
87   }
88   int32_t iUsedLen = 0;
89   FX_BOOL bNegtive = FALSE;
90   switch (pwsStr[iUsedLen]) {
91     case '-':
92       bNegtive = TRUE;
93     case '+':
94       iUsedLen++;
95       break;
96   }
97   FX_FLOAT fValue = 0.0f;
98   while (iUsedLen < iLength) {
99     FX_WCHAR wch = pwsStr[iUsedLen];
100     if (wch >= L'0' && wch <= L'9') {
101       fValue = fValue * 10.0f + (wch - L'0');
102     } else {
103       break;
104     }
105     iUsedLen++;
106   }
107   if (iUsedLen < iLength && pwsStr[iUsedLen] == L'.') {
108     FX_FLOAT fPrecise = 0.1f;
109     while (++iUsedLen < iLength) {
110       FX_WCHAR wch = pwsStr[iUsedLen];
111       if (wch >= L'0' && wch <= L'9') {
112         fValue += (wch - L'0') * fPrecise;
113         fPrecise *= 0.1f;
114       } else {
115         break;
116       }
117     }
118   }
119   if (pUsedLen) {
120     *pUsedLen = iUsedLen;
121   }
122   return bNegtive ? -fValue : fValue;
123 }
124 FX_WCHAR* FXSYS_wcsncpy(FX_WCHAR* dstStr,
125                         const FX_WCHAR* srcStr,
126                         size_t count) {
127   FXSYS_assert(dstStr != NULL && srcStr != NULL && count > 0);
128   for (size_t i = 0; i < count; ++i)
129     if ((dstStr[i] = srcStr[i]) == L'\0') {
130       break;
131     }
132   return dstStr;
133 }
134 int32_t FXSYS_wcsnicmp(const FX_WCHAR* s1, const FX_WCHAR* s2, size_t count) {
135   FXSYS_assert(s1 != NULL && s2 != NULL && count > 0);
136   FX_WCHAR wch1 = 0, wch2 = 0;
137   while (count-- > 0) {
138     wch1 = (FX_WCHAR)FXSYS_tolower(*s1++);
139     wch2 = (FX_WCHAR)FXSYS_tolower(*s2++);
140     if (wch1 != wch2) {
141       break;
142     }
143   }
144   return wch1 - wch2;
145 }
146 int32_t FXSYS_strnicmp(const FX_CHAR* s1, const FX_CHAR* s2, size_t count) {
147   FXSYS_assert(s1 != NULL && s2 != NULL && count > 0);
148   FX_CHAR ch1 = 0, ch2 = 0;
149   while (count-- > 0) {
150     ch1 = (FX_CHAR)FXSYS_tolower(*s1++);
151     ch2 = (FX_CHAR)FXSYS_tolower(*s2++);
152     if (ch1 != ch2) {
153       break;
154     }
155   }
156   return ch1 - ch2;
157 }
158 FX_DWORD FX_HashCode_String_GetA(const FX_CHAR* pStr,
159                                  int32_t iLength,
160                                  FX_BOOL bIgnoreCase) {
161   FXSYS_assert(pStr != NULL);
162   if (iLength < 0) {
163     iLength = (int32_t)FXSYS_strlen(pStr);
164   }
165   const FX_CHAR* pStrEnd = pStr + iLength;
166   FX_DWORD dwHashCode = 0;
167   if (bIgnoreCase) {
168     while (pStr < pStrEnd) {
169       dwHashCode = 31 * dwHashCode + FXSYS_tolower(*pStr++);
170     }
171   } else {
172     while (pStr < pStrEnd) {
173       dwHashCode = 31 * dwHashCode + *pStr++;
174     }
175   }
176   return dwHashCode;
177 }
178 FX_DWORD FX_HashCode_String_GetW(const FX_WCHAR* pStr,
179                                  int32_t iLength,
180                                  FX_BOOL bIgnoreCase) {
181   FXSYS_assert(pStr != NULL);
182   if (iLength < 0) {
183     iLength = (int32_t)FXSYS_wcslen(pStr);
184   }
185   const FX_WCHAR* pStrEnd = pStr + iLength;
186   FX_DWORD dwHashCode = 0;
187   if (bIgnoreCase) {
188     while (pStr < pStrEnd) {
189       dwHashCode = 1313 * dwHashCode + FXSYS_tolower(*pStr++);
190     }
191   } else {
192     while (pStr < pStrEnd) {
193       dwHashCode = 1313 * dwHashCode + *pStr++;
194     }
195   }
196   return dwHashCode;
197 }
198 #ifdef __cplusplus
199 }
200 #endif
201 #ifdef __cplusplus
202 extern "C" {
203 #endif
204 void* FX_Random_MT_Start(FX_DWORD dwSeed) {
205   FX_LPMTRANDOMCONTEXT pContext = FX_Alloc(FX_MTRANDOMCONTEXT, 1);
206   pContext->mt[0] = dwSeed;
207   FX_DWORD& i = pContext->mti;
208   FX_DWORD* pBuf = pContext->mt;
209   for (i = 1; i < MT_N; i++) {
210     pBuf[i] = (1812433253UL * (pBuf[i - 1] ^ (pBuf[i - 1] >> 30)) + i);
211   }
212   pContext->bHaveSeed = TRUE;
213   return pContext;
214 }
215 FX_DWORD FX_Random_MT_Generate(void* pContext) {
216   FXSYS_assert(pContext != NULL);
217   FX_LPMTRANDOMCONTEXT pMTC = (FX_LPMTRANDOMCONTEXT)pContext;
218   FX_DWORD v;
219   static FX_DWORD mag[2] = {0, MT_Matrix_A};
220   FX_DWORD& mti = pMTC->mti;
221   FX_DWORD* pBuf = pMTC->mt;
222   if ((int)mti < 0 || mti >= MT_N) {
223     if (mti > MT_N && !pMTC->bHaveSeed) {
224       return 0;
225     }
226     FX_DWORD kk;
227     for (kk = 0; kk < MT_N - MT_M; kk++) {
228       v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask);
229       pBuf[kk] = pBuf[kk + MT_M] ^ (v >> 1) ^ mag[v & 1];
230     }
231     for (; kk < MT_N - 1; kk++) {
232       v = (pBuf[kk] & MT_Upper_Mask) | (pBuf[kk + 1] & MT_Lower_Mask);
233       pBuf[kk] = pBuf[kk + (MT_M - MT_N)] ^ (v >> 1) ^ mag[v & 1];
234     }
235     v = (pBuf[MT_N - 1] & MT_Upper_Mask) | (pBuf[0] & MT_Lower_Mask);
236     pBuf[MT_N - 1] = pBuf[MT_M - 1] ^ (v >> 1) ^ mag[v & 1];
237     mti = 0;
238   }
239   v = pBuf[mti++];
240   v ^= (v >> 11);
241   v ^= (v << 7) & 0x9d2c5680UL;
242   v ^= (v << 15) & 0xefc60000UL;
243   v ^= (v >> 18);
244   return v;
245 }
246 void FX_Random_MT_Close(void* pContext) {
247   FXSYS_assert(pContext != NULL);
248   FX_Free(pContext);
249 }
250 void FX_Random_GenerateMT(FX_DWORD* pBuffer, int32_t iCount) {
251   FX_DWORD dwSeed;
252 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
253   if (!FX_GenerateCryptoRandom(&dwSeed, 1)) {
254     FX_Random_GenerateBase(&dwSeed, 1);
255   }
256 #else
257   FX_Random_GenerateBase(&dwSeed, 1);
258 #endif
259   void* pContext = FX_Random_MT_Start(dwSeed);
260   while (iCount-- > 0) {
261     *pBuffer++ = FX_Random_MT_Generate(pContext);
262   }
263   FX_Random_MT_Close(pContext);
264 }
265 void FX_Random_GenerateBase(FX_DWORD* pBuffer, int32_t iCount) {
266 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
267   SYSTEMTIME st1, st2;
268   ::GetSystemTime(&st1);
269   do {
270     ::GetSystemTime(&st2);
271   } while (FXSYS_memcmp(&st1, &st2, sizeof(SYSTEMTIME)) == 0);
272   FX_DWORD dwHash1 =
273       FX_HashCode_String_GetA((const FX_CHAR*)&st1, sizeof(st1), TRUE);
274   FX_DWORD dwHash2 =
275       FX_HashCode_String_GetA((const FX_CHAR*)&st2, sizeof(st2), TRUE);
276   ::srand((dwHash1 << 16) | (FX_DWORD)dwHash2);
277 #else
278   time_t tmLast = time(NULL), tmCur;
279   while ((tmCur = time(NULL)) == tmLast)
280     ;
281   ::srand((tmCur << 16) | (tmLast & 0xFFFF));
282 #endif
283   while (iCount-- > 0) {
284     *pBuffer++ = (FX_DWORD)((::rand() << 16) | (::rand() & 0xFFFF));
285   }
286 }
287 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
288 FX_BOOL FX_GenerateCryptoRandom(FX_DWORD* pBuffer, int32_t iCount) {
289   HCRYPTPROV hCP = NULL;
290   if (!::CryptAcquireContext(&hCP, NULL, NULL, PROV_RSA_FULL, 0) ||
291       hCP == NULL) {
292     return FALSE;
293   }
294   ::CryptGenRandom(hCP, iCount * sizeof(FX_DWORD), (uint8_t*)pBuffer);
295   ::CryptReleaseContext(hCP, 0);
296   return TRUE;
297 }
298 #endif
299 void FX_Random_GenerateCrypto(FX_DWORD* pBuffer, int32_t iCount) {
300 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
301   FX_GenerateCryptoRandom(pBuffer, iCount);
302 #else
303   FX_Random_GenerateBase(pBuffer, iCount);
304 #endif
305 }
306 #ifdef __cplusplus
307 }
308 #endif