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