diff options
author | Aaron Seigo <aseigo@kde.org> | 2014-12-07 10:08:07 +0100 |
---|---|---|
committer | Aaron Seigo <aseigo@kde.org> | 2014-12-11 01:07:08 +0100 |
commit | 9ee8378d393778ac67314be7ea8d5bcbaeee9ee0 (patch) | |
tree | cf93471a69f9f4bbb4940de55ae134106fcd8380 /common/unqlite/jx9_lib.c | |
parent | ee6f068dff6b15441e553ffbfb2bf8aa97b26f57 (diff) | |
download | sink-9ee8378d393778ac67314be7ea8d5bcbaeee9ee0.tar.gz sink-9ee8378d393778ac67314be7ea8d5bcbaeee9ee0.zip |
try out unqlite
Diffstat (limited to 'common/unqlite/jx9_lib.c')
-rw-r--r-- | common/unqlite/jx9_lib.c | 4387 |
1 files changed, 4387 insertions, 0 deletions
diff --git a/common/unqlite/jx9_lib.c b/common/unqlite/jx9_lib.c new file mode 100644 index 0000000..9f3bcb2 --- /dev/null +++ b/common/unqlite/jx9_lib.c | |||
@@ -0,0 +1,4387 @@ | |||
1 | /* | ||
2 | * Symisc JX9: A Highly Efficient Embeddable Scripting Engine Based on JSON. | ||
3 | * Copyright (C) 2012-2013, Symisc Systems http://jx9.symisc.net/ | ||
4 | * Version 1.7.2 | ||
5 | * For information on licensing, redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES | ||
6 | * please contact Symisc Systems via: | ||
7 | * legal@symisc.net | ||
8 | * licensing@symisc.net | ||
9 | * contact@symisc.net | ||
10 | * or visit: | ||
11 | * http://jx9.symisc.net/ | ||
12 | */ | ||
13 | /* $SymiscID: lib.c v5.1 Win7 2012-08-08 04:19 stable <chm@symisc.net> $ */ | ||
14 | /* | ||
15 | * Symisc Run-Time API: A modern thread safe replacement of the standard libc | ||
16 | * Copyright (C) Symisc Systems 2007-2012, http://www.symisc.net/ | ||
17 | * | ||
18 | * The Symisc Run-Time API is an independent project developed by symisc systems | ||
19 | * internally as a secure replacement of the standard libc. | ||
20 | * The library is re-entrant, thread-safe and platform independent. | ||
21 | */ | ||
22 | #ifndef JX9_AMALGAMATION | ||
23 | #include "jx9Int.h" | ||
24 | #endif | ||
25 | #if defined(__WINNT__) | ||
26 | #include <Windows.h> | ||
27 | #else | ||
28 | #include <stdlib.h> | ||
29 | #endif | ||
30 | #if defined(JX9_ENABLE_THREADS) | ||
31 | /* SyRunTimeApi: sxmutex.c */ | ||
32 | #if defined(__WINNT__) | ||
33 | struct SyMutex | ||
34 | { | ||
35 | CRITICAL_SECTION sMutex; | ||
36 | sxu32 nType; /* Mutex type, one of SXMUTEX_TYPE_* */ | ||
37 | }; | ||
38 | /* Preallocated static mutex */ | ||
39 | static SyMutex aStaticMutexes[] = { | ||
40 | {{0}, SXMUTEX_TYPE_STATIC_1}, | ||
41 | {{0}, SXMUTEX_TYPE_STATIC_2}, | ||
42 | {{0}, SXMUTEX_TYPE_STATIC_3}, | ||
43 | {{0}, SXMUTEX_TYPE_STATIC_4}, | ||
44 | {{0}, SXMUTEX_TYPE_STATIC_5}, | ||
45 | {{0}, SXMUTEX_TYPE_STATIC_6} | ||
46 | }; | ||
47 | static BOOL winMutexInit = FALSE; | ||
48 | static LONG winMutexLock = 0; | ||
49 | |||
50 | static sxi32 WinMutexGlobaInit(void) | ||
51 | { | ||
52 | LONG rc; | ||
53 | rc = InterlockedCompareExchange(&winMutexLock, 1, 0); | ||
54 | if ( rc == 0 ){ | ||
55 | sxu32 n; | ||
56 | for( n = 0 ; n < SX_ARRAYSIZE(aStaticMutexes) ; ++n ){ | ||
57 | InitializeCriticalSection(&aStaticMutexes[n].sMutex); | ||
58 | } | ||
59 | winMutexInit = TRUE; | ||
60 | }else{ | ||
61 | /* Someone else is doing this for us */ | ||
62 | while( winMutexInit == FALSE ){ | ||
63 | Sleep(1); | ||
64 | } | ||
65 | } | ||
66 | return SXRET_OK; | ||
67 | } | ||
68 | static void WinMutexGlobalRelease(void) | ||
69 | { | ||
70 | LONG rc; | ||
71 | rc = InterlockedCompareExchange(&winMutexLock, 0, 1); | ||
72 | if( rc == 1 ){ | ||
73 | /* The first to decrement to zero does the actual global release */ | ||
74 | if( winMutexInit == TRUE ){ | ||
75 | sxu32 n; | ||
76 | for( n = 0 ; n < SX_ARRAYSIZE(aStaticMutexes) ; ++n ){ | ||
77 | DeleteCriticalSection(&aStaticMutexes[n].sMutex); | ||
78 | } | ||
79 | winMutexInit = FALSE; | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | static SyMutex * WinMutexNew(int nType) | ||
84 | { | ||
85 | SyMutex *pMutex = 0; | ||
86 | if( nType == SXMUTEX_TYPE_FAST || nType == SXMUTEX_TYPE_RECURSIVE ){ | ||
87 | /* Allocate a new mutex */ | ||
88 | pMutex = (SyMutex *)HeapAlloc(GetProcessHeap(), 0, sizeof(SyMutex)); | ||
89 | if( pMutex == 0 ){ | ||
90 | return 0; | ||
91 | } | ||
92 | InitializeCriticalSection(&pMutex->sMutex); | ||
93 | }else{ | ||
94 | /* Use a pre-allocated static mutex */ | ||
95 | if( nType > SXMUTEX_TYPE_STATIC_6 ){ | ||
96 | nType = SXMUTEX_TYPE_STATIC_6; | ||
97 | } | ||
98 | pMutex = &aStaticMutexes[nType - 3]; | ||
99 | } | ||
100 | pMutex->nType = nType; | ||
101 | return pMutex; | ||
102 | } | ||
103 | static void WinMutexRelease(SyMutex *pMutex) | ||
104 | { | ||
105 | if( pMutex->nType == SXMUTEX_TYPE_FAST || pMutex->nType == SXMUTEX_TYPE_RECURSIVE ){ | ||
106 | DeleteCriticalSection(&pMutex->sMutex); | ||
107 | HeapFree(GetProcessHeap(), 0, pMutex); | ||
108 | } | ||
109 | } | ||
110 | static void WinMutexEnter(SyMutex *pMutex) | ||
111 | { | ||
112 | EnterCriticalSection(&pMutex->sMutex); | ||
113 | } | ||
114 | static sxi32 WinMutexTryEnter(SyMutex *pMutex) | ||
115 | { | ||
116 | #ifdef _WIN32_WINNT | ||
117 | BOOL rc; | ||
118 | /* Only WindowsNT platforms */ | ||
119 | rc = TryEnterCriticalSection(&pMutex->sMutex); | ||
120 | if( rc ){ | ||
121 | return SXRET_OK; | ||
122 | }else{ | ||
123 | return SXERR_BUSY; | ||
124 | } | ||
125 | #else | ||
126 | return SXERR_NOTIMPLEMENTED; | ||
127 | #endif | ||
128 | } | ||
129 | static void WinMutexLeave(SyMutex *pMutex) | ||
130 | { | ||
131 | LeaveCriticalSection(&pMutex->sMutex); | ||
132 | } | ||
133 | /* Export Windows mutex interfaces */ | ||
134 | static const SyMutexMethods sWinMutexMethods = { | ||
135 | WinMutexGlobaInit, /* xGlobalInit() */ | ||
136 | WinMutexGlobalRelease, /* xGlobalRelease() */ | ||
137 | WinMutexNew, /* xNew() */ | ||
138 | WinMutexRelease, /* xRelease() */ | ||
139 | WinMutexEnter, /* xEnter() */ | ||
140 | WinMutexTryEnter, /* xTryEnter() */ | ||
141 | WinMutexLeave /* xLeave() */ | ||
142 | }; | ||
143 | JX9_PRIVATE const SyMutexMethods * SyMutexExportMethods(void) | ||
144 | { | ||
145 | return &sWinMutexMethods; | ||
146 | } | ||
147 | #elif defined(__UNIXES__) | ||
148 | #include <pthread.h> | ||
149 | struct SyMutex | ||
150 | { | ||
151 | pthread_mutex_t sMutex; | ||
152 | sxu32 nType; | ||
153 | }; | ||
154 | static SyMutex * UnixMutexNew(int nType) | ||
155 | { | ||
156 | static SyMutex aStaticMutexes[] = { | ||
157 | {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_1}, | ||
158 | {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_2}, | ||
159 | {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_3}, | ||
160 | {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_4}, | ||
161 | {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_5}, | ||
162 | {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_6} | ||
163 | }; | ||
164 | SyMutex *pMutex; | ||
165 | |||
166 | if( nType == SXMUTEX_TYPE_FAST || nType == SXMUTEX_TYPE_RECURSIVE ){ | ||
167 | pthread_mutexattr_t sRecursiveAttr; | ||
168 | /* Allocate a new mutex */ | ||
169 | pMutex = (SyMutex *)malloc(sizeof(SyMutex)); | ||
170 | if( pMutex == 0 ){ | ||
171 | return 0; | ||
172 | } | ||
173 | if( nType == SXMUTEX_TYPE_RECURSIVE ){ | ||
174 | pthread_mutexattr_init(&sRecursiveAttr); | ||
175 | pthread_mutexattr_settype(&sRecursiveAttr, PTHREAD_MUTEX_RECURSIVE); | ||
176 | } | ||
177 | pthread_mutex_init(&pMutex->sMutex, nType == SXMUTEX_TYPE_RECURSIVE ? &sRecursiveAttr : 0 ); | ||
178 | if( nType == SXMUTEX_TYPE_RECURSIVE ){ | ||
179 | pthread_mutexattr_destroy(&sRecursiveAttr); | ||
180 | } | ||
181 | }else{ | ||
182 | /* Use a pre-allocated static mutex */ | ||
183 | if( nType > SXMUTEX_TYPE_STATIC_6 ){ | ||
184 | nType = SXMUTEX_TYPE_STATIC_6; | ||
185 | } | ||
186 | pMutex = &aStaticMutexes[nType - 3]; | ||
187 | } | ||
188 | pMutex->nType = nType; | ||
189 | |||
190 | return pMutex; | ||
191 | } | ||
192 | static void UnixMutexRelease(SyMutex *pMutex) | ||
193 | { | ||
194 | if( pMutex->nType == SXMUTEX_TYPE_FAST || pMutex->nType == SXMUTEX_TYPE_RECURSIVE ){ | ||
195 | pthread_mutex_destroy(&pMutex->sMutex); | ||
196 | free(pMutex); | ||
197 | } | ||
198 | } | ||
199 | static void UnixMutexEnter(SyMutex *pMutex) | ||
200 | { | ||
201 | pthread_mutex_lock(&pMutex->sMutex); | ||
202 | } | ||
203 | static void UnixMutexLeave(SyMutex *pMutex) | ||
204 | { | ||
205 | pthread_mutex_unlock(&pMutex->sMutex); | ||
206 | } | ||
207 | /* Export pthread mutex interfaces */ | ||
208 | static const SyMutexMethods sPthreadMutexMethods = { | ||
209 | 0, /* xGlobalInit() */ | ||
210 | 0, /* xGlobalRelease() */ | ||
211 | UnixMutexNew, /* xNew() */ | ||
212 | UnixMutexRelease, /* xRelease() */ | ||
213 | UnixMutexEnter, /* xEnter() */ | ||
214 | 0, /* xTryEnter() */ | ||
215 | UnixMutexLeave /* xLeave() */ | ||
216 | }; | ||
217 | JX9_PRIVATE const SyMutexMethods * SyMutexExportMethods(void) | ||
218 | { | ||
219 | return &sPthreadMutexMethods; | ||
220 | } | ||
221 | #else | ||
222 | /* Host application must register their own mutex subsystem if the target | ||
223 | * platform is not an UNIX-like or windows systems. | ||
224 | */ | ||
225 | struct SyMutex | ||
226 | { | ||
227 | sxu32 nType; | ||
228 | }; | ||
229 | static SyMutex * DummyMutexNew(int nType) | ||
230 | { | ||
231 | static SyMutex sMutex; | ||
232 | SXUNUSED(nType); | ||
233 | return &sMutex; | ||
234 | } | ||
235 | static void DummyMutexRelease(SyMutex *pMutex) | ||
236 | { | ||
237 | SXUNUSED(pMutex); | ||
238 | } | ||
239 | static void DummyMutexEnter(SyMutex *pMutex) | ||
240 | { | ||
241 | SXUNUSED(pMutex); | ||
242 | } | ||
243 | static void DummyMutexLeave(SyMutex *pMutex) | ||
244 | { | ||
245 | SXUNUSED(pMutex); | ||
246 | } | ||
247 | /* Export the dummy mutex interfaces */ | ||
248 | static const SyMutexMethods sDummyMutexMethods = { | ||
249 | 0, /* xGlobalInit() */ | ||
250 | 0, /* xGlobalRelease() */ | ||
251 | DummyMutexNew, /* xNew() */ | ||
252 | DummyMutexRelease, /* xRelease() */ | ||
253 | DummyMutexEnter, /* xEnter() */ | ||
254 | 0, /* xTryEnter() */ | ||
255 | DummyMutexLeave /* xLeave() */ | ||
256 | }; | ||
257 | JX9_PRIVATE const SyMutexMethods * SyMutexExportMethods(void) | ||
258 | { | ||
259 | return &sDummyMutexMethods; | ||
260 | } | ||
261 | #endif /* __WINNT__ */ | ||
262 | #endif /* JX9_ENABLE_THREADS */ | ||
263 | static void * SyOSHeapAlloc(sxu32 nByte) | ||
264 | { | ||
265 | void *pNew; | ||
266 | #if defined(__WINNT__) | ||
267 | pNew = HeapAlloc(GetProcessHeap(), 0, nByte); | ||
268 | #else | ||
269 | pNew = malloc((size_t)nByte); | ||
270 | #endif | ||
271 | return pNew; | ||
272 | } | ||
273 | static void * SyOSHeapRealloc(void *pOld, sxu32 nByte) | ||
274 | { | ||
275 | void *pNew; | ||
276 | #if defined(__WINNT__) | ||
277 | pNew = HeapReAlloc(GetProcessHeap(), 0, pOld, nByte); | ||
278 | #else | ||
279 | pNew = realloc(pOld, (size_t)nByte); | ||
280 | #endif | ||
281 | return pNew; | ||
282 | } | ||
283 | static void SyOSHeapFree(void *pPtr) | ||
284 | { | ||
285 | #if defined(__WINNT__) | ||
286 | HeapFree(GetProcessHeap(), 0, pPtr); | ||
287 | #else | ||
288 | free(pPtr); | ||
289 | #endif | ||
290 | } | ||
291 | /* SyRunTimeApi:sxstr.c */ | ||
292 | JX9_PRIVATE sxu32 SyStrlen(const char *zSrc) | ||
293 | { | ||
294 | register const char *zIn = zSrc; | ||
295 | #if defined(UNTRUST) | ||
296 | if( zIn == 0 ){ | ||
297 | return 0; | ||
298 | } | ||
299 | #endif | ||
300 | for(;;){ | ||
301 | if( !zIn[0] ){ break; } zIn++; | ||
302 | if( !zIn[0] ){ break; } zIn++; | ||
303 | if( !zIn[0] ){ break; } zIn++; | ||
304 | if( !zIn[0] ){ break; } zIn++; | ||
305 | } | ||
306 | return (sxu32)(zIn - zSrc); | ||
307 | } | ||
308 | JX9_PRIVATE sxi32 SyByteFind(const char *zStr, sxu32 nLen, sxi32 c, sxu32 *pPos) | ||
309 | { | ||
310 | const char *zIn = zStr; | ||
311 | const char *zEnd; | ||
312 | |||
313 | zEnd = &zIn[nLen]; | ||
314 | for(;;){ | ||
315 | if( zIn >= zEnd ){ break; }if( zIn[0] == c ){ if( pPos ){ *pPos = (sxu32)(zIn - zStr); } return SXRET_OK; } zIn++; | ||
316 | if( zIn >= zEnd ){ break; }if( zIn[0] == c ){ if( pPos ){ *pPos = (sxu32)(zIn - zStr); } return SXRET_OK; } zIn++; | ||
317 | if( zIn >= zEnd ){ break; }if( zIn[0] == c ){ if( pPos ){ *pPos = (sxu32)(zIn - zStr); } return SXRET_OK; } zIn++; | ||
318 | if( zIn >= zEnd ){ break; }if( zIn[0] == c ){ if( pPos ){ *pPos = (sxu32)(zIn - zStr); } return SXRET_OK; } zIn++; | ||
319 | } | ||
320 | return SXERR_NOTFOUND; | ||
321 | } | ||
322 | #ifndef JX9_DISABLE_BUILTIN_FUNC | ||
323 | JX9_PRIVATE sxi32 SyByteFind2(const char *zStr, sxu32 nLen, sxi32 c, sxu32 *pPos) | ||
324 | { | ||
325 | const char *zIn = zStr; | ||
326 | const char *zEnd; | ||
327 | |||
328 | zEnd = &zIn[nLen - 1]; | ||
329 | for( ;; ){ | ||
330 | if( zEnd < zIn ){ break; } if( zEnd[0] == c ){ if( pPos ){ *pPos = (sxu32)(zEnd - zIn);} return SXRET_OK; } zEnd--; | ||
331 | if( zEnd < zIn ){ break; } if( zEnd[0] == c ){ if( pPos ){ *pPos = (sxu32)(zEnd - zIn);} return SXRET_OK; } zEnd--; | ||
332 | if( zEnd < zIn ){ break; } if( zEnd[0] == c ){ if( pPos ){ *pPos = (sxu32)(zEnd - zIn);} return SXRET_OK; } zEnd--; | ||
333 | if( zEnd < zIn ){ break; } if( zEnd[0] == c ){ if( pPos ){ *pPos = (sxu32)(zEnd - zIn);} return SXRET_OK; } zEnd--; | ||
334 | } | ||
335 | return SXERR_NOTFOUND; | ||
336 | } | ||
337 | #endif /* JX9_DISABLE_BUILTIN_FUNC */ | ||
338 | JX9_PRIVATE sxi32 SyByteListFind(const char *zSrc, sxu32 nLen, const char *zList, sxu32 *pFirstPos) | ||
339 | { | ||
340 | const char *zIn = zSrc; | ||
341 | const char *zPtr; | ||
342 | const char *zEnd; | ||
343 | sxi32 c; | ||
344 | zEnd = &zSrc[nLen]; | ||
345 | for(;;){ | ||
346 | if( zIn >= zEnd ){ break; } for(zPtr = zList ; (c = zPtr[0]) != 0 ; zPtr++ ){ if( zIn[0] == c ){ if( pFirstPos ){ *pFirstPos = (sxu32)(zIn - zSrc); } return SXRET_OK; } } zIn++; | ||
347 | if( zIn >= zEnd ){ break; } for(zPtr = zList ; (c = zPtr[0]) != 0 ; zPtr++ ){ if( zIn[0] == c ){ if( pFirstPos ){ *pFirstPos = (sxu32)(zIn - zSrc); } return SXRET_OK; } } zIn++; | ||
348 | if( zIn >= zEnd ){ break; } for(zPtr = zList ; (c = zPtr[0]) != 0 ; zPtr++ ){ if( zIn[0] == c ){ if( pFirstPos ){ *pFirstPos = (sxu32)(zIn - zSrc); } return SXRET_OK; } } zIn++; | ||
349 | if( zIn >= zEnd ){ break; } for(zPtr = zList ; (c = zPtr[0]) != 0 ; zPtr++ ){ if( zIn[0] == c ){ if( pFirstPos ){ *pFirstPos = (sxu32)(zIn - zSrc); } return SXRET_OK; } } zIn++; | ||
350 | } | ||
351 | return SXERR_NOTFOUND; | ||
352 | } | ||
353 | #ifndef JX9_DISABLE_BUILTIN_FUNC | ||
354 | JX9_PRIVATE sxi32 SyStrncmp(const char *zLeft, const char *zRight, sxu32 nLen) | ||
355 | { | ||
356 | const unsigned char *zP = (const unsigned char *)zLeft; | ||
357 | const unsigned char *zQ = (const unsigned char *)zRight; | ||
358 | |||
359 | if( SX_EMPTY_STR(zP) || SX_EMPTY_STR(zQ) ){ | ||
360 | return SX_EMPTY_STR(zP) ? (SX_EMPTY_STR(zQ) ? 0 : -1) :1; | ||
361 | } | ||
362 | if( nLen <= 0 ){ | ||
363 | return 0; | ||
364 | } | ||
365 | for(;;){ | ||
366 | if( nLen <= 0 ){ return 0; } if( zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0] ){ break; } zP++; zQ++; nLen--; | ||
367 | if( nLen <= 0 ){ return 0; } if( zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0] ){ break; } zP++; zQ++; nLen--; | ||
368 | if( nLen <= 0 ){ return 0; } if( zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0] ){ break; } zP++; zQ++; nLen--; | ||
369 | if( nLen <= 0 ){ return 0; } if( zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0] ){ break; } zP++; zQ++; nLen--; | ||
370 | } | ||
371 | return (sxi32)(zP[0] - zQ[0]); | ||
372 | } | ||
373 | #endif | ||
374 | JX9_PRIVATE sxi32 SyStrnicmp(const char *zLeft, const char *zRight, sxu32 SLen) | ||
375 | { | ||
376 | register unsigned char *p = (unsigned char *)zLeft; | ||
377 | register unsigned char *q = (unsigned char *)zRight; | ||
378 | |||
379 | if( SX_EMPTY_STR(p) || SX_EMPTY_STR(q) ){ | ||
380 | return SX_EMPTY_STR(p)? SX_EMPTY_STR(q) ? 0 : -1 :1; | ||
381 | } | ||
382 | for(;;){ | ||
383 | if( !SLen ){ return 0; }if( !*p || !*q || SyCharToLower(*p) != SyCharToLower(*q) ){ break; }p++;q++;--SLen; | ||
384 | if( !SLen ){ return 0; }if( !*p || !*q || SyCharToLower(*p) != SyCharToLower(*q) ){ break; }p++;q++;--SLen; | ||
385 | if( !SLen ){ return 0; }if( !*p || !*q || SyCharToLower(*p) != SyCharToLower(*q) ){ break; }p++;q++;--SLen; | ||
386 | if( !SLen ){ return 0; }if( !*p || !*q || SyCharToLower(*p) != SyCharToLower(*q) ){ break; }p++;q++;--SLen; | ||
387 | |||
388 | } | ||
389 | return (sxi32)(SyCharToLower(p[0]) - SyCharToLower(q[0])); | ||
390 | } | ||
391 | JX9_PRIVATE sxu32 Systrcpy(char *zDest, sxu32 nDestLen, const char *zSrc, sxu32 nLen) | ||
392 | { | ||
393 | unsigned char *zBuf = (unsigned char *)zDest; | ||
394 | unsigned char *zIn = (unsigned char *)zSrc; | ||
395 | unsigned char *zEnd; | ||
396 | #if defined(UNTRUST) | ||
397 | if( zSrc == (const char *)zDest ){ | ||
398 | return 0; | ||
399 | } | ||
400 | #endif | ||
401 | if( nLen <= 0 ){ | ||
402 | nLen = SyStrlen(zSrc); | ||
403 | } | ||
404 | zEnd = &zBuf[nDestLen - 1]; /* reserve a room for the null terminator */ | ||
405 | for(;;){ | ||
406 | if( zBuf >= zEnd || nLen == 0 ){ break;} zBuf[0] = zIn[0]; zIn++; zBuf++; nLen--; | ||
407 | if( zBuf >= zEnd || nLen == 0 ){ break;} zBuf[0] = zIn[0]; zIn++; zBuf++; nLen--; | ||
408 | if( zBuf >= zEnd || nLen == 0 ){ break;} zBuf[0] = zIn[0]; zIn++; zBuf++; nLen--; | ||
409 | if( zBuf >= zEnd || nLen == 0 ){ break;} zBuf[0] = zIn[0]; zIn++; zBuf++; nLen--; | ||
410 | } | ||
411 | zBuf[0] = 0; | ||
412 | return (sxu32)(zBuf-(unsigned char *)zDest); | ||
413 | } | ||
414 | /* SyRunTimeApi:sxmem.c */ | ||
415 | JX9_PRIVATE void SyZero(void *pSrc, sxu32 nSize) | ||
416 | { | ||
417 | register unsigned char *zSrc = (unsigned char *)pSrc; | ||
418 | unsigned char *zEnd; | ||
419 | #if defined(UNTRUST) | ||
420 | if( zSrc == 0 || nSize <= 0 ){ | ||
421 | return ; | ||
422 | } | ||
423 | #endif | ||
424 | zEnd = &zSrc[nSize]; | ||
425 | for(;;){ | ||
426 | if( zSrc >= zEnd ){break;} zSrc[0] = 0; zSrc++; | ||
427 | if( zSrc >= zEnd ){break;} zSrc[0] = 0; zSrc++; | ||
428 | if( zSrc >= zEnd ){break;} zSrc[0] = 0; zSrc++; | ||
429 | if( zSrc >= zEnd ){break;} zSrc[0] = 0; zSrc++; | ||
430 | } | ||
431 | } | ||
432 | JX9_PRIVATE sxi32 SyMemcmp(const void *pB1, const void *pB2, sxu32 nSize) | ||
433 | { | ||
434 | sxi32 rc; | ||
435 | if( nSize <= 0 ){ | ||
436 | return 0; | ||
437 | } | ||
438 | if( pB1 == 0 || pB2 == 0 ){ | ||
439 | return pB1 != 0 ? 1 : (pB2 == 0 ? 0 : -1); | ||
440 | } | ||
441 | SX_MACRO_FAST_CMP(pB1, pB2, nSize, rc); | ||
442 | return rc; | ||
443 | } | ||
444 | JX9_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen) | ||
445 | { | ||
446 | if( pSrc == 0 || pDest == 0 ){ | ||
447 | return 0; | ||
448 | } | ||
449 | if( pSrc == (const void *)pDest ){ | ||
450 | return nLen; | ||
451 | } | ||
452 | SX_MACRO_FAST_MEMCPY(pSrc, pDest, nLen); | ||
453 | return nLen; | ||
454 | } | ||
455 | static void * MemOSAlloc(sxu32 nBytes) | ||
456 | { | ||
457 | sxu32 *pChunk; | ||
458 | pChunk = (sxu32 *)SyOSHeapAlloc(nBytes + sizeof(sxu32)); | ||
459 | if( pChunk == 0 ){ | ||
460 | return 0; | ||
461 | } | ||
462 | pChunk[0] = nBytes; | ||
463 | return (void *)&pChunk[1]; | ||
464 | } | ||
465 | static void * MemOSRealloc(void *pOld, sxu32 nBytes) | ||
466 | { | ||
467 | sxu32 *pOldChunk; | ||
468 | sxu32 *pChunk; | ||
469 | pOldChunk = (sxu32 *)(((char *)pOld)-sizeof(sxu32)); | ||
470 | if( pOldChunk[0] >= nBytes ){ | ||
471 | return pOld; | ||
472 | } | ||
473 | pChunk = (sxu32 *)SyOSHeapRealloc(pOldChunk, nBytes + sizeof(sxu32)); | ||
474 | if( pChunk == 0 ){ | ||
475 | return 0; | ||
476 | } | ||
477 | pChunk[0] = nBytes; | ||
478 | return (void *)&pChunk[1]; | ||
479 | } | ||
480 | static void MemOSFree(void *pBlock) | ||
481 | { | ||
482 | void *pChunk; | ||
483 | pChunk = (void *)(((char *)pBlock)-sizeof(sxu32)); | ||
484 | SyOSHeapFree(pChunk); | ||
485 | } | ||
486 | static sxu32 MemOSChunkSize(void *pBlock) | ||
487 | { | ||
488 | sxu32 *pChunk; | ||
489 | pChunk = (sxu32 *)(((char *)pBlock)-sizeof(sxu32)); | ||
490 | return pChunk[0]; | ||
491 | } | ||
492 | /* Export OS allocation methods */ | ||
493 | static const SyMemMethods sOSAllocMethods = { | ||
494 | MemOSAlloc, | ||
495 | MemOSRealloc, | ||
496 | MemOSFree, | ||
497 | MemOSChunkSize, | ||
498 | 0, | ||
499 | 0, | ||
500 | 0 | ||
501 | }; | ||
502 | static void * MemBackendAlloc(SyMemBackend *pBackend, sxu32 nByte) | ||
503 | { | ||
504 | SyMemBlock *pBlock; | ||
505 | sxi32 nRetry = 0; | ||
506 | |||
507 | /* Append an extra block so we can tracks allocated chunks and avoid memory | ||
508 | * leaks. | ||
509 | */ | ||
510 | nByte += sizeof(SyMemBlock); | ||
511 | for(;;){ | ||
512 | pBlock = (SyMemBlock *)pBackend->pMethods->xAlloc(nByte); | ||
513 | if( pBlock != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY | ||
514 | || SXERR_RETRY != pBackend->xMemError(pBackend->pUserData) ){ | ||
515 | break; | ||
516 | } | ||
517 | nRetry++; | ||
518 | } | ||
519 | if( pBlock == 0 ){ | ||
520 | return 0; | ||
521 | } | ||
522 | pBlock->pNext = pBlock->pPrev = 0; | ||
523 | /* Link to the list of already tracked blocks */ | ||
524 | MACRO_LD_PUSH(pBackend->pBlocks, pBlock); | ||
525 | #if defined(UNTRUST) | ||
526 | pBlock->nGuard = SXMEM_BACKEND_MAGIC; | ||
527 | #endif | ||
528 | pBackend->nBlock++; | ||
529 | return (void *)&pBlock[1]; | ||
530 | } | ||
531 | JX9_PRIVATE void * SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nByte) | ||
532 | { | ||
533 | void *pChunk; | ||
534 | #if defined(UNTRUST) | ||
535 | if( SXMEM_BACKEND_CORRUPT(pBackend) ){ | ||
536 | return 0; | ||
537 | } | ||
538 | #endif | ||
539 | if( pBackend->pMutexMethods ){ | ||
540 | SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); | ||
541 | } | ||
542 | pChunk = MemBackendAlloc(&(*pBackend), nByte); | ||
543 | if( pBackend->pMutexMethods ){ | ||
544 | SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); | ||
545 | } | ||
546 | return pChunk; | ||
547 | } | ||
548 | static void * MemBackendRealloc(SyMemBackend *pBackend, void * pOld, sxu32 nByte) | ||
549 | { | ||
550 | SyMemBlock *pBlock, *pNew, *pPrev, *pNext; | ||
551 | sxu32 nRetry = 0; | ||
552 | |||
553 | if( pOld == 0 ){ | ||
554 | return MemBackendAlloc(&(*pBackend), nByte); | ||
555 | } | ||
556 | pBlock = (SyMemBlock *)(((char *)pOld) - sizeof(SyMemBlock)); | ||
557 | #if defined(UNTRUST) | ||
558 | if( pBlock->nGuard != SXMEM_BACKEND_MAGIC ){ | ||
559 | return 0; | ||
560 | } | ||
561 | #endif | ||
562 | nByte += sizeof(SyMemBlock); | ||
563 | pPrev = pBlock->pPrev; | ||
564 | pNext = pBlock->pNext; | ||
565 | for(;;){ | ||
566 | pNew = (SyMemBlock *)pBackend->pMethods->xRealloc(pBlock, nByte); | ||
567 | if( pNew != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY || | ||
568 | SXERR_RETRY != pBackend->xMemError(pBackend->pUserData) ){ | ||
569 | break; | ||
570 | } | ||
571 | nRetry++; | ||
572 | } | ||
573 | if( pNew == 0 ){ | ||
574 | return 0; | ||
575 | } | ||
576 | if( pNew != pBlock ){ | ||
577 | if( pPrev == 0 ){ | ||
578 | pBackend->pBlocks = pNew; | ||
579 | }else{ | ||
580 | pPrev->pNext = pNew; | ||
581 | } | ||
582 | if( pNext ){ | ||
583 | pNext->pPrev = pNew; | ||
584 | } | ||
585 | #if defined(UNTRUST) | ||
586 | pNew->nGuard = SXMEM_BACKEND_MAGIC; | ||
587 | #endif | ||
588 | } | ||
589 | return (void *)&pNew[1]; | ||
590 | } | ||
591 | JX9_PRIVATE void * SyMemBackendRealloc(SyMemBackend *pBackend, void * pOld, sxu32 nByte) | ||
592 | { | ||
593 | void *pChunk; | ||
594 | #if defined(UNTRUST) | ||
595 | if( SXMEM_BACKEND_CORRUPT(pBackend) ){ | ||
596 | return 0; | ||
597 | } | ||
598 | #endif | ||
599 | if( pBackend->pMutexMethods ){ | ||
600 | SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); | ||
601 | } | ||
602 | pChunk = MemBackendRealloc(&(*pBackend), pOld, nByte); | ||
603 | if( pBackend->pMutexMethods ){ | ||
604 | SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); | ||
605 | } | ||
606 | return pChunk; | ||
607 | } | ||
608 | static sxi32 MemBackendFree(SyMemBackend *pBackend, void * pChunk) | ||
609 | { | ||
610 | SyMemBlock *pBlock; | ||
611 | pBlock = (SyMemBlock *)(((char *)pChunk) - sizeof(SyMemBlock)); | ||
612 | #if defined(UNTRUST) | ||
613 | if( pBlock->nGuard != SXMEM_BACKEND_MAGIC ){ | ||
614 | return SXERR_CORRUPT; | ||
615 | } | ||
616 | #endif | ||
617 | /* Unlink from the list of active blocks */ | ||
618 | if( pBackend->nBlock > 0 ){ | ||
619 | /* Release the block */ | ||
620 | #if defined(UNTRUST) | ||
621 | /* Mark as stale block */ | ||
622 | pBlock->nGuard = 0x635B; | ||
623 | #endif | ||
624 | MACRO_LD_REMOVE(pBackend->pBlocks, pBlock); | ||
625 | pBackend->nBlock--; | ||
626 | pBackend->pMethods->xFree(pBlock); | ||
627 | } | ||
628 | return SXRET_OK; | ||
629 | } | ||
630 | JX9_PRIVATE sxi32 SyMemBackendFree(SyMemBackend *pBackend, void * pChunk) | ||
631 | { | ||
632 | sxi32 rc; | ||
633 | #if defined(UNTRUST) | ||
634 | if( SXMEM_BACKEND_CORRUPT(pBackend) ){ | ||
635 | return SXERR_CORRUPT; | ||
636 | } | ||
637 | #endif | ||
638 | if( pChunk == 0 ){ | ||
639 | return SXRET_OK; | ||
640 | } | ||
641 | if( pBackend->pMutexMethods ){ | ||
642 | SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); | ||
643 | } | ||
644 | rc = MemBackendFree(&(*pBackend), pChunk); | ||
645 | if( pBackend->pMutexMethods ){ | ||
646 | SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); | ||
647 | } | ||
648 | return rc; | ||
649 | } | ||
650 | #if defined(JX9_ENABLE_THREADS) | ||
651 | JX9_PRIVATE sxi32 SyMemBackendMakeThreadSafe(SyMemBackend *pBackend, const SyMutexMethods *pMethods) | ||
652 | { | ||
653 | SyMutex *pMutex; | ||
654 | #if defined(UNTRUST) | ||
655 | if( SXMEM_BACKEND_CORRUPT(pBackend) || pMethods == 0 || pMethods->xNew == 0){ | ||
656 | return SXERR_CORRUPT; | ||
657 | } | ||
658 | #endif | ||
659 | pMutex = pMethods->xNew(SXMUTEX_TYPE_FAST); | ||
660 | if( pMutex == 0 ){ | ||
661 | return SXERR_OS; | ||
662 | } | ||
663 | /* Attach the mutex to the memory backend */ | ||
664 | pBackend->pMutex = pMutex; | ||
665 | pBackend->pMutexMethods = pMethods; | ||
666 | return SXRET_OK; | ||
667 | } | ||
668 | JX9_PRIVATE sxi32 SyMemBackendDisbaleMutexing(SyMemBackend *pBackend) | ||
669 | { | ||
670 | #if defined(UNTRUST) | ||
671 | if( SXMEM_BACKEND_CORRUPT(pBackend) ){ | ||
672 | return SXERR_CORRUPT; | ||
673 | } | ||
674 | #endif | ||
675 | if( pBackend->pMutex == 0 ){ | ||
676 | /* There is no mutex subsystem at all */ | ||
677 | return SXRET_OK; | ||
678 | } | ||
679 | SyMutexRelease(pBackend->pMutexMethods, pBackend->pMutex); | ||
680 | pBackend->pMutexMethods = 0; | ||
681 | pBackend->pMutex = 0; | ||
682 | return SXRET_OK; | ||
683 | } | ||
684 | #endif | ||
685 | /* | ||
686 | * Memory pool allocator | ||
687 | */ | ||
688 | #define SXMEM_POOL_MAGIC 0xDEAD | ||
689 | #define SXMEM_POOL_MAXALLOC (1<<(SXMEM_POOL_NBUCKETS+SXMEM_POOL_INCR)) | ||
690 | #define SXMEM_POOL_MINALLOC (1<<(SXMEM_POOL_INCR)) | ||
691 | static sxi32 MemPoolBucketAlloc(SyMemBackend *pBackend, sxu32 nBucket) | ||
692 | { | ||
693 | char *zBucket, *zBucketEnd; | ||
694 | SyMemHeader *pHeader; | ||
695 | sxu32 nBucketSize; | ||
696 | |||
697 | /* Allocate one big block first */ | ||
698 | zBucket = (char *)MemBackendAlloc(&(*pBackend), SXMEM_POOL_MAXALLOC); | ||
699 | if( zBucket == 0 ){ | ||
700 | return SXERR_MEM; | ||
701 | } | ||
702 | zBucketEnd = &zBucket[SXMEM_POOL_MAXALLOC]; | ||
703 | /* Divide the big block into mini bucket pool */ | ||
704 | nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR); | ||
705 | pBackend->apPool[nBucket] = pHeader = (SyMemHeader *)zBucket; | ||
706 | for(;;){ | ||
707 | if( &zBucket[nBucketSize] >= zBucketEnd ){ | ||
708 | break; | ||
709 | } | ||
710 | pHeader->pNext = (SyMemHeader *)&zBucket[nBucketSize]; | ||
711 | /* Advance the cursor to the next available chunk */ | ||
712 | pHeader = pHeader->pNext; | ||
713 | zBucket += nBucketSize; | ||
714 | } | ||
715 | pHeader->pNext = 0; | ||
716 | |||
717 | return SXRET_OK; | ||
718 | } | ||
719 | static void * MemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nByte) | ||
720 | { | ||
721 | SyMemHeader *pBucket, *pNext; | ||
722 | sxu32 nBucketSize; | ||
723 | sxu32 nBucket; | ||
724 | |||
725 | if( nByte + sizeof(SyMemHeader) >= SXMEM_POOL_MAXALLOC ){ | ||
726 | /* Allocate a big chunk directly */ | ||
727 | pBucket = (SyMemHeader *)MemBackendAlloc(&(*pBackend), nByte+sizeof(SyMemHeader)); | ||
728 | if( pBucket == 0 ){ | ||
729 | return 0; | ||
730 | } | ||
731 | /* Record as big block */ | ||
732 | pBucket->nBucket = (sxu32)(SXMEM_POOL_MAGIC << 16) | SXU16_HIGH; | ||
733 | return (void *)(pBucket+1); | ||
734 | } | ||
735 | /* Locate the appropriate bucket */ | ||
736 | nBucket = 0; | ||
737 | nBucketSize = SXMEM_POOL_MINALLOC; | ||
738 | while( nByte + sizeof(SyMemHeader) > nBucketSize ){ | ||
739 | nBucketSize <<= 1; | ||
740 | nBucket++; | ||
741 | } | ||
742 | pBucket = pBackend->apPool[nBucket]; | ||
743 | if( pBucket == 0 ){ | ||
744 | sxi32 rc; | ||
745 | rc = MemPoolBucketAlloc(&(*pBackend), nBucket); | ||
746 | if( rc != SXRET_OK ){ | ||
747 | return 0; | ||
748 | } | ||
749 | pBucket = pBackend->apPool[nBucket]; | ||
750 | } | ||
751 | /* Remove from the free list */ | ||
752 | pNext = pBucket->pNext; | ||
753 | pBackend->apPool[nBucket] = pNext; | ||
754 | /* Record bucket&magic number */ | ||
755 | pBucket->nBucket = (SXMEM_POOL_MAGIC << 16) | nBucket; | ||
756 | return (void *)&pBucket[1]; | ||
757 | } | ||
758 | JX9_PRIVATE void * SyMemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nByte) | ||
759 | { | ||
760 | void *pChunk; | ||
761 | #if defined(UNTRUST) | ||
762 | if( SXMEM_BACKEND_CORRUPT(pBackend) ){ | ||
763 | return 0; | ||
764 | } | ||
765 | #endif | ||
766 | if( pBackend->pMutexMethods ){ | ||
767 | SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); | ||
768 | } | ||
769 | pChunk = MemBackendPoolAlloc(&(*pBackend), nByte); | ||
770 | if( pBackend->pMutexMethods ){ | ||
771 | SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); | ||
772 | } | ||
773 | return pChunk; | ||
774 | } | ||
775 | static sxi32 MemBackendPoolFree(SyMemBackend *pBackend, void * pChunk) | ||
776 | { | ||
777 | SyMemHeader *pHeader; | ||
778 | sxu32 nBucket; | ||
779 | /* Get the corresponding bucket */ | ||
780 | pHeader = (SyMemHeader *)(((char *)pChunk) - sizeof(SyMemHeader)); | ||
781 | /* Sanity check to avoid misuse */ | ||
782 | if( (pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC ){ | ||
783 | return SXERR_CORRUPT; | ||
784 | } | ||
785 | nBucket = pHeader->nBucket & 0xFFFF; | ||
786 | if( nBucket == SXU16_HIGH ){ | ||
787 | /* Free the big block */ | ||
788 | MemBackendFree(&(*pBackend), pHeader); | ||
789 | }else{ | ||
790 | /* Return to the free list */ | ||
791 | pHeader->pNext = pBackend->apPool[nBucket & 0x0f]; | ||
792 | pBackend->apPool[nBucket & 0x0f] = pHeader; | ||
793 | } | ||
794 | return SXRET_OK; | ||
795 | } | ||
796 | JX9_PRIVATE sxi32 SyMemBackendPoolFree(SyMemBackend *pBackend, void * pChunk) | ||
797 | { | ||
798 | sxi32 rc; | ||
799 | #if defined(UNTRUST) | ||
800 | if( SXMEM_BACKEND_CORRUPT(pBackend) || pChunk == 0 ){ | ||
801 | return SXERR_CORRUPT; | ||
802 | } | ||
803 | #endif | ||
804 | if( pBackend->pMutexMethods ){ | ||
805 | SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); | ||
806 | } | ||
807 | rc = MemBackendPoolFree(&(*pBackend), pChunk); | ||
808 | if( pBackend->pMutexMethods ){ | ||
809 | SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); | ||
810 | } | ||
811 | return rc; | ||
812 | } | ||
813 | #if 0 | ||
814 | static void * MemBackendPoolRealloc(SyMemBackend *pBackend, void * pOld, sxu32 nByte) | ||
815 | { | ||
816 | sxu32 nBucket, nBucketSize; | ||
817 | SyMemHeader *pHeader; | ||
818 | void * pNew; | ||
819 | |||
820 | if( pOld == 0 ){ | ||
821 | /* Allocate a new pool */ | ||
822 | pNew = MemBackendPoolAlloc(&(*pBackend), nByte); | ||
823 | return pNew; | ||
824 | } | ||
825 | /* Get the corresponding bucket */ | ||
826 | pHeader = (SyMemHeader *)(((char *)pOld) - sizeof(SyMemHeader)); | ||
827 | /* Sanity check to avoid misuse */ | ||
828 | if( (pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC ){ | ||
829 | return 0; | ||
830 | } | ||
831 | nBucket = pHeader->nBucket & 0xFFFF; | ||
832 | if( nBucket == SXU16_HIGH ){ | ||
833 | /* Big block */ | ||
834 | return MemBackendRealloc(&(*pBackend), pHeader, nByte); | ||
835 | } | ||
836 | nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR); | ||
837 | if( nBucketSize >= nByte + sizeof(SyMemHeader) ){ | ||
838 | /* The old bucket can honor the requested size */ | ||
839 | return pOld; | ||
840 | } | ||
841 | /* Allocate a new pool */ | ||
842 | pNew = MemBackendPoolAlloc(&(*pBackend), nByte); | ||
843 | if( pNew == 0 ){ | ||
844 | return 0; | ||
845 | } | ||
846 | /* Copy the old data into the new block */ | ||
847 | SyMemcpy(pOld, pNew, nBucketSize); | ||
848 | /* Free the stale block */ | ||
849 | MemBackendPoolFree(&(*pBackend), pOld); | ||
850 | return pNew; | ||
851 | } | ||
852 | JX9_PRIVATE void * SyMemBackendPoolRealloc(SyMemBackend *pBackend, void * pOld, sxu32 nByte) | ||
853 | { | ||
854 | void *pChunk; | ||
855 | #if defined(UNTRUST) | ||
856 | if( SXMEM_BACKEND_CORRUPT(pBackend) ){ | ||
857 | return 0; | ||
858 | } | ||
859 | #endif | ||
860 | if( pBackend->pMutexMethods ){ | ||
861 | SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); | ||
862 | } | ||
863 | pChunk = MemBackendPoolRealloc(&(*pBackend), pOld, nByte); | ||
864 | if( pBackend->pMutexMethods ){ | ||
865 | SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); | ||
866 | } | ||
867 | return pChunk; | ||
868 | } | ||
869 | #endif | ||
870 | JX9_PRIVATE sxi32 SyMemBackendInit(SyMemBackend *pBackend, ProcMemError xMemErr, void * pUserData) | ||
871 | { | ||
872 | #if defined(UNTRUST) | ||
873 | if( pBackend == 0 ){ | ||
874 | return SXERR_EMPTY; | ||
875 | } | ||
876 | #endif | ||
877 | /* Zero the allocator first */ | ||
878 | SyZero(&(*pBackend), sizeof(SyMemBackend)); | ||
879 | pBackend->xMemError = xMemErr; | ||
880 | pBackend->pUserData = pUserData; | ||
881 | /* Switch to the OS memory allocator */ | ||
882 | pBackend->pMethods = &sOSAllocMethods; | ||
883 | if( pBackend->pMethods->xInit ){ | ||
884 | /* Initialize the backend */ | ||
885 | if( SXRET_OK != pBackend->pMethods->xInit(pBackend->pMethods->pUserData) ){ | ||
886 | return SXERR_ABORT; | ||
887 | } | ||
888 | } | ||
889 | #if defined(UNTRUST) | ||
890 | pBackend->nMagic = SXMEM_BACKEND_MAGIC; | ||
891 | #endif | ||
892 | return SXRET_OK; | ||
893 | } | ||
894 | JX9_PRIVATE sxi32 SyMemBackendInitFromOthers(SyMemBackend *pBackend, const SyMemMethods *pMethods, ProcMemError xMemErr, void * pUserData) | ||
895 | { | ||
896 | #if defined(UNTRUST) | ||
897 | if( pBackend == 0 || pMethods == 0){ | ||
898 | return SXERR_EMPTY; | ||
899 | } | ||
900 | #endif | ||
901 | if( pMethods->xAlloc == 0 || pMethods->xRealloc == 0 || pMethods->xFree == 0 || pMethods->xChunkSize == 0 ){ | ||
902 | /* mandatory methods are missing */ | ||
903 | return SXERR_INVALID; | ||
904 | } | ||
905 | /* Zero the allocator first */ | ||
906 | SyZero(&(*pBackend), sizeof(SyMemBackend)); | ||
907 | pBackend->xMemError = xMemErr; | ||
908 | pBackend->pUserData = pUserData; | ||
909 | /* Switch to the host application memory allocator */ | ||
910 | pBackend->pMethods = pMethods; | ||
911 | if( pBackend->pMethods->xInit ){ | ||
912 | /* Initialize the backend */ | ||
913 | if( SXRET_OK != pBackend->pMethods->xInit(pBackend->pMethods->pUserData) ){ | ||
914 | return SXERR_ABORT; | ||
915 | } | ||
916 | } | ||
917 | #if defined(UNTRUST) | ||
918 | pBackend->nMagic = SXMEM_BACKEND_MAGIC; | ||
919 | #endif | ||
920 | return SXRET_OK; | ||
921 | } | ||
922 | JX9_PRIVATE sxi32 SyMemBackendInitFromParent(SyMemBackend *pBackend,const SyMemBackend *pParent) | ||
923 | { | ||
924 | sxu8 bInheritMutex; | ||
925 | #if defined(UNTRUST) | ||
926 | if( pBackend == 0 || SXMEM_BACKEND_CORRUPT(pParent) ){ | ||
927 | return SXERR_CORRUPT; | ||
928 | } | ||
929 | #endif | ||
930 | /* Zero the allocator first */ | ||
931 | SyZero(&(*pBackend), sizeof(SyMemBackend)); | ||
932 | pBackend->pMethods = pParent->pMethods; | ||
933 | pBackend->xMemError = pParent->xMemError; | ||
934 | pBackend->pUserData = pParent->pUserData; | ||
935 | bInheritMutex = pParent->pMutexMethods ? TRUE : FALSE; | ||
936 | if( bInheritMutex ){ | ||
937 | pBackend->pMutexMethods = pParent->pMutexMethods; | ||
938 | /* Create a private mutex */ | ||
939 | pBackend->pMutex = pBackend->pMutexMethods->xNew(SXMUTEX_TYPE_FAST); | ||
940 | if( pBackend->pMutex == 0){ | ||
941 | return SXERR_OS; | ||
942 | } | ||
943 | } | ||
944 | #if defined(UNTRUST) | ||
945 | pBackend->nMagic = SXMEM_BACKEND_MAGIC; | ||
946 | #endif | ||
947 | return SXRET_OK; | ||
948 | } | ||
949 | static sxi32 MemBackendRelease(SyMemBackend *pBackend) | ||
950 | { | ||
951 | SyMemBlock *pBlock, *pNext; | ||
952 | |||
953 | pBlock = pBackend->pBlocks; | ||
954 | for(;;){ | ||
955 | if( pBackend->nBlock == 0 ){ | ||
956 | break; | ||
957 | } | ||
958 | pNext = pBlock->pNext; | ||
959 | pBackend->pMethods->xFree(pBlock); | ||
960 | pBlock = pNext; | ||
961 | pBackend->nBlock--; | ||
962 | /* LOOP ONE */ | ||
963 | if( pBackend->nBlock == 0 ){ | ||
964 | break; | ||
965 | } | ||
966 | pNext = pBlock->pNext; | ||
967 | pBackend->pMethods->xFree(pBlock); | ||
968 | pBlock = pNext; | ||
969 | pBackend->nBlock--; | ||
970 | /* LOOP TWO */ | ||
971 | if( pBackend->nBlock == 0 ){ | ||
972 | break; | ||
973 | } | ||
974 | pNext = pBlock->pNext; | ||
975 | pBackend->pMethods->xFree(pBlock); | ||
976 | pBlock = pNext; | ||
977 | pBackend->nBlock--; | ||
978 | /* LOOP THREE */ | ||
979 | if( pBackend->nBlock == 0 ){ | ||
980 | break; | ||
981 | } | ||
982 | pNext = pBlock->pNext; | ||
983 | pBackend->pMethods->xFree(pBlock); | ||
984 | pBlock = pNext; | ||
985 | pBackend->nBlock--; | ||
986 | /* LOOP FOUR */ | ||
987 | } | ||
988 | if( pBackend->pMethods->xRelease ){ | ||
989 | pBackend->pMethods->xRelease(pBackend->pMethods->pUserData); | ||
990 | } | ||
991 | pBackend->pMethods = 0; | ||
992 | pBackend->pBlocks = 0; | ||
993 | #if defined(UNTRUST) | ||
994 | pBackend->nMagic = 0x2626; | ||
995 | #endif | ||
996 | return SXRET_OK; | ||
997 | } | ||
998 | JX9_PRIVATE sxi32 SyMemBackendRelease(SyMemBackend *pBackend) | ||
999 | { | ||
1000 | sxi32 rc; | ||
1001 | #if defined(UNTRUST) | ||
1002 | if( SXMEM_BACKEND_CORRUPT(pBackend) ){ | ||
1003 | return SXERR_INVALID; | ||
1004 | } | ||
1005 | #endif | ||
1006 | if( pBackend->pMutexMethods ){ | ||
1007 | SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); | ||
1008 | } | ||
1009 | rc = MemBackendRelease(&(*pBackend)); | ||
1010 | if( pBackend->pMutexMethods ){ | ||
1011 | SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); | ||
1012 | SyMutexRelease(pBackend->pMutexMethods, pBackend->pMutex); | ||
1013 | } | ||
1014 | return rc; | ||
1015 | } | ||
1016 | JX9_PRIVATE void * SyMemBackendDup(SyMemBackend *pBackend, const void *pSrc, sxu32 nSize) | ||
1017 | { | ||
1018 | void *pNew; | ||
1019 | #if defined(UNTRUST) | ||
1020 | if( pSrc == 0 || nSize <= 0 ){ | ||
1021 | return 0; | ||
1022 | } | ||
1023 | #endif | ||
1024 | pNew = SyMemBackendAlloc(&(*pBackend), nSize); | ||
1025 | if( pNew ){ | ||
1026 | SyMemcpy(pSrc, pNew, nSize); | ||
1027 | } | ||
1028 | return pNew; | ||
1029 | } | ||
1030 | JX9_PRIVATE char * SyMemBackendStrDup(SyMemBackend *pBackend, const char *zSrc, sxu32 nSize) | ||
1031 | { | ||
1032 | char *zDest; | ||
1033 | zDest = (char *)SyMemBackendAlloc(&(*pBackend), nSize + 1); | ||
1034 | if( zDest ){ | ||
1035 | Systrcpy(zDest, nSize+1, zSrc, nSize); | ||
1036 | } | ||
1037 | return zDest; | ||
1038 | } | ||
1039 | JX9_PRIVATE sxi32 SyBlobInitFromBuf(SyBlob *pBlob, void *pBuffer, sxu32 nSize) | ||
1040 | { | ||
1041 | #if defined(UNTRUST) | ||
1042 | if( pBlob == 0 || pBuffer == 0 || nSize < 1 ){ | ||
1043 | return SXERR_EMPTY; | ||
1044 | } | ||
1045 | #endif | ||
1046 | pBlob->pBlob = pBuffer; | ||
1047 | pBlob->mByte = nSize; | ||
1048 | pBlob->nByte = 0; | ||
1049 | pBlob->pAllocator = 0; | ||
1050 | pBlob->nFlags = SXBLOB_LOCKED|SXBLOB_STATIC; | ||
1051 | return SXRET_OK; | ||
1052 | } | ||
1053 | JX9_PRIVATE sxi32 SyBlobInit(SyBlob *pBlob, SyMemBackend *pAllocator) | ||
1054 | { | ||
1055 | #if defined(UNTRUST) | ||
1056 | if( pBlob == 0 ){ | ||
1057 | return SXERR_EMPTY; | ||
1058 | } | ||
1059 | #endif | ||
1060 | pBlob->pBlob = 0; | ||
1061 | pBlob->mByte = pBlob->nByte = 0; | ||
1062 | pBlob->pAllocator = &(*pAllocator); | ||
1063 | pBlob->nFlags = 0; | ||
1064 | return SXRET_OK; | ||
1065 | } | ||
1066 | JX9_PRIVATE sxi32 SyBlobReadOnly(SyBlob *pBlob, const void *pData, sxu32 nByte) | ||
1067 | { | ||
1068 | #if defined(UNTRUST) | ||
1069 | if( pBlob == 0 ){ | ||
1070 | return SXERR_EMPTY; | ||
1071 | } | ||
1072 | #endif | ||
1073 | pBlob->pBlob = (void *)pData; | ||
1074 | pBlob->nByte = nByte; | ||
1075 | pBlob->mByte = 0; | ||
1076 | pBlob->nFlags |= SXBLOB_RDONLY; | ||
1077 | return SXRET_OK; | ||
1078 | } | ||
1079 | #ifndef SXBLOB_MIN_GROWTH | ||
1080 | #define SXBLOB_MIN_GROWTH 16 | ||
1081 | #endif | ||
1082 | static sxi32 BlobPrepareGrow(SyBlob *pBlob, sxu32 *pByte) | ||
1083 | { | ||
1084 | sxu32 nByte; | ||
1085 | void *pNew; | ||
1086 | nByte = *pByte; | ||
1087 | if( pBlob->nFlags & (SXBLOB_LOCKED|SXBLOB_STATIC) ){ | ||
1088 | if ( SyBlobFreeSpace(pBlob) < nByte ){ | ||
1089 | *pByte = SyBlobFreeSpace(pBlob); | ||
1090 | if( (*pByte) == 0 ){ | ||
1091 | return SXERR_SHORT; | ||
1092 | } | ||
1093 | } | ||
1094 | return SXRET_OK; | ||
1095 | } | ||
1096 | if( pBlob->nFlags & SXBLOB_RDONLY ){ | ||
1097 | /* Make a copy of the read-only item */ | ||
1098 | if( pBlob->nByte > 0 ){ | ||
1099 | pNew = SyMemBackendDup(pBlob->pAllocator, pBlob->pBlob, pBlob->nByte); | ||
1100 | if( pNew == 0 ){ | ||
1101 | return SXERR_MEM; | ||
1102 | } | ||
1103 | pBlob->pBlob = pNew; | ||
1104 | pBlob->mByte = pBlob->nByte; | ||
1105 | }else{ | ||
1106 | pBlob->pBlob = 0; | ||
1107 | pBlob->mByte = 0; | ||
1108 | } | ||
1109 | /* Remove the read-only flag */ | ||
1110 | pBlob->nFlags &= ~SXBLOB_RDONLY; | ||
1111 | } | ||
1112 | if( SyBlobFreeSpace(pBlob) >= nByte ){ | ||
1113 | return SXRET_OK; | ||
1114 | } | ||
1115 | if( pBlob->mByte > 0 ){ | ||
1116 | nByte = nByte + pBlob->mByte * 2 + SXBLOB_MIN_GROWTH; | ||
1117 | }else if ( nByte < SXBLOB_MIN_GROWTH ){ | ||
1118 | nByte = SXBLOB_MIN_GROWTH; | ||
1119 | } | ||
1120 | pNew = SyMemBackendRealloc(pBlob->pAllocator, pBlob->pBlob, nByte); | ||
1121 | if( pNew == 0 ){ | ||
1122 | return SXERR_MEM; | ||
1123 | } | ||
1124 | pBlob->pBlob = pNew; | ||
1125 | pBlob->mByte = nByte; | ||
1126 | return SXRET_OK; | ||
1127 | } | ||
1128 | JX9_PRIVATE sxi32 SyBlobAppend(SyBlob *pBlob, const void *pData, sxu32 nSize) | ||
1129 | { | ||
1130 | sxu8 *zBlob; | ||
1131 | sxi32 rc; | ||
1132 | if( nSize < 1 ){ | ||
1133 | return SXRET_OK; | ||
1134 | } | ||
1135 | rc = BlobPrepareGrow(&(*pBlob), &nSize); | ||
1136 | if( SXRET_OK != rc ){ | ||
1137 | return rc; | ||
1138 | } | ||
1139 | if( pData ){ | ||
1140 | zBlob = (sxu8 *)pBlob->pBlob ; | ||
1141 | zBlob = &zBlob[pBlob->nByte]; | ||
1142 | pBlob->nByte += nSize; | ||
1143 | SX_MACRO_FAST_MEMCPY(pData, zBlob, nSize); | ||
1144 | } | ||
1145 | return SXRET_OK; | ||
1146 | } | ||
1147 | JX9_PRIVATE sxi32 SyBlobNullAppend(SyBlob *pBlob) | ||
1148 | { | ||
1149 | sxi32 rc; | ||
1150 | sxu32 n; | ||
1151 | n = pBlob->nByte; | ||
1152 | rc = SyBlobAppend(&(*pBlob), (const void *)"\0", sizeof(char)); | ||
1153 | if (rc == SXRET_OK ){ | ||
1154 | pBlob->nByte = n; | ||
1155 | } | ||
1156 | return rc; | ||
1157 | } | ||
1158 | JX9_PRIVATE sxi32 SyBlobDup(SyBlob *pSrc, SyBlob *pDest) | ||
1159 | { | ||
1160 | sxi32 rc = SXRET_OK; | ||
1161 | if( pSrc->nByte > 0 ){ | ||
1162 | rc = SyBlobAppend(&(*pDest), pSrc->pBlob, pSrc->nByte); | ||
1163 | } | ||
1164 | return rc; | ||
1165 | } | ||
1166 | JX9_PRIVATE sxi32 SyBlobReset(SyBlob *pBlob) | ||
1167 | { | ||
1168 | pBlob->nByte = 0; | ||
1169 | if( pBlob->nFlags & SXBLOB_RDONLY ){ | ||
1170 | /* Read-only (Not malloced chunk) */ | ||
1171 | pBlob->pBlob = 0; | ||
1172 | pBlob->mByte = 0; | ||
1173 | pBlob->nFlags &= ~SXBLOB_RDONLY; | ||
1174 | } | ||
1175 | return SXRET_OK; | ||
1176 | } | ||
1177 | JX9_PRIVATE sxi32 SyBlobTruncate(SyBlob *pBlob,sxu32 nNewLen) | ||
1178 | { | ||
1179 | if( nNewLen < pBlob->nByte ){ | ||
1180 | pBlob->nByte = nNewLen; | ||
1181 | } | ||
1182 | return SXRET_OK; | ||
1183 | } | ||
1184 | JX9_PRIVATE sxi32 SyBlobRelease(SyBlob *pBlob) | ||
1185 | { | ||
1186 | if( (pBlob->nFlags & (SXBLOB_STATIC|SXBLOB_RDONLY)) == 0 && pBlob->mByte > 0 ){ | ||
1187 | SyMemBackendFree(pBlob->pAllocator, pBlob->pBlob); | ||
1188 | } | ||
1189 | pBlob->pBlob = 0; | ||
1190 | pBlob->nByte = pBlob->mByte = 0; | ||
1191 | pBlob->nFlags = 0; | ||
1192 | return SXRET_OK; | ||
1193 | } | ||
1194 | #ifndef JX9_DISABLE_BUILTIN_FUNC | ||
1195 | JX9_PRIVATE sxi32 SyBlobSearch(const void *pBlob, sxu32 nLen, const void *pPattern, sxu32 pLen, sxu32 *pOfft) | ||
1196 | { | ||
1197 | const char *zIn = (const char *)pBlob; | ||
1198 | const char *zEnd; | ||
1199 | sxi32 rc; | ||
1200 | if( pLen > nLen ){ | ||
1201 | return SXERR_NOTFOUND; | ||
1202 | } | ||
1203 | zEnd = &zIn[nLen-pLen]; | ||
1204 | for(;;){ | ||
1205 | if( zIn > zEnd ){break;} SX_MACRO_FAST_CMP(zIn, pPattern, pLen, rc); if( rc == 0 ){ if( pOfft ){ *pOfft = (sxu32)(zIn - (const char *)pBlob);} return SXRET_OK; } zIn++; | ||
1206 | if( zIn > zEnd ){break;} SX_MACRO_FAST_CMP(zIn, pPattern, pLen, rc); if( rc == 0 ){ if( pOfft ){ *pOfft = (sxu32)(zIn - (const char *)pBlob);} return SXRET_OK; } zIn++; | ||
1207 | if( zIn > zEnd ){break;} SX_MACRO_FAST_CMP(zIn, pPattern, pLen, rc); if( rc == 0 ){ if( pOfft ){ *pOfft = (sxu32)(zIn - (const char *)pBlob);} return SXRET_OK; } zIn++; | ||
1208 | if( zIn > zEnd ){break;} SX_MACRO_FAST_CMP(zIn, pPattern, pLen, rc); if( rc == 0 ){ if( pOfft ){ *pOfft = (sxu32)(zIn - (const char *)pBlob);} return SXRET_OK; } zIn++; | ||
1209 | } | ||
1210 | return SXERR_NOTFOUND; | ||
1211 | } | ||
1212 | #endif /* JX9_DISABLE_BUILTIN_FUNC */ | ||
1213 | /* SyRunTimeApi:sxds.c */ | ||
1214 | JX9_PRIVATE sxi32 SySetInit(SySet *pSet, SyMemBackend *pAllocator, sxu32 ElemSize) | ||
1215 | { | ||
1216 | pSet->nSize = 0 ; | ||
1217 | pSet->nUsed = 0; | ||
1218 | pSet->nCursor = 0; | ||
1219 | pSet->eSize = ElemSize; | ||
1220 | pSet->pAllocator = pAllocator; | ||
1221 | pSet->pBase = 0; | ||
1222 | pSet->pUserData = 0; | ||
1223 | return SXRET_OK; | ||
1224 | } | ||
1225 | JX9_PRIVATE sxi32 SySetPut(SySet *pSet, const void *pItem) | ||
1226 | { | ||
1227 | unsigned char *zbase; | ||
1228 | if( pSet->nUsed >= pSet->nSize ){ | ||
1229 | void *pNew; | ||
1230 | if( pSet->pAllocator == 0 ){ | ||
1231 | return SXERR_LOCKED; | ||
1232 | } | ||
1233 | if( pSet->nSize <= 0 ){ | ||
1234 | pSet->nSize = 4; | ||
1235 | } | ||
1236 | pNew = SyMemBackendRealloc(pSet->pAllocator, pSet->pBase, pSet->eSize * pSet->nSize * 2); | ||
1237 | if( pNew == 0 ){ | ||
1238 | return SXERR_MEM; | ||
1239 | } | ||
1240 | pSet->pBase = pNew; | ||
1241 | pSet->nSize <<= 1; | ||
1242 | } | ||
1243 | zbase = (unsigned char *)pSet->pBase; | ||
1244 | SX_MACRO_FAST_MEMCPY(pItem, &zbase[pSet->nUsed * pSet->eSize], pSet->eSize); | ||
1245 | pSet->nUsed++; | ||
1246 | return SXRET_OK; | ||
1247 | } | ||
1248 | JX9_PRIVATE sxi32 SySetAlloc(SySet *pSet, sxi32 nItem) | ||
1249 | { | ||
1250 | if( pSet->nSize > 0 ){ | ||
1251 | return SXERR_LOCKED; | ||
1252 | } | ||
1253 | if( nItem < 8 ){ | ||
1254 | nItem = 8; | ||
1255 | } | ||
1256 | pSet->pBase = SyMemBackendAlloc(pSet->pAllocator, pSet->eSize * nItem); | ||
1257 | if( pSet->pBase == 0 ){ | ||
1258 | return SXERR_MEM; | ||
1259 | } | ||
1260 | pSet->nSize = nItem; | ||
1261 | return SXRET_OK; | ||
1262 | } | ||
1263 | JX9_PRIVATE sxi32 SySetReset(SySet *pSet) | ||
1264 | { | ||
1265 | pSet->nUsed = 0; | ||
1266 | pSet->nCursor = 0; | ||
1267 | return SXRET_OK; | ||
1268 | } | ||
1269 | JX9_PRIVATE sxi32 SySetResetCursor(SySet *pSet) | ||
1270 | { | ||
1271 | pSet->nCursor = 0; | ||
1272 | return SXRET_OK; | ||
1273 | } | ||
1274 | JX9_PRIVATE sxi32 SySetGetNextEntry(SySet *pSet, void **ppEntry) | ||
1275 | { | ||
1276 | register unsigned char *zSrc; | ||
1277 | if( pSet->nCursor >= pSet->nUsed ){ | ||
1278 | /* Reset cursor */ | ||
1279 | pSet->nCursor = 0; | ||
1280 | return SXERR_EOF; | ||
1281 | } | ||
1282 | zSrc = (unsigned char *)SySetBasePtr(pSet); | ||
1283 | if( ppEntry ){ | ||
1284 | *ppEntry = (void *)&zSrc[pSet->nCursor * pSet->eSize]; | ||
1285 | } | ||
1286 | pSet->nCursor++; | ||
1287 | return SXRET_OK; | ||
1288 | } | ||
1289 | JX9_PRIVATE sxi32 SySetRelease(SySet *pSet) | ||
1290 | { | ||
1291 | sxi32 rc = SXRET_OK; | ||
1292 | if( pSet->pAllocator && pSet->pBase ){ | ||
1293 | rc = SyMemBackendFree(pSet->pAllocator, pSet->pBase); | ||
1294 | } | ||
1295 | pSet->pBase = 0; | ||
1296 | pSet->nUsed = 0; | ||
1297 | pSet->nCursor = 0; | ||
1298 | return rc; | ||
1299 | } | ||
1300 | JX9_PRIVATE void * SySetPeek(SySet *pSet) | ||
1301 | { | ||
1302 | const char *zBase; | ||
1303 | if( pSet->nUsed <= 0 ){ | ||
1304 | return 0; | ||
1305 | } | ||
1306 | zBase = (const char *)pSet->pBase; | ||
1307 | return (void *)&zBase[(pSet->nUsed - 1) * pSet->eSize]; | ||
1308 | } | ||
1309 | JX9_PRIVATE void * SySetPop(SySet *pSet) | ||
1310 | { | ||
1311 | const char *zBase; | ||
1312 | void *pData; | ||
1313 | if( pSet->nUsed <= 0 ){ | ||
1314 | return 0; | ||
1315 | } | ||
1316 | zBase = (const char *)pSet->pBase; | ||
1317 | pSet->nUsed--; | ||
1318 | pData = (void *)&zBase[pSet->nUsed * pSet->eSize]; | ||
1319 | return pData; | ||
1320 | } | ||
1321 | JX9_PRIVATE void * SySetAt(SySet *pSet, sxu32 nIdx) | ||
1322 | { | ||
1323 | const char *zBase; | ||
1324 | if( nIdx >= pSet->nUsed ){ | ||
1325 | /* Out of range */ | ||
1326 | return 0; | ||
1327 | } | ||
1328 | zBase = (const char *)pSet->pBase; | ||
1329 | return (void *)&zBase[nIdx * pSet->eSize]; | ||
1330 | } | ||
1331 | /* Private hash entry */ | ||
1332 | struct SyHashEntry_Pr | ||
1333 | { | ||
1334 | const void *pKey; /* Hash key */ | ||
1335 | sxu32 nKeyLen; /* Key length */ | ||
1336 | void *pUserData; /* User private data */ | ||
1337 | /* Private fields */ | ||
1338 | sxu32 nHash; | ||
1339 | SyHash *pHash; | ||
1340 | SyHashEntry_Pr *pNext, *pPrev; /* Next and previous entry in the list */ | ||
1341 | SyHashEntry_Pr *pNextCollide, *pPrevCollide; /* Collision list */ | ||
1342 | }; | ||
1343 | #define INVALID_HASH(H) ((H)->apBucket == 0) | ||
1344 | JX9_PRIVATE sxi32 SyHashInit(SyHash *pHash, SyMemBackend *pAllocator, ProcHash xHash, ProcCmp xCmp) | ||
1345 | { | ||
1346 | SyHashEntry_Pr **apNew; | ||
1347 | #if defined(UNTRUST) | ||
1348 | if( pHash == 0 ){ | ||
1349 | return SXERR_EMPTY; | ||
1350 | } | ||
1351 | #endif | ||
1352 | /* Allocate a new table */ | ||
1353 | apNew = (SyHashEntry_Pr **)SyMemBackendAlloc(&(*pAllocator), sizeof(SyHashEntry_Pr *) * SXHASH_BUCKET_SIZE); | ||
1354 | if( apNew == 0 ){ | ||
1355 | return SXERR_MEM; | ||
1356 | } | ||
1357 | SyZero((void *)apNew, sizeof(SyHashEntry_Pr *) * SXHASH_BUCKET_SIZE); | ||
1358 | pHash->pAllocator = &(*pAllocator); | ||
1359 | pHash->xHash = xHash ? xHash : SyBinHash; | ||
1360 | pHash->xCmp = xCmp ? xCmp : SyMemcmp; | ||
1361 | pHash->pCurrent = pHash->pList = 0; | ||
1362 | pHash->nEntry = 0; | ||
1363 | pHash->apBucket = apNew; | ||
1364 | pHash->nBucketSize = SXHASH_BUCKET_SIZE; | ||
1365 | return SXRET_OK; | ||
1366 | } | ||
1367 | JX9_PRIVATE sxi32 SyHashRelease(SyHash *pHash) | ||
1368 | { | ||
1369 | SyHashEntry_Pr *pEntry, *pNext; | ||
1370 | #if defined(UNTRUST) | ||
1371 | if( INVALID_HASH(pHash) ){ | ||
1372 | return SXERR_EMPTY; | ||
1373 | } | ||
1374 | #endif | ||
1375 | pEntry = pHash->pList; | ||
1376 | for(;;){ | ||
1377 | if( pHash->nEntry == 0 ){ | ||
1378 | break; | ||
1379 | } | ||
1380 | pNext = pEntry->pNext; | ||
1381 | SyMemBackendPoolFree(pHash->pAllocator, pEntry); | ||
1382 | pEntry = pNext; | ||
1383 | pHash->nEntry--; | ||
1384 | } | ||
1385 | if( pHash->apBucket ){ | ||
1386 | SyMemBackendFree(pHash->pAllocator, (void *)pHash->apBucket); | ||
1387 | } | ||
1388 | pHash->apBucket = 0; | ||
1389 | pHash->nBucketSize = 0; | ||
1390 | pHash->pAllocator = 0; | ||
1391 | return SXRET_OK; | ||
1392 | } | ||
1393 | static SyHashEntry_Pr * HashGetEntry(SyHash *pHash, const void *pKey, sxu32 nKeyLen) | ||
1394 | { | ||
1395 | SyHashEntry_Pr *pEntry; | ||
1396 | sxu32 nHash; | ||
1397 | |||
1398 | nHash = pHash->xHash(pKey, nKeyLen); | ||
1399 | pEntry = pHash->apBucket[nHash & (pHash->nBucketSize - 1)]; | ||
1400 | for(;;){ | ||
1401 | if( pEntry == 0 ){ | ||
1402 | break; | ||
1403 | } | ||
1404 | if( pEntry->nHash == nHash && pEntry->nKeyLen == nKeyLen && | ||
1405 | pHash->xCmp(pEntry->pKey, pKey, nKeyLen) == 0 ){ | ||
1406 | return pEntry; | ||
1407 | } | ||
1408 | pEntry = pEntry->pNextCollide; | ||
1409 | } | ||
1410 | /* Entry not found */ | ||
1411 | return 0; | ||
1412 | } | ||
1413 | JX9_PRIVATE SyHashEntry * SyHashGet(SyHash *pHash, const void *pKey, sxu32 nKeyLen) | ||
1414 | { | ||
1415 | SyHashEntry_Pr *pEntry; | ||
1416 | #if defined(UNTRUST) | ||
1417 | if( INVALID_HASH(pHash) ){ | ||
1418 | return 0; | ||
1419 | } | ||
1420 | #endif | ||
1421 | if( pHash->nEntry < 1 || nKeyLen < 1 ){ | ||
1422 | /* Don't bother hashing, return immediately */ | ||
1423 | return 0; | ||
1424 | } | ||
1425 | pEntry = HashGetEntry(&(*pHash), pKey, nKeyLen); | ||
1426 | if( pEntry == 0 ){ | ||
1427 | return 0; | ||
1428 | } | ||
1429 | return (SyHashEntry *)pEntry; | ||
1430 | } | ||
1431 | static sxi32 HashDeleteEntry(SyHash *pHash, SyHashEntry_Pr *pEntry, void **ppUserData) | ||
1432 | { | ||
1433 | sxi32 rc; | ||
1434 | if( pEntry->pPrevCollide == 0 ){ | ||
1435 | pHash->apBucket[pEntry->nHash & (pHash->nBucketSize - 1)] = pEntry->pNextCollide; | ||
1436 | }else{ | ||
1437 | pEntry->pPrevCollide->pNextCollide = pEntry->pNextCollide; | ||
1438 | } | ||
1439 | if( pEntry->pNextCollide ){ | ||
1440 | pEntry->pNextCollide->pPrevCollide = pEntry->pPrevCollide; | ||
1441 | } | ||
1442 | MACRO_LD_REMOVE(pHash->pList, pEntry); | ||
1443 | pHash->nEntry--; | ||
1444 | if( ppUserData ){ | ||
1445 | /* Write a pointer to the user data */ | ||
1446 | *ppUserData = pEntry->pUserData; | ||
1447 | } | ||
1448 | /* Release the entry */ | ||
1449 | rc = SyMemBackendPoolFree(pHash->pAllocator, pEntry); | ||
1450 | return rc; | ||
1451 | } | ||
1452 | JX9_PRIVATE sxi32 SyHashDeleteEntry(SyHash *pHash, const void *pKey, sxu32 nKeyLen, void **ppUserData) | ||
1453 | { | ||
1454 | SyHashEntry_Pr *pEntry; | ||
1455 | sxi32 rc; | ||
1456 | #if defined(UNTRUST) | ||
1457 | if( INVALID_HASH(pHash) ){ | ||
1458 | return SXERR_CORRUPT; | ||
1459 | } | ||
1460 | #endif | ||
1461 | pEntry = HashGetEntry(&(*pHash), pKey, nKeyLen); | ||
1462 | if( pEntry == 0 ){ | ||
1463 | return SXERR_NOTFOUND; | ||
1464 | } | ||
1465 | rc = HashDeleteEntry(&(*pHash), pEntry, ppUserData); | ||
1466 | return rc; | ||
1467 | } | ||
1468 | JX9_PRIVATE sxi32 SyHashForEach(SyHash *pHash, sxi32 (*xStep)(SyHashEntry *, void *), void *pUserData) | ||
1469 | { | ||
1470 | SyHashEntry_Pr *pEntry; | ||
1471 | sxi32 rc; | ||
1472 | sxu32 n; | ||
1473 | #if defined(UNTRUST) | ||
1474 | if( INVALID_HASH(pHash) || xStep == 0){ | ||
1475 | return 0; | ||
1476 | } | ||
1477 | #endif | ||
1478 | pEntry = pHash->pList; | ||
1479 | for( n = 0 ; n < pHash->nEntry ; n++ ){ | ||
1480 | /* Invoke the callback */ | ||
1481 | rc = xStep((SyHashEntry *)pEntry, pUserData); | ||
1482 | if( rc != SXRET_OK ){ | ||
1483 | return rc; | ||
1484 | } | ||
1485 | /* Point to the next entry */ | ||
1486 | pEntry = pEntry->pNext; | ||
1487 | } | ||
1488 | return SXRET_OK; | ||
1489 | } | ||
1490 | static sxi32 HashGrowTable(SyHash *pHash) | ||
1491 | { | ||
1492 | sxu32 nNewSize = pHash->nBucketSize * 2; | ||
1493 | SyHashEntry_Pr *pEntry; | ||
1494 | SyHashEntry_Pr **apNew; | ||
1495 | sxu32 n, iBucket; | ||
1496 | |||
1497 | /* Allocate a new larger table */ | ||
1498 | apNew = (SyHashEntry_Pr **)SyMemBackendAlloc(pHash->pAllocator, nNewSize * sizeof(SyHashEntry_Pr *)); | ||
1499 | if( apNew == 0 ){ | ||
1500 | /* Not so fatal, simply a performance hit */ | ||
1501 | return SXRET_OK; | ||
1502 | } | ||
1503 | /* Zero the new table */ | ||
1504 | SyZero((void *)apNew, nNewSize * sizeof(SyHashEntry_Pr *)); | ||
1505 | /* Rehash all entries */ | ||
1506 | for( n = 0, pEntry = pHash->pList; n < pHash->nEntry ; n++ ){ | ||
1507 | pEntry->pNextCollide = pEntry->pPrevCollide = 0; | ||
1508 | /* Install in the new bucket */ | ||
1509 | iBucket = pEntry->nHash & (nNewSize - 1); | ||
1510 | pEntry->pNextCollide = apNew[iBucket]; | ||
1511 | if( apNew[iBucket] != 0 ){ | ||
1512 | apNew[iBucket]->pPrevCollide = pEntry; | ||
1513 | } | ||
1514 | apNew[iBucket] = pEntry; | ||
1515 | /* Point to the next entry */ | ||
1516 | pEntry = pEntry->pNext; | ||
1517 | } | ||
1518 | /* Release the old table and reflect the change */ | ||
1519 | SyMemBackendFree(pHash->pAllocator, (void *)pHash->apBucket); | ||
1520 | pHash->apBucket = apNew; | ||
1521 | pHash->nBucketSize = nNewSize; | ||
1522 | return SXRET_OK; | ||
1523 | } | ||
1524 | static sxi32 HashInsert(SyHash *pHash, SyHashEntry_Pr *pEntry) | ||
1525 | { | ||
1526 | sxu32 iBucket = pEntry->nHash & (pHash->nBucketSize - 1); | ||
1527 | /* Insert the entry in its corresponding bcuket */ | ||
1528 | pEntry->pNextCollide = pHash->apBucket[iBucket]; | ||
1529 | if( pHash->apBucket[iBucket] != 0 ){ | ||
1530 | pHash->apBucket[iBucket]->pPrevCollide = pEntry; | ||
1531 | } | ||
1532 | pHash->apBucket[iBucket] = pEntry; | ||
1533 | /* Link to the entry list */ | ||
1534 | MACRO_LD_PUSH(pHash->pList, pEntry); | ||
1535 | if( pHash->nEntry == 0 ){ | ||
1536 | pHash->pCurrent = pHash->pList; | ||
1537 | } | ||
1538 | pHash->nEntry++; | ||
1539 | return SXRET_OK; | ||
1540 | } | ||
1541 | JX9_PRIVATE sxi32 SyHashInsert(SyHash *pHash, const void *pKey, sxu32 nKeyLen, void *pUserData) | ||
1542 | { | ||
1543 | SyHashEntry_Pr *pEntry; | ||
1544 | sxi32 rc; | ||
1545 | #if defined(UNTRUST) | ||
1546 | if( INVALID_HASH(pHash) || pKey == 0 ){ | ||
1547 | return SXERR_CORRUPT; | ||
1548 | } | ||
1549 | #endif | ||
1550 | if( pHash->nEntry >= pHash->nBucketSize * SXHASH_FILL_FACTOR ){ | ||
1551 | rc = HashGrowTable(&(*pHash)); | ||
1552 | if( rc != SXRET_OK ){ | ||
1553 | return rc; | ||
1554 | } | ||
1555 | } | ||
1556 | /* Allocate a new hash entry */ | ||
1557 | pEntry = (SyHashEntry_Pr *)SyMemBackendPoolAlloc(pHash->pAllocator, sizeof(SyHashEntry_Pr)); | ||
1558 | if( pEntry == 0 ){ | ||
1559 | return SXERR_MEM; | ||
1560 | } | ||
1561 | /* Zero the entry */ | ||
1562 | SyZero(pEntry, sizeof(SyHashEntry_Pr)); | ||
1563 | pEntry->pHash = pHash; | ||
1564 | pEntry->pKey = pKey; | ||
1565 | pEntry->nKeyLen = nKeyLen; | ||
1566 | pEntry->pUserData = pUserData; | ||
1567 | pEntry->nHash = pHash->xHash(pEntry->pKey, pEntry->nKeyLen); | ||
1568 | /* Finally insert the entry in its corresponding bucket */ | ||
1569 | rc = HashInsert(&(*pHash), pEntry); | ||
1570 | return rc; | ||
1571 | } | ||
1572 | /* SyRunTimeApi:sxutils.c */ | ||
1573 | JX9_PRIVATE sxi32 SyStrIsNumeric(const char *zSrc, sxu32 nLen, sxu8 *pReal, const char **pzTail) | ||
1574 | { | ||
1575 | const char *zCur, *zEnd; | ||
1576 | #ifdef UNTRUST | ||
1577 | if( SX_EMPTY_STR(zSrc) ){ | ||
1578 | return SXERR_EMPTY; | ||
1579 | } | ||
1580 | #endif | ||
1581 | zEnd = &zSrc[nLen]; | ||
1582 | /* Jump leading white spaces */ | ||
1583 | while( zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisSpace(zSrc[0]) ){ | ||
1584 | zSrc++; | ||
1585 | } | ||
1586 | if( zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-') ){ | ||
1587 | zSrc++; | ||
1588 | } | ||
1589 | zCur = zSrc; | ||
1590 | if( pReal ){ | ||
1591 | *pReal = FALSE; | ||
1592 | } | ||
1593 | for(;;){ | ||
1594 | if( zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0]) ){ break; } zSrc++; | ||
1595 | if( zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0]) ){ break; } zSrc++; | ||
1596 | if( zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0]) ){ break; } zSrc++; | ||
1597 | if( zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0]) ){ break; } zSrc++; | ||
1598 | }; | ||
1599 | if( zSrc < zEnd && zSrc > zCur ){ | ||
1600 | int c = zSrc[0]; | ||
1601 | if( c == '.' ){ | ||
1602 | zSrc++; | ||
1603 | if( pReal ){ | ||
1604 | *pReal = TRUE; | ||
1605 | } | ||
1606 | if( pzTail ){ | ||
1607 | while( zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0]) ){ | ||
1608 | zSrc++; | ||
1609 | } | ||
1610 | if( zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E') ){ | ||
1611 | zSrc++; | ||
1612 | if( zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-') ){ | ||
1613 | zSrc++; | ||
1614 | } | ||
1615 | while( zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0]) ){ | ||
1616 | zSrc++; | ||
1617 | } | ||
1618 | } | ||
1619 | } | ||
1620 | }else if( c == 'e' || c == 'E' ){ | ||
1621 | zSrc++; | ||
1622 | if( pReal ){ | ||
1623 | *pReal = TRUE; | ||
1624 | } | ||
1625 | if( pzTail ){ | ||
1626 | if( zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-') ){ | ||
1627 | zSrc++; | ||
1628 | } | ||
1629 | while( zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0]) ){ | ||
1630 | zSrc++; | ||
1631 | } | ||
1632 | } | ||
1633 | } | ||
1634 | } | ||
1635 | if( pzTail ){ | ||
1636 | /* Point to the non numeric part */ | ||
1637 | *pzTail = zSrc; | ||
1638 | } | ||
1639 | return zSrc > zCur ? SXRET_OK /* String prefix is numeric */ : SXERR_INVALID /* Not a digit stream */; | ||
1640 | } | ||
1641 | #define SXINT32_MIN_STR "2147483648" | ||
1642 | #define SXINT32_MAX_STR "2147483647" | ||
1643 | #define SXINT64_MIN_STR "9223372036854775808" | ||
1644 | #define SXINT64_MAX_STR "9223372036854775807" | ||
1645 | JX9_PRIVATE sxi32 SyStrToInt32(const char *zSrc, sxu32 nLen, void * pOutVal, const char **zRest) | ||
1646 | { | ||
1647 | int isNeg = FALSE; | ||
1648 | const char *zEnd; | ||
1649 | sxi32 nVal = 0; | ||
1650 | sxi16 i; | ||
1651 | #if defined(UNTRUST) | ||
1652 | if( SX_EMPTY_STR(zSrc) ){ | ||
1653 | if( pOutVal ){ | ||
1654 | *(sxi32 *)pOutVal = 0; | ||
1655 | } | ||
1656 | return SXERR_EMPTY; | ||
1657 | } | ||
1658 | #endif | ||
1659 | zEnd = &zSrc[nLen]; | ||
1660 | while(zSrc < zEnd && SyisSpace(zSrc[0]) ){ | ||
1661 | zSrc++; | ||
1662 | } | ||
1663 | if( zSrc < zEnd && ( zSrc[0] == '-' || zSrc[0] == '+' ) ){ | ||
1664 | isNeg = (zSrc[0] == '-') ? TRUE :FALSE; | ||
1665 | zSrc++; | ||
1666 | } | ||
1667 | /* Skip leading zero */ | ||
1668 | while(zSrc < zEnd && zSrc[0] == '0' ){ | ||
1669 | zSrc++; | ||
1670 | } | ||
1671 | i = 10; | ||
1672 | if( (sxu32)(zEnd-zSrc) >= 10 ){ | ||
1673 | /* Handle overflow */ | ||
1674 | i = SyMemcmp(zSrc, (isNeg == TRUE) ? SXINT32_MIN_STR : SXINT32_MAX_STR, nLen) <= 0 ? 10 : 9; | ||
1675 | } | ||
1676 | for(;;){ | ||
1677 | if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])){ break; } nVal = nVal * 10 + ( zSrc[0] - '0' ) ; --i ; zSrc++; | ||
1678 | if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])){ break; } nVal = nVal * 10 + ( zSrc[0] - '0' ) ; --i ; zSrc++; | ||
1679 | if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])){ break; } nVal = nVal * 10 + ( zSrc[0] - '0' ) ; --i ; zSrc++; | ||
1680 | if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])){ break; } nVal = nVal * 10 + ( zSrc[0] - '0' ) ; --i ; zSrc++; | ||
1681 | } | ||
1682 | /* Skip trailing spaces */ | ||
1683 | while(zSrc < zEnd && SyisSpace(zSrc[0])){ | ||
1684 | zSrc++; | ||
1685 | } | ||
1686 | if( zRest ){ | ||
1687 | *zRest = (char *)zSrc; | ||
1688 | } | ||
1689 | if( pOutVal ){ | ||
1690 | if( isNeg == TRUE && nVal != 0 ){ | ||
1691 | nVal = -nVal; | ||
1692 | } | ||
1693 | *(sxi32 *)pOutVal = nVal; | ||
1694 | } | ||
1695 | return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; | ||
1696 | } | ||
1697 | JX9_PRIVATE sxi32 SyStrToInt64(const char *zSrc, sxu32 nLen, void * pOutVal, const char **zRest) | ||
1698 | { | ||
1699 | int isNeg = FALSE; | ||
1700 | const char *zEnd; | ||
1701 | sxi64 nVal; | ||
1702 | sxi16 i; | ||
1703 | #if defined(UNTRUST) | ||
1704 | if( SX_EMPTY_STR(zSrc) ){ | ||
1705 | if( pOutVal ){ | ||
1706 | *(sxi32 *)pOutVal = 0; | ||
1707 | } | ||
1708 | return SXERR_EMPTY; | ||
1709 | } | ||
1710 | #endif | ||
1711 | zEnd = &zSrc[nLen]; | ||
1712 | while(zSrc < zEnd && SyisSpace(zSrc[0]) ){ | ||
1713 | zSrc++; | ||
1714 | } | ||
1715 | if( zSrc < zEnd && ( zSrc[0] == '-' || zSrc[0] == '+' ) ){ | ||
1716 | isNeg = (zSrc[0] == '-') ? TRUE :FALSE; | ||
1717 | zSrc++; | ||
1718 | } | ||
1719 | /* Skip leading zero */ | ||
1720 | while(zSrc < zEnd && zSrc[0] == '0' ){ | ||
1721 | zSrc++; | ||
1722 | } | ||
1723 | i = 19; | ||
1724 | if( (sxu32)(zEnd-zSrc) >= 19 ){ | ||
1725 | i = SyMemcmp(zSrc, isNeg ? SXINT64_MIN_STR : SXINT64_MAX_STR, 19) <= 0 ? 19 : 18 ; | ||
1726 | } | ||
1727 | nVal = 0; | ||
1728 | for(;;){ | ||
1729 | if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])){ break; } nVal = nVal * 10 + ( zSrc[0] - '0' ) ; --i ; zSrc++; | ||
1730 | if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])){ break; } nVal = nVal * 10 + ( zSrc[0] - '0' ) ; --i ; zSrc++; | ||
1731 | if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])){ break; } nVal = nVal * 10 + ( zSrc[0] - '0' ) ; --i ; zSrc++; | ||
1732 | if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])){ break; } nVal = nVal * 10 + ( zSrc[0] - '0' ) ; --i ; zSrc++; | ||
1733 | } | ||
1734 | /* Skip trailing spaces */ | ||
1735 | while(zSrc < zEnd && SyisSpace(zSrc[0])){ | ||
1736 | zSrc++; | ||
1737 | } | ||
1738 | if( zRest ){ | ||
1739 | *zRest = (char *)zSrc; | ||
1740 | } | ||
1741 | if( pOutVal ){ | ||
1742 | if( isNeg == TRUE && nVal != 0 ){ | ||
1743 | nVal = -nVal; | ||
1744 | } | ||
1745 | *(sxi64 *)pOutVal = nVal; | ||
1746 | } | ||
1747 | return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; | ||
1748 | } | ||
1749 | JX9_PRIVATE sxi32 SyHexToint(sxi32 c) | ||
1750 | { | ||
1751 | switch(c){ | ||
1752 | case '0': return 0; | ||
1753 | case '1': return 1; | ||
1754 | case '2': return 2; | ||
1755 | case '3': return 3; | ||
1756 | case '4': return 4; | ||
1757 | case '5': return 5; | ||
1758 | case '6': return 6; | ||
1759 | case '7': return 7; | ||
1760 | case '8': return 8; | ||
1761 | case '9': return 9; | ||
1762 | case 'A': case 'a': return 10; | ||
1763 | case 'B': case 'b': return 11; | ||
1764 | case 'C': case 'c': return 12; | ||
1765 | case 'D': case 'd': return 13; | ||
1766 | case 'E': case 'e': return 14; | ||
1767 | case 'F': case 'f': return 15; | ||
1768 | } | ||
1769 | return -1; | ||
1770 | } | ||
1771 | JX9_PRIVATE sxi32 SyHexStrToInt64(const char *zSrc, sxu32 nLen, void * pOutVal, const char **zRest) | ||
1772 | { | ||
1773 | const char *zIn, *zEnd; | ||
1774 | int isNeg = FALSE; | ||
1775 | sxi64 nVal = 0; | ||
1776 | #if defined(UNTRUST) | ||
1777 | if( SX_EMPTY_STR(zSrc) ){ | ||
1778 | if( pOutVal ){ | ||
1779 | *(sxi32 *)pOutVal = 0; | ||
1780 | } | ||
1781 | return SXERR_EMPTY; | ||
1782 | } | ||
1783 | #endif | ||
1784 | zEnd = &zSrc[nLen]; | ||
1785 | while( zSrc < zEnd && SyisSpace(zSrc[0]) ){ | ||
1786 | zSrc++; | ||
1787 | } | ||
1788 | if( zSrc < zEnd && ( *zSrc == '-' || *zSrc == '+' ) ){ | ||
1789 | isNeg = (zSrc[0] == '-') ? TRUE :FALSE; | ||
1790 | zSrc++; | ||
1791 | } | ||
1792 | if( zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'x' || zSrc[1] == 'X') ){ | ||
1793 | /* Bypass hex prefix */ | ||
1794 | zSrc += sizeof(char) * 2; | ||
1795 | } | ||
1796 | /* Skip leading zero */ | ||
1797 | while(zSrc < zEnd && zSrc[0] == '0' ){ | ||
1798 | zSrc++; | ||
1799 | } | ||
1800 | zIn = zSrc; | ||
1801 | for(;;){ | ||
1802 | if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc-zIn) > 15) break; nVal = nVal * 16 + SyHexToint(zSrc[0]); zSrc++ ; | ||
1803 | if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc-zIn) > 15) break; nVal = nVal * 16 + SyHexToint(zSrc[0]); zSrc++ ; | ||
1804 | if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc-zIn) > 15) break; nVal = nVal * 16 + SyHexToint(zSrc[0]); zSrc++ ; | ||
1805 | if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc-zIn) > 15) break; nVal = nVal * 16 + SyHexToint(zSrc[0]); zSrc++ ; | ||
1806 | } | ||
1807 | while( zSrc < zEnd && SyisSpace(zSrc[0]) ){ | ||
1808 | zSrc++; | ||
1809 | } | ||
1810 | if( zRest ){ | ||
1811 | *zRest = zSrc; | ||
1812 | } | ||
1813 | if( pOutVal ){ | ||
1814 | if( isNeg == TRUE && nVal != 0 ){ | ||
1815 | nVal = -nVal; | ||
1816 | } | ||
1817 | *(sxi64 *)pOutVal = nVal; | ||
1818 | } | ||
1819 | return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX; | ||
1820 | } | ||
1821 | JX9_PRIVATE sxi32 SyOctalStrToInt64(const char *zSrc, sxu32 nLen, void * pOutVal, const char **zRest) | ||
1822 | { | ||
1823 | const char *zIn, *zEnd; | ||
1824 | int isNeg = FALSE; | ||
1825 | sxi64 nVal = 0; | ||
1826 | int c; | ||
1827 | #if defined(UNTRUST) | ||
1828 | if( SX_EMPTY_STR(zSrc) ){ | ||
1829 | if( pOutVal ){ | ||
1830 | *(sxi32 *)pOutVal = 0; | ||
1831 | } | ||
1832 | return SXERR_EMPTY; | ||
1833 | } | ||
1834 | #endif | ||
1835 | zEnd = &zSrc[nLen]; | ||
1836 | while(zSrc < zEnd && SyisSpace(zSrc[0]) ){ | ||
1837 | zSrc++; | ||
1838 | } | ||
1839 | if( zSrc < zEnd && ( zSrc[0] == '-' || zSrc[0] == '+' ) ){ | ||
1840 | isNeg = (zSrc[0] == '-') ? TRUE :FALSE; | ||
1841 | zSrc++; | ||
1842 | } | ||
1843 | /* Skip leading zero */ | ||
1844 | while(zSrc < zEnd && zSrc[0] == '0' ){ | ||
1845 | zSrc++; | ||
1846 | } | ||
1847 | zIn = zSrc; | ||
1848 | for(;;){ | ||
1849 | if(zSrc >= zEnd || !SyisDigit(zSrc[0])){ break; } if( (c=zSrc[0]-'0') > 7 || (int)(zSrc-zIn) > 20){ break;} nVal = nVal * 8 + c; zSrc++; | ||
1850 | if(zSrc >= zEnd || !SyisDigit(zSrc[0])){ break; } if( (c=zSrc[0]-'0') > 7 || (int)(zSrc-zIn) > 20){ break;} nVal = nVal * 8 + c; zSrc++; | ||
1851 | if(zSrc >= zEnd || !SyisDigit(zSrc[0])){ break; } if( (c=zSrc[0]-'0') > 7 || (int)(zSrc-zIn) > 20){ break;} nVal = nVal * 8 + c; zSrc++; | ||
1852 | if(zSrc >= zEnd || !SyisDigit(zSrc[0])){ break; } if( (c=zSrc[0]-'0') > 7 || (int)(zSrc-zIn) > 20){ break;} nVal = nVal * 8 + c; zSrc++; | ||
1853 | } | ||
1854 | /* Skip trailing spaces */ | ||
1855 | while(zSrc < zEnd && SyisSpace(zSrc[0])){ | ||
1856 | zSrc++; | ||
1857 | } | ||
1858 | if( zRest ){ | ||
1859 | *zRest = zSrc; | ||
1860 | } | ||
1861 | if( pOutVal ){ | ||
1862 | if( isNeg == TRUE && nVal != 0 ){ | ||
1863 | nVal = -nVal; | ||
1864 | } | ||
1865 | *(sxi64 *)pOutVal = nVal; | ||
1866 | } | ||
1867 | return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; | ||
1868 | } | ||
1869 | JX9_PRIVATE sxi32 SyBinaryStrToInt64(const char *zSrc, sxu32 nLen, void * pOutVal, const char **zRest) | ||
1870 | { | ||
1871 | const char *zIn, *zEnd; | ||
1872 | int isNeg = FALSE; | ||
1873 | sxi64 nVal = 0; | ||
1874 | int c; | ||
1875 | #if defined(UNTRUST) | ||
1876 | if( SX_EMPTY_STR(zSrc) ){ | ||
1877 | if( pOutVal ){ | ||
1878 | *(sxi32 *)pOutVal = 0; | ||
1879 | } | ||
1880 | return SXERR_EMPTY; | ||
1881 | } | ||
1882 | #endif | ||
1883 | zEnd = &zSrc[nLen]; | ||
1884 | while(zSrc < zEnd && SyisSpace(zSrc[0]) ){ | ||
1885 | zSrc++; | ||
1886 | } | ||
1887 | if( zSrc < zEnd && ( zSrc[0] == '-' || zSrc[0] == '+' ) ){ | ||
1888 | isNeg = (zSrc[0] == '-') ? TRUE :FALSE; | ||
1889 | zSrc++; | ||
1890 | } | ||
1891 | if( zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'b' || zSrc[1] == 'B') ){ | ||
1892 | /* Bypass binary prefix */ | ||
1893 | zSrc += sizeof(char) * 2; | ||
1894 | } | ||
1895 | /* Skip leading zero */ | ||
1896 | while(zSrc < zEnd && zSrc[0] == '0' ){ | ||
1897 | zSrc++; | ||
1898 | } | ||
1899 | zIn = zSrc; | ||
1900 | for(;;){ | ||
1901 | if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc-zIn) > 62){ break; } c = zSrc[0] - '0'; nVal = (nVal << 1) + c; zSrc++; | ||
1902 | if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc-zIn) > 62){ break; } c = zSrc[0] - '0'; nVal = (nVal << 1) + c; zSrc++; | ||
1903 | if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc-zIn) > 62){ break; } c = zSrc[0] - '0'; nVal = (nVal << 1) + c; zSrc++; | ||
1904 | if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc-zIn) > 62){ break; } c = zSrc[0] - '0'; nVal = (nVal << 1) + c; zSrc++; | ||
1905 | } | ||
1906 | /* Skip trailing spaces */ | ||
1907 | while(zSrc < zEnd && SyisSpace(zSrc[0])){ | ||
1908 | zSrc++; | ||
1909 | } | ||
1910 | if( zRest ){ | ||
1911 | *zRest = zSrc; | ||
1912 | } | ||
1913 | if( pOutVal ){ | ||
1914 | if( isNeg == TRUE && nVal != 0 ){ | ||
1915 | nVal = -nVal; | ||
1916 | } | ||
1917 | *(sxi64 *)pOutVal = nVal; | ||
1918 | } | ||
1919 | return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; | ||
1920 | } | ||
1921 | JX9_PRIVATE sxi32 SyStrToReal(const char *zSrc, sxu32 nLen, void * pOutVal, const char **zRest) | ||
1922 | { | ||
1923 | #define SXDBL_DIG 15 | ||
1924 | #define SXDBL_MAX_EXP 308 | ||
1925 | #define SXDBL_MIN_EXP_PLUS 307 | ||
1926 | static const sxreal aTab[] = { | ||
1927 | 10, | ||
1928 | 1.0e2, | ||
1929 | 1.0e4, | ||
1930 | 1.0e8, | ||
1931 | 1.0e16, | ||
1932 | 1.0e32, | ||
1933 | 1.0e64, | ||
1934 | 1.0e128, | ||
1935 | 1.0e256 | ||
1936 | }; | ||
1937 | sxu8 neg = FALSE; | ||
1938 | sxreal Val = 0.0; | ||
1939 | const char *zEnd; | ||
1940 | sxi32 Lim, exp; | ||
1941 | sxreal *p = 0; | ||
1942 | #ifdef UNTRUST | ||
1943 | if( SX_EMPTY_STR(zSrc) ){ | ||
1944 | if( pOutVal ){ | ||
1945 | *(sxreal *)pOutVal = 0.0; | ||
1946 | } | ||
1947 | return SXERR_EMPTY; | ||
1948 | } | ||
1949 | #endif | ||
1950 | zEnd = &zSrc[nLen]; | ||
1951 | while( zSrc < zEnd && SyisSpace(zSrc[0]) ){ | ||
1952 | zSrc++; | ||
1953 | } | ||
1954 | if( zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+' ) ){ | ||
1955 | neg = zSrc[0] == '-' ? TRUE : FALSE ; | ||
1956 | zSrc++; | ||
1957 | } | ||
1958 | Lim = SXDBL_DIG ; | ||
1959 | for(;;){ | ||
1960 | if(zSrc >= zEnd||!Lim||!SyisDigit(zSrc[0])) break ; Val = Val * 10.0 + (zSrc[0] - '0') ; zSrc++ ; --Lim; | ||
1961 | if(zSrc >= zEnd||!Lim||!SyisDigit(zSrc[0])) break ; Val = Val * 10.0 + (zSrc[0] - '0') ; zSrc++ ; --Lim; | ||
1962 | if(zSrc >= zEnd||!Lim||!SyisDigit(zSrc[0])) break ; Val = Val * 10.0 + (zSrc[0] - '0') ; zSrc++ ; --Lim; | ||
1963 | if(zSrc >= zEnd||!Lim||!SyisDigit(zSrc[0])) break ; Val = Val * 10.0 + (zSrc[0] - '0') ; zSrc++ ; --Lim; | ||
1964 | } | ||
1965 | if( zSrc < zEnd && ( zSrc[0] == '.' || zSrc[0] == ',' ) ){ | ||
1966 | sxreal dec = 1.0; | ||
1967 | zSrc++; | ||
1968 | for(;;){ | ||
1969 | if(zSrc >= zEnd||!Lim||!SyisDigit(zSrc[0])) break ; Val = Val * 10.0 + (zSrc[0] - '0') ; dec *= 10.0; zSrc++ ;--Lim; | ||
1970 | if(zSrc >= zEnd||!Lim||!SyisDigit(zSrc[0])) break ; Val = Val * 10.0 + (zSrc[0] - '0') ; dec *= 10.0; zSrc++ ;--Lim; | ||
1971 | if(zSrc >= zEnd||!Lim||!SyisDigit(zSrc[0])) break ; Val = Val * 10.0 + (zSrc[0] - '0') ; dec *= 10.0; zSrc++ ;--Lim; | ||
1972 | if(zSrc >= zEnd||!Lim||!SyisDigit(zSrc[0])) break ; Val = Val * 10.0 + (zSrc[0] - '0') ; dec *= 10.0; zSrc++ ;--Lim; | ||
1973 | } | ||
1974 | Val /= dec; | ||
1975 | } | ||
1976 | if( neg == TRUE && Val != 0.0 ) { | ||
1977 | Val = -Val ; | ||
1978 | } | ||
1979 | if( Lim <= 0 ){ | ||
1980 | /* jump overflow digit */ | ||
1981 | while( zSrc < zEnd ){ | ||
1982 | if( zSrc[0] == 'e' || zSrc[0] == 'E' ){ | ||
1983 | break; | ||
1984 | } | ||
1985 | zSrc++; | ||
1986 | } | ||
1987 | } | ||
1988 | neg = FALSE; | ||
1989 | if( zSrc < zEnd && ( zSrc[0] == 'e' || zSrc[0] == 'E' ) ){ | ||
1990 | zSrc++; | ||
1991 | if( zSrc < zEnd && ( zSrc[0] == '-' || zSrc[0] == '+') ){ | ||
1992 | neg = zSrc[0] == '-' ? TRUE : FALSE ; | ||
1993 | zSrc++; | ||
1994 | } | ||
1995 | exp = 0; | ||
1996 | while( zSrc < zEnd && SyisDigit(zSrc[0]) && exp < SXDBL_MAX_EXP ){ | ||
1997 | exp = exp * 10 + (zSrc[0] - '0'); | ||
1998 | zSrc++; | ||
1999 | } | ||
2000 | if( neg ){ | ||
2001 | if( exp > SXDBL_MIN_EXP_PLUS ) exp = SXDBL_MIN_EXP_PLUS ; | ||
2002 | }else if ( exp > SXDBL_MAX_EXP ){ | ||
2003 | exp = SXDBL_MAX_EXP; | ||
2004 | } | ||
2005 | for( p = (sxreal *)aTab ; exp ; exp >>= 1 , p++ ){ | ||
2006 | if( exp & 01 ){ | ||
2007 | if( neg ){ | ||
2008 | Val /= *p ; | ||
2009 | }else{ | ||
2010 | Val *= *p; | ||
2011 | } | ||
2012 | } | ||
2013 | } | ||
2014 | } | ||
2015 | while( zSrc < zEnd && SyisSpace(zSrc[0]) ){ | ||
2016 | zSrc++; | ||
2017 | } | ||
2018 | if( zRest ){ | ||
2019 | *zRest = zSrc; | ||
2020 | } | ||
2021 | if( pOutVal ){ | ||
2022 | *(sxreal *)pOutVal = Val; | ||
2023 | } | ||
2024 | return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX; | ||
2025 | } | ||
2026 | /* SyRunTimeApi:sxlib.c */ | ||
2027 | JX9_PRIVATE sxu32 SyBinHash(const void *pSrc, sxu32 nLen) | ||
2028 | { | ||
2029 | register unsigned char *zIn = (unsigned char *)pSrc; | ||
2030 | unsigned char *zEnd; | ||
2031 | sxu32 nH = 5381; | ||
2032 | zEnd = &zIn[nLen]; | ||
2033 | for(;;){ | ||
2034 | if( zIn >= zEnd ){ break; } nH = nH * 33 + zIn[0] ; zIn++; | ||
2035 | if( zIn >= zEnd ){ break; } nH = nH * 33 + zIn[0] ; zIn++; | ||
2036 | if( zIn >= zEnd ){ break; } nH = nH * 33 + zIn[0] ; zIn++; | ||
2037 | if( zIn >= zEnd ){ break; } nH = nH * 33 + zIn[0] ; zIn++; | ||
2038 | } | ||
2039 | return nH; | ||
2040 | } | ||
2041 | #ifndef JX9_DISABLE_BUILTIN_FUNC | ||
2042 | JX9_PRIVATE sxi32 SyBase64Encode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) | ||
2043 | { | ||
2044 | static const unsigned char zBase64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
2045 | unsigned char *zIn = (unsigned char *)zSrc; | ||
2046 | unsigned char z64[4]; | ||
2047 | sxu32 i; | ||
2048 | sxi32 rc; | ||
2049 | #if defined(UNTRUST) | ||
2050 | if( SX_EMPTY_STR(zSrc) || xConsumer == 0){ | ||
2051 | return SXERR_EMPTY; | ||
2052 | } | ||
2053 | #endif | ||
2054 | for(i = 0; i + 2 < nLen; i += 3){ | ||
2055 | z64[0] = zBase64[(zIn[i] >> 2) & 0x3F]; | ||
2056 | z64[1] = zBase64[( ((zIn[i] & 0x03) << 4) | (zIn[i+1] >> 4)) & 0x3F]; | ||
2057 | z64[2] = zBase64[( ((zIn[i+1] & 0x0F) << 2) | (zIn[i + 2] >> 6) ) & 0x3F]; | ||
2058 | z64[3] = zBase64[ zIn[i + 2] & 0x3F]; | ||
2059 | |||
2060 | rc = xConsumer((const void *)z64, sizeof(z64), pUserData); | ||
2061 | if( rc != SXRET_OK ){return SXERR_ABORT;} | ||
2062 | |||
2063 | } | ||
2064 | if ( i+1 < nLen ){ | ||
2065 | z64[0] = zBase64[(zIn[i] >> 2) & 0x3F]; | ||
2066 | z64[1] = zBase64[( ((zIn[i] & 0x03) << 4) | (zIn[i+1] >> 4)) & 0x3F]; | ||
2067 | z64[2] = zBase64[(zIn[i+1] & 0x0F) << 2 ]; | ||
2068 | z64[3] = '='; | ||
2069 | |||
2070 | rc = xConsumer((const void *)z64, sizeof(z64), pUserData); | ||
2071 | if( rc != SXRET_OK ){return SXERR_ABORT;} | ||
2072 | |||
2073 | }else if( i < nLen ){ | ||
2074 | z64[0] = zBase64[(zIn[i] >> 2) & 0x3F]; | ||
2075 | z64[1] = zBase64[(zIn[i] & 0x03) << 4]; | ||
2076 | z64[2] = '='; | ||
2077 | z64[3] = '='; | ||
2078 | |||
2079 | rc = xConsumer((const void *)z64, sizeof(z64), pUserData); | ||
2080 | if( rc != SXRET_OK ){return SXERR_ABORT;} | ||
2081 | } | ||
2082 | |||
2083 | return SXRET_OK; | ||
2084 | } | ||
2085 | JX9_PRIVATE sxi32 SyBase64Decode(const char *zB64, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) | ||
2086 | { | ||
2087 | static const sxu32 aBase64Trans[] = { | ||
2088 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
2089 | 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, | ||
2090 | 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, | ||
2091 | 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, | ||
2092 | 0, 0, 0 | ||
2093 | }; | ||
2094 | sxu32 n, w, x, y, z; | ||
2095 | sxi32 rc; | ||
2096 | unsigned char zOut[10]; | ||
2097 | #if defined(UNTRUST) | ||
2098 | if( SX_EMPTY_STR(zB64) || xConsumer == 0 ){ | ||
2099 | return SXERR_EMPTY; | ||
2100 | } | ||
2101 | #endif | ||
2102 | while(nLen > 0 && zB64[nLen - 1] == '=' ){ | ||
2103 | nLen--; | ||
2104 | } | ||
2105 | for( n = 0 ; n+3<nLen ; n += 4){ | ||
2106 | w = aBase64Trans[zB64[n] & 0x7F]; | ||
2107 | x = aBase64Trans[zB64[n+1] & 0x7F]; | ||
2108 | y = aBase64Trans[zB64[n+2] & 0x7F]; | ||
2109 | z = aBase64Trans[zB64[n+3] & 0x7F]; | ||
2110 | zOut[0] = ((w<<2) & 0xFC) | ((x>>4) & 0x03); | ||
2111 | zOut[1] = ((x<<4) & 0xF0) | ((y>>2) & 0x0F); | ||
2112 | zOut[2] = ((y<<6) & 0xC0) | (z & 0x3F); | ||
2113 | |||
2114 | rc = xConsumer((const void *)zOut, sizeof(unsigned char)*3, pUserData); | ||
2115 | if( rc != SXRET_OK ){ return SXERR_ABORT;} | ||
2116 | } | ||
2117 | if( n+2 < nLen ){ | ||
2118 | w = aBase64Trans[zB64[n] & 0x7F]; | ||
2119 | x = aBase64Trans[zB64[n+1] & 0x7F]; | ||
2120 | y = aBase64Trans[zB64[n+2] & 0x7F]; | ||
2121 | |||
2122 | zOut[0] = ((w<<2) & 0xFC) | ((x>>4) & 0x03); | ||
2123 | zOut[1] = ((x<<4) & 0xF0) | ((y>>2) & 0x0F); | ||
2124 | |||
2125 | rc = xConsumer((const void *)zOut, sizeof(unsigned char)*2, pUserData); | ||
2126 | if( rc != SXRET_OK ){ return SXERR_ABORT;} | ||
2127 | }else if( n+1 < nLen ){ | ||
2128 | w = aBase64Trans[zB64[n] & 0x7F]; | ||
2129 | x = aBase64Trans[zB64[n+1] & 0x7F]; | ||
2130 | |||
2131 | zOut[0] = ((w<<2) & 0xFC) | ((x>>4) & 0x03); | ||
2132 | |||
2133 | rc = xConsumer((const void *)zOut, sizeof(unsigned char)*1, pUserData); | ||
2134 | if( rc != SXRET_OK ){ return SXERR_ABORT;} | ||
2135 | } | ||
2136 | return SXRET_OK; | ||
2137 | } | ||
2138 | #endif /* JX9_DISABLE_BUILTIN_FUNC */ | ||
2139 | #define INVALID_LEXER(LEX) ( LEX == 0 || LEX->xTokenizer == 0 ) | ||
2140 | JX9_PRIVATE sxi32 SyLexInit(SyLex *pLex, SySet *pSet, ProcTokenizer xTokenizer, void *pUserData) | ||
2141 | { | ||
2142 | SyStream *pStream; | ||
2143 | #if defined (UNTRUST) | ||
2144 | if ( pLex == 0 || xTokenizer == 0 ){ | ||
2145 | return SXERR_CORRUPT; | ||
2146 | } | ||
2147 | #endif | ||
2148 | pLex->pTokenSet = 0; | ||
2149 | /* Initialize lexer fields */ | ||
2150 | if( pSet ){ | ||
2151 | if ( SySetElemSize(pSet) != sizeof(SyToken) ){ | ||
2152 | return SXERR_INVALID; | ||
2153 | } | ||
2154 | pLex->pTokenSet = pSet; | ||
2155 | } | ||
2156 | pStream = &pLex->sStream; | ||
2157 | pLex->xTokenizer = xTokenizer; | ||
2158 | pLex->pUserData = pUserData; | ||
2159 | |||
2160 | pStream->nLine = 1; | ||
2161 | pStream->nIgn = 0; | ||
2162 | pStream->zText = pStream->zEnd = 0; | ||
2163 | pStream->pSet = pSet; | ||
2164 | return SXRET_OK; | ||
2165 | } | ||
2166 | JX9_PRIVATE sxi32 SyLexTokenizeInput(SyLex *pLex, const char *zInput, sxu32 nLen, void *pCtxData, ProcSort xSort, ProcCmp xCmp) | ||
2167 | { | ||
2168 | const unsigned char *zCur; | ||
2169 | SyStream *pStream; | ||
2170 | SyToken sToken; | ||
2171 | sxi32 rc; | ||
2172 | #if defined (UNTRUST) | ||
2173 | if ( INVALID_LEXER(pLex) || zInput == 0 ){ | ||
2174 | return SXERR_CORRUPT; | ||
2175 | } | ||
2176 | #endif | ||
2177 | pStream = &pLex->sStream; | ||
2178 | /* Point to the head of the input */ | ||
2179 | pStream->zText = pStream->zInput = (const unsigned char *)zInput; | ||
2180 | /* Point to the end of the input */ | ||
2181 | pStream->zEnd = &pStream->zInput[nLen]; | ||
2182 | for(;;){ | ||
2183 | if( pStream->zText >= pStream->zEnd ){ | ||
2184 | /* End of the input reached */ | ||
2185 | break; | ||
2186 | } | ||
2187 | zCur = pStream->zText; | ||
2188 | /* Call the tokenizer callback */ | ||
2189 | rc = pLex->xTokenizer(pStream, &sToken, pLex->pUserData, pCtxData); | ||
2190 | if( rc != SXRET_OK && rc != SXERR_CONTINUE ){ | ||
2191 | /* Tokenizer callback request an operation abort */ | ||
2192 | if( rc == SXERR_ABORT ){ | ||
2193 | return SXERR_ABORT; | ||
2194 | } | ||
2195 | break; | ||
2196 | } | ||
2197 | if( rc == SXERR_CONTINUE ){ | ||
2198 | /* Request to ignore this token */ | ||
2199 | pStream->nIgn++; | ||
2200 | }else if( pLex->pTokenSet ){ | ||
2201 | /* Put the token in the set */ | ||
2202 | rc = SySetPut(pLex->pTokenSet, (const void *)&sToken); | ||
2203 | if( rc != SXRET_OK ){ | ||
2204 | break; | ||
2205 | } | ||
2206 | } | ||
2207 | if( zCur >= pStream->zText ){ | ||
2208 | /* Automatic advance of the stream cursor */ | ||
2209 | pStream->zText = &zCur[1]; | ||
2210 | } | ||
2211 | } | ||
2212 | if( xSort && pLex->pTokenSet ){ | ||
2213 | SyToken *aToken = (SyToken *)SySetBasePtr(pLex->pTokenSet); | ||
2214 | /* Sort the extrated tokens */ | ||
2215 | if( xCmp == 0 ){ | ||
2216 | /* Use a default comparison function */ | ||
2217 | xCmp = SyMemcmp; | ||
2218 | } | ||
2219 | xSort(aToken, SySetUsed(pLex->pTokenSet), sizeof(SyToken), xCmp); | ||
2220 | } | ||
2221 | return SXRET_OK; | ||
2222 | } | ||
2223 | JX9_PRIVATE sxi32 SyLexRelease(SyLex *pLex) | ||
2224 | { | ||
2225 | sxi32 rc = SXRET_OK; | ||
2226 | #if defined (UNTRUST) | ||
2227 | if ( INVALID_LEXER(pLex) ){ | ||
2228 | return SXERR_CORRUPT; | ||
2229 | } | ||
2230 | #else | ||
2231 | SXUNUSED(pLex); /* Prevent compiler warning */ | ||
2232 | #endif | ||
2233 | return rc; | ||
2234 | } | ||
2235 | #ifndef JX9_DISABLE_BUILTIN_FUNC | ||
2236 | #define SAFE_HTTP(C) (SyisAlphaNum(c) || c == '_' || c == '-' || c == '$' || c == '.' ) | ||
2237 | JX9_PRIVATE sxi32 SyUriEncode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) | ||
2238 | { | ||
2239 | unsigned char *zIn = (unsigned char *)zSrc; | ||
2240 | unsigned char zHex[3] = { '%', 0, 0 }; | ||
2241 | unsigned char zOut[2]; | ||
2242 | unsigned char *zCur, *zEnd; | ||
2243 | sxi32 c; | ||
2244 | sxi32 rc; | ||
2245 | #ifdef UNTRUST | ||
2246 | if( SX_EMPTY_STR(zSrc) || xConsumer == 0 ){ | ||
2247 | return SXERR_EMPTY; | ||
2248 | } | ||
2249 | #endif | ||
2250 | rc = SXRET_OK; | ||
2251 | zEnd = &zIn[nLen]; zCur = zIn; | ||
2252 | for(;;){ | ||
2253 | if( zCur >= zEnd ){ | ||
2254 | if( zCur != zIn ){ | ||
2255 | rc = xConsumer(zIn, (sxu32)(zCur-zIn), pUserData); | ||
2256 | } | ||
2257 | break; | ||
2258 | } | ||
2259 | c = zCur[0]; | ||
2260 | if( SAFE_HTTP(c) ){ | ||
2261 | zCur++; continue; | ||
2262 | } | ||
2263 | if( zCur != zIn && SXRET_OK != (rc = xConsumer(zIn, (sxu32)(zCur-zIn), pUserData))){ | ||
2264 | break; | ||
2265 | } | ||
2266 | if( c == ' ' ){ | ||
2267 | zOut[0] = '+'; | ||
2268 | rc = xConsumer((const void *)zOut, sizeof(unsigned char), pUserData); | ||
2269 | }else{ | ||
2270 | zHex[1] = "0123456789ABCDEF"[(c >> 4) & 0x0F]; | ||
2271 | zHex[2] = "0123456789ABCDEF"[c & 0x0F]; | ||
2272 | rc = xConsumer(zHex, sizeof(zHex), pUserData); | ||
2273 | } | ||
2274 | if( SXRET_OK != rc ){ | ||
2275 | break; | ||
2276 | } | ||
2277 | zIn = &zCur[1]; zCur = zIn ; | ||
2278 | } | ||
2279 | return rc == SXRET_OK ? SXRET_OK : SXERR_ABORT; | ||
2280 | } | ||
2281 | #endif /* JX9_DISABLE_BUILTIN_FUNC */ | ||
2282 | static sxi32 SyAsciiToHex(sxi32 c) | ||
2283 | { | ||
2284 | if( c >= 'a' && c <= 'f' ){ | ||
2285 | c += 10 - 'a'; | ||
2286 | return c; | ||
2287 | } | ||
2288 | if( c >= '0' && c <= '9' ){ | ||
2289 | c -= '0'; | ||
2290 | return c; | ||
2291 | } | ||
2292 | if( c >= 'A' && c <= 'F') { | ||
2293 | c += 10 - 'A'; | ||
2294 | return c; | ||
2295 | } | ||
2296 | return 0; | ||
2297 | } | ||
2298 | JX9_PRIVATE sxi32 SyUriDecode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData, int bUTF8) | ||
2299 | { | ||
2300 | static const sxu8 Utf8Trans[] = { | ||
2301 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | ||
2302 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | ||
2303 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, | ||
2304 | 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, | ||
2305 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | ||
2306 | 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | ||
2307 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, | ||
2308 | 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00 | ||
2309 | }; | ||
2310 | const char *zIn = zSrc; | ||
2311 | const char *zEnd; | ||
2312 | const char *zCur; | ||
2313 | sxu8 *zOutPtr; | ||
2314 | sxu8 zOut[10]; | ||
2315 | sxi32 c, d; | ||
2316 | sxi32 rc; | ||
2317 | #if defined(UNTRUST) | ||
2318 | if( SX_EMPTY_STR(zSrc) || xConsumer == 0 ){ | ||
2319 | return SXERR_EMPTY; | ||
2320 | } | ||
2321 | #endif | ||
2322 | rc = SXRET_OK; | ||
2323 | zEnd = &zSrc[nLen]; | ||
2324 | zCur = zIn; | ||
2325 | for(;;){ | ||
2326 | while(zCur < zEnd && zCur[0] != '%' && zCur[0] != '+' ){ | ||
2327 | zCur++; | ||
2328 | } | ||
2329 | if( zCur != zIn ){ | ||
2330 | /* Consume input */ | ||
2331 | rc = xConsumer(zIn, (unsigned int)(zCur-zIn), pUserData); | ||
2332 | if( rc != SXRET_OK ){ | ||
2333 | /* User consumer routine request an operation abort */ | ||
2334 | break; | ||
2335 | } | ||
2336 | } | ||
2337 | if( zCur >= zEnd ){ | ||
2338 | rc = SXRET_OK; | ||
2339 | break; | ||
2340 | } | ||
2341 | /* Decode unsafe HTTP characters */ | ||
2342 | zOutPtr = zOut; | ||
2343 | if( zCur[0] == '+' ){ | ||
2344 | *zOutPtr++ = ' '; | ||
2345 | zCur++; | ||
2346 | }else{ | ||
2347 | if( &zCur[2] >= zEnd ){ | ||
2348 | rc = SXERR_OVERFLOW; | ||
2349 | break; | ||
2350 | } | ||
2351 | c = (SyAsciiToHex(zCur[1]) <<4) | SyAsciiToHex(zCur[2]); | ||
2352 | zCur += 3; | ||
2353 | if( c < 0x000C0 ){ | ||
2354 | *zOutPtr++ = (sxu8)c; | ||
2355 | }else{ | ||
2356 | c = Utf8Trans[c-0xC0]; | ||
2357 | while( zCur[0] == '%' ){ | ||
2358 | d = (SyAsciiToHex(zCur[1]) <<4) | SyAsciiToHex(zCur[2]); | ||
2359 | if( (d&0xC0) != 0x80 ){ | ||
2360 | break; | ||
2361 | } | ||
2362 | c = (c<<6) + (0x3f & d); | ||
2363 | zCur += 3; | ||
2364 | } | ||
2365 | if( bUTF8 == FALSE ){ | ||
2366 | *zOutPtr++ = (sxu8)c; | ||
2367 | }else{ | ||
2368 | SX_WRITE_UTF8(zOutPtr, c); | ||
2369 | } | ||
2370 | } | ||
2371 | |||
2372 | } | ||
2373 | /* Consume the decoded characters */ | ||
2374 | rc = xConsumer((const void *)zOut, (unsigned int)(zOutPtr-zOut), pUserData); | ||
2375 | if( rc != SXRET_OK ){ | ||
2376 | break; | ||
2377 | } | ||
2378 | /* Synchronize pointers */ | ||
2379 | zIn = zCur; | ||
2380 | } | ||
2381 | return rc; | ||
2382 | } | ||
2383 | #ifndef JX9_DISABLE_BUILTIN_FUNC | ||
2384 | static const char *zEngDay[] = { | ||
2385 | "Sunday", "Monday", "Tuesday", "Wednesday", | ||
2386 | "Thursday", "Friday", "Saturday" | ||
2387 | }; | ||
2388 | static const char *zEngMonth[] = { | ||
2389 | "January", "February", "March", "April", | ||
2390 | "May", "June", "July", "August", | ||
2391 | "September", "October", "November", "December" | ||
2392 | }; | ||
2393 | static const char * GetDay(sxi32 i) | ||
2394 | { | ||
2395 | return zEngDay[ i % 7 ]; | ||
2396 | } | ||
2397 | static const char * GetMonth(sxi32 i) | ||
2398 | { | ||
2399 | return zEngMonth[ i % 12 ]; | ||
2400 | } | ||
2401 | JX9_PRIVATE const char * SyTimeGetDay(sxi32 iDay) | ||
2402 | { | ||
2403 | return GetDay(iDay); | ||
2404 | } | ||
2405 | JX9_PRIVATE const char * SyTimeGetMonth(sxi32 iMonth) | ||
2406 | { | ||
2407 | return GetMonth(iMonth); | ||
2408 | } | ||
2409 | #endif /* JX9_DISABLE_BUILTIN_FUNC */ | ||
2410 | /* SyRunTimeApi: sxfmt.c */ | ||
2411 | #define SXFMT_BUFSIZ 1024 /* Conversion buffer size */ | ||
2412 | /* | ||
2413 | ** Conversion types fall into various categories as defined by the | ||
2414 | ** following enumeration. | ||
2415 | */ | ||
2416 | #define SXFMT_RADIX 1 /* Integer types.%d, %x, %o, and so forth */ | ||
2417 | #define SXFMT_FLOAT 2 /* Floating point.%f */ | ||
2418 | #define SXFMT_EXP 3 /* Exponentional notation.%e and %E */ | ||
2419 | #define SXFMT_GENERIC 4 /* Floating or exponential, depending on exponent.%g */ | ||
2420 | #define SXFMT_SIZE 5 /* Total number of characters processed so far.%n */ | ||
2421 | #define SXFMT_STRING 6 /* Strings.%s */ | ||
2422 | #define SXFMT_PERCENT 7 /* Percent symbol.%% */ | ||
2423 | #define SXFMT_CHARX 8 /* Characters.%c */ | ||
2424 | #define SXFMT_ERROR 9 /* Used to indicate no such conversion type */ | ||
2425 | /* Extension by Symisc Systems */ | ||
2426 | #define SXFMT_RAWSTR 13 /* %z Pointer to raw string (SyString *) */ | ||
2427 | #define SXFMT_UNUSED 15 | ||
2428 | /* | ||
2429 | ** Allowed values for SyFmtInfo.flags | ||
2430 | */ | ||
2431 | #define SXFLAG_SIGNED 0x01 | ||
2432 | #define SXFLAG_UNSIGNED 0x02 | ||
2433 | /* Allowed values for SyFmtConsumer.nType */ | ||
2434 | #define SXFMT_CONS_PROC 1 /* Consumer is a procedure */ | ||
2435 | #define SXFMT_CONS_STR 2 /* Consumer is a managed string */ | ||
2436 | #define SXFMT_CONS_FILE 5 /* Consumer is an open File */ | ||
2437 | #define SXFMT_CONS_BLOB 6 /* Consumer is a BLOB */ | ||
2438 | /* | ||
2439 | ** Each builtin conversion character (ex: the 'd' in "%d") is described | ||
2440 | ** by an instance of the following structure | ||
2441 | */ | ||
2442 | typedef struct SyFmtInfo SyFmtInfo; | ||
2443 | struct SyFmtInfo | ||
2444 | { | ||
2445 | char fmttype; /* The format field code letter [i.e: 'd', 's', 'x'] */ | ||
2446 | sxu8 base; /* The base for radix conversion */ | ||
2447 | int flags; /* One or more of SXFLAG_ constants below */ | ||
2448 | sxu8 type; /* Conversion paradigm */ | ||
2449 | char *charset; /* The character set for conversion */ | ||
2450 | char *prefix; /* Prefix on non-zero values in alt format */ | ||
2451 | }; | ||
2452 | typedef struct SyFmtConsumer SyFmtConsumer; | ||
2453 | struct SyFmtConsumer | ||
2454 | { | ||
2455 | sxu32 nLen; /* Total output length */ | ||
2456 | sxi32 nType; /* Type of the consumer see below */ | ||
2457 | sxi32 rc; /* Consumer return value;Abort processing if rc != SXRET_OK */ | ||
2458 | union{ | ||
2459 | struct{ | ||
2460 | ProcConsumer xUserConsumer; | ||
2461 | void *pUserData; | ||
2462 | }sFunc; | ||
2463 | SyBlob *pBlob; | ||
2464 | }uConsumer; | ||
2465 | }; | ||
2466 | #ifndef SX_OMIT_FLOATINGPOINT | ||
2467 | static int getdigit(sxlongreal *val, int *cnt) | ||
2468 | { | ||
2469 | sxlongreal d; | ||
2470 | int digit; | ||
2471 | |||
2472 | if( (*cnt)++ >= 16 ){ | ||
2473 | return '0'; | ||
2474 | } | ||
2475 | digit = (int)*val; | ||
2476 | d = digit; | ||
2477 | *val = (*val - d)*10.0; | ||
2478 | return digit + '0' ; | ||
2479 | } | ||
2480 | #endif /* SX_OMIT_FLOATINGPOINT */ | ||
2481 | /* | ||
2482 | * The following routine was taken from the SQLITE2 source tree and was | ||
2483 | * extended by Symisc Systems to fit its need. | ||
2484 | * Status: Public Domain | ||
2485 | */ | ||
2486 | static sxi32 InternFormat(ProcConsumer xConsumer, void *pUserData, const char *zFormat, va_list ap) | ||
2487 | { | ||
2488 | /* | ||
2489 | * The following table is searched linearly, so it is good to put the most frequently | ||
2490 | * used conversion types first. | ||
2491 | */ | ||
2492 | static const SyFmtInfo aFmt[] = { | ||
2493 | { 'd', 10, SXFLAG_SIGNED, SXFMT_RADIX, "0123456789", 0 }, | ||
2494 | { 's', 0, 0, SXFMT_STRING, 0, 0 }, | ||
2495 | { 'c', 0, 0, SXFMT_CHARX, 0, 0 }, | ||
2496 | { 'x', 16, 0, SXFMT_RADIX, "0123456789abcdef", "x0" }, | ||
2497 | { 'X', 16, 0, SXFMT_RADIX, "0123456789ABCDEF", "X0" }, | ||
2498 | /* -- Extensions by Symisc Systems -- */ | ||
2499 | { 'z', 0, 0, SXFMT_RAWSTR, 0, 0 }, /* Pointer to a raw string (SyString *) */ | ||
2500 | { 'B', 2, 0, SXFMT_RADIX, "01", "b0"}, | ||
2501 | /* -- End of Extensions -- */ | ||
2502 | { 'o', 8, 0, SXFMT_RADIX, "01234567", "0" }, | ||
2503 | { 'u', 10, 0, SXFMT_RADIX, "0123456789", 0 }, | ||
2504 | #ifndef SX_OMIT_FLOATINGPOINT | ||
2505 | { 'f', 0, SXFLAG_SIGNED, SXFMT_FLOAT, 0, 0 }, | ||
2506 | { 'e', 0, SXFLAG_SIGNED, SXFMT_EXP, "e", 0 }, | ||
2507 | { 'E', 0, SXFLAG_SIGNED, SXFMT_EXP, "E", 0 }, | ||
2508 | { 'g', 0, SXFLAG_SIGNED, SXFMT_GENERIC, "e", 0 }, | ||
2509 | { 'G', 0, SXFLAG_SIGNED, SXFMT_GENERIC, "E", 0 }, | ||
2510 | #endif | ||
2511 | { 'i', 10, SXFLAG_SIGNED, SXFMT_RADIX, "0123456789", 0 }, | ||
2512 | { 'n', 0, 0, SXFMT_SIZE, 0, 0 }, | ||
2513 | { '%', 0, 0, SXFMT_PERCENT, 0, 0 }, | ||
2514 | { 'p', 10, 0, SXFMT_RADIX, "0123456789", 0 } | ||
2515 | }; | ||
2516 | int c; /* Next character in the format string */ | ||
2517 | char *bufpt; /* Pointer to the conversion buffer */ | ||
2518 | int precision; /* Precision of the current field */ | ||
2519 | int length; /* Length of the field */ | ||
2520 | int idx; /* A general purpose loop counter */ | ||
2521 | int width; /* Width of the current field */ | ||
2522 | sxu8 flag_leftjustify; /* True if "-" flag is present */ | ||
2523 | sxu8 flag_plussign; /* True if "+" flag is present */ | ||
2524 | sxu8 flag_blanksign; /* True if " " flag is present */ | ||
2525 | sxu8 flag_alternateform; /* True if "#" flag is present */ | ||
2526 | sxu8 flag_zeropad; /* True if field width constant starts with zero */ | ||
2527 | sxu8 flag_long; /* True if "l" flag is present */ | ||
2528 | sxi64 longvalue; /* Value for integer types */ | ||
2529 | const SyFmtInfo *infop; /* Pointer to the appropriate info structure */ | ||
2530 | char buf[SXFMT_BUFSIZ]; /* Conversion buffer */ | ||
2531 | char prefix; /* Prefix character."+" or "-" or " " or '\0'.*/ | ||
2532 | sxu8 errorflag = 0; /* True if an error is encountered */ | ||
2533 | sxu8 xtype; /* Conversion paradigm */ | ||
2534 | char *zExtra; | ||
2535 | static char spaces[] = " "; | ||
2536 | #define etSPACESIZE ((int)sizeof(spaces)-1) | ||
2537 | #ifndef SX_OMIT_FLOATINGPOINT | ||
2538 | sxlongreal realvalue; /* Value for real types */ | ||
2539 | int exp; /* exponent of real numbers */ | ||
2540 | double rounder; /* Used for rounding floating point values */ | ||
2541 | sxu8 flag_dp; /* True if decimal point should be shown */ | ||
2542 | sxu8 flag_rtz; /* True if trailing zeros should be removed */ | ||
2543 | sxu8 flag_exp; /* True to force display of the exponent */ | ||
2544 | int nsd; /* Number of significant digits returned */ | ||
2545 | #endif | ||
2546 | int rc; | ||
2547 | |||
2548 | length = 0; | ||
2549 | bufpt = 0; | ||
2550 | for(; (c=(*zFormat))!=0; ++zFormat){ | ||
2551 | if( c!='%' ){ | ||
2552 | unsigned int amt; | ||
2553 | bufpt = (char *)zFormat; | ||
2554 | amt = 1; | ||
2555 | while( (c=(*++zFormat))!='%' && c!=0 ) amt++; | ||
2556 | rc = xConsumer((const void *)bufpt, amt, pUserData); | ||
2557 | if( rc != SXRET_OK ){ | ||
2558 | return SXERR_ABORT; /* Consumer routine request an operation abort */ | ||
2559 | } | ||
2560 | if( c==0 ){ | ||
2561 | return errorflag > 0 ? SXERR_FORMAT : SXRET_OK; | ||
2562 | } | ||
2563 | } | ||
2564 | if( (c=(*++zFormat))==0 ){ | ||
2565 | errorflag = 1; | ||
2566 | rc = xConsumer("%", sizeof("%")-1, pUserData); | ||
2567 | if( rc != SXRET_OK ){ | ||
2568 | return SXERR_ABORT; /* Consumer routine request an operation abort */ | ||
2569 | } | ||
2570 | return errorflag > 0 ? SXERR_FORMAT : SXRET_OK; | ||
2571 | } | ||
2572 | /* Find out what flags are present */ | ||
2573 | flag_leftjustify = flag_plussign = flag_blanksign = | ||
2574 | flag_alternateform = flag_zeropad = 0; | ||
2575 | do{ | ||
2576 | switch( c ){ | ||
2577 | case '-': flag_leftjustify = 1; c = 0; break; | ||
2578 | case '+': flag_plussign = 1; c = 0; break; | ||
2579 | case ' ': flag_blanksign = 1; c = 0; break; | ||
2580 | case '#': flag_alternateform = 1; c = 0; break; | ||
2581 | case '0': flag_zeropad = 1; c = 0; break; | ||
2582 | default: break; | ||
2583 | } | ||
2584 | }while( c==0 && (c=(*++zFormat))!=0 ); | ||
2585 | /* Get the field width */ | ||
2586 | width = 0; | ||
2587 | if( c=='*' ){ | ||
2588 | width = va_arg(ap, int); | ||
2589 | if( width<0 ){ | ||
2590 | flag_leftjustify = 1; | ||
2591 | width = -width; | ||
2592 | } | ||
2593 | c = *++zFormat; | ||
2594 | }else{ | ||
2595 | while( c>='0' && c<='9' ){ | ||
2596 | width = width*10 + c - '0'; | ||
2597 | c = *++zFormat; | ||
2598 | } | ||
2599 | } | ||
2600 | if( width > SXFMT_BUFSIZ-10 ){ | ||
2601 | width = SXFMT_BUFSIZ-10; | ||
2602 | } | ||
2603 | /* Get the precision */ | ||
2604 | precision = -1; | ||
2605 | if( c=='.' ){ | ||
2606 | precision = 0; | ||
2607 | c = *++zFormat; | ||
2608 | if( c=='*' ){ | ||
2609 | precision = va_arg(ap, int); | ||
2610 | if( precision<0 ) precision = -precision; | ||
2611 | c = *++zFormat; | ||
2612 | }else{ | ||
2613 | while( c>='0' && c<='9' ){ | ||
2614 | precision = precision*10 + c - '0'; | ||
2615 | c = *++zFormat; | ||
2616 | } | ||
2617 | } | ||
2618 | } | ||
2619 | /* Get the conversion type modifier */ | ||
2620 | flag_long = 0; | ||
2621 | if( c=='l' || c == 'q' /* BSD quad (expect a 64-bit integer) */ ){ | ||
2622 | flag_long = (c == 'q') ? 2 : 1; | ||
2623 | c = *++zFormat; | ||
2624 | if( c == 'l' ){ | ||
2625 | /* Standard printf emulation 'lld' (expect a 64bit integer) */ | ||
2626 | flag_long = 2; | ||
2627 | } | ||
2628 | } | ||
2629 | /* Fetch the info entry for the field */ | ||
2630 | infop = 0; | ||
2631 | xtype = SXFMT_ERROR; | ||
2632 | for(idx=0; idx< (int)SX_ARRAYSIZE(aFmt); idx++){ | ||
2633 | if( c==aFmt[idx].fmttype ){ | ||
2634 | infop = &aFmt[idx]; | ||
2635 | xtype = infop->type; | ||
2636 | break; | ||
2637 | } | ||
2638 | } | ||
2639 | zExtra = 0; | ||
2640 | |||
2641 | /* | ||
2642 | ** At this point, variables are initialized as follows: | ||
2643 | ** | ||
2644 | ** flag_alternateform TRUE if a '#' is present. | ||
2645 | ** flag_plussign TRUE if a '+' is present. | ||
2646 | ** flag_leftjustify TRUE if a '-' is present or if the | ||
2647 | ** field width was negative. | ||
2648 | ** flag_zeropad TRUE if the width began with 0. | ||
2649 | ** flag_long TRUE if the letter 'l' (ell) or 'q'(BSD quad) prefixed | ||
2650 | ** the conversion character. | ||
2651 | ** flag_blanksign TRUE if a ' ' is present. | ||
2652 | ** width The specified field width.This is | ||
2653 | ** always non-negative.Zero is the default. | ||
2654 | ** precision The specified precision.The default | ||
2655 | ** is -1. | ||
2656 | ** xtype The object of the conversion. | ||
2657 | ** infop Pointer to the appropriate info struct. | ||
2658 | */ | ||
2659 | switch( xtype ){ | ||
2660 | case SXFMT_RADIX: | ||
2661 | if( flag_long > 0 ){ | ||
2662 | if( flag_long > 1 ){ | ||
2663 | /* BSD quad: expect a 64-bit integer */ | ||
2664 | longvalue = va_arg(ap, sxi64); | ||
2665 | }else{ | ||
2666 | longvalue = va_arg(ap, sxlong); | ||
2667 | } | ||
2668 | }else{ | ||
2669 | if( infop->flags & SXFLAG_SIGNED ){ | ||
2670 | longvalue = va_arg(ap, sxi32); | ||
2671 | }else{ | ||
2672 | longvalue = va_arg(ap, sxu32); | ||
2673 | } | ||
2674 | } | ||
2675 | /* Limit the precision to prevent overflowing buf[] during conversion */ | ||
2676 | if( precision>SXFMT_BUFSIZ-40 ) precision = SXFMT_BUFSIZ-40; | ||
2677 | #if 1 | ||
2678 | /* For the format %#x, the value zero is printed "0" not "0x0". | ||
2679 | ** I think this is stupid.*/ | ||
2680 | if( longvalue==0 ) flag_alternateform = 0; | ||
2681 | #else | ||
2682 | /* More sensible: turn off the prefix for octal (to prevent "00"), | ||
2683 | ** but leave the prefix for hex.*/ | ||
2684 | if( longvalue==0 && infop->base==8 ) flag_alternateform = 0; | ||
2685 | #endif | ||
2686 | if( infop->flags & SXFLAG_SIGNED ){ | ||
2687 | if( longvalue<0 ){ | ||
2688 | longvalue = -longvalue; | ||
2689 | /* Ticket 1433-003 */ | ||
2690 | if( longvalue < 0 ){ | ||
2691 | /* Overflow */ | ||
2692 | longvalue= 0x7FFFFFFFFFFFFFFF; | ||
2693 | } | ||
2694 | prefix = '-'; | ||
2695 | }else if( flag_plussign ) prefix = '+'; | ||
2696 | else if( flag_blanksign ) prefix = ' '; | ||
2697 | else prefix = 0; | ||
2698 | }else{ | ||
2699 | if( longvalue<0 ){ | ||
2700 | longvalue = -longvalue; | ||
2701 | /* Ticket 1433-003 */ | ||
2702 | if( longvalue < 0 ){ | ||
2703 | /* Overflow */ | ||
2704 | longvalue= 0x7FFFFFFFFFFFFFFF; | ||
2705 | } | ||
2706 | } | ||
2707 | prefix = 0; | ||
2708 | } | ||
2709 | if( flag_zeropad && precision<width-(prefix!=0) ){ | ||
2710 | precision = width-(prefix!=0); | ||
2711 | } | ||
2712 | bufpt = &buf[SXFMT_BUFSIZ-1]; | ||
2713 | { | ||
2714 | register char *cset; /* Use registers for speed */ | ||
2715 | register int base; | ||
2716 | cset = infop->charset; | ||
2717 | base = infop->base; | ||
2718 | do{ /* Convert to ascii */ | ||
2719 | *(--bufpt) = cset[longvalue%base]; | ||
2720 | longvalue = longvalue/base; | ||
2721 | }while( longvalue>0 ); | ||
2722 | } | ||
2723 | length = &buf[SXFMT_BUFSIZ-1]-bufpt; | ||
2724 | for(idx=precision-length; idx>0; idx--){ | ||
2725 | *(--bufpt) = '0'; /* Zero pad */ | ||
2726 | } | ||
2727 | if( prefix ) *(--bufpt) = prefix; /* Add sign */ | ||
2728 | if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ | ||
2729 | char *pre, x; | ||
2730 | pre = infop->prefix; | ||
2731 | if( *bufpt!=pre[0] ){ | ||
2732 | for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x; | ||
2733 | } | ||
2734 | } | ||
2735 | length = &buf[SXFMT_BUFSIZ-1]-bufpt; | ||
2736 | break; | ||
2737 | case SXFMT_FLOAT: | ||
2738 | case SXFMT_EXP: | ||
2739 | case SXFMT_GENERIC: | ||
2740 | #ifndef SX_OMIT_FLOATINGPOINT | ||
2741 | realvalue = va_arg(ap, double); | ||
2742 | if( precision<0 ) precision = 6; /* Set default precision */ | ||
2743 | if( precision>SXFMT_BUFSIZ-40) precision = SXFMT_BUFSIZ-40; | ||
2744 | if( realvalue<0.0 ){ | ||
2745 | realvalue = -realvalue; | ||
2746 | prefix = '-'; | ||
2747 | }else{ | ||
2748 | if( flag_plussign ) prefix = '+'; | ||
2749 | else if( flag_blanksign ) prefix = ' '; | ||
2750 | else prefix = 0; | ||
2751 | } | ||
2752 | if( infop->type==SXFMT_GENERIC && precision>0 ) precision--; | ||
2753 | rounder = 0.0; | ||
2754 | #if 0 | ||
2755 | /* Rounding works like BSD when the constant 0.4999 is used.Wierd! */ | ||
2756 | for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1); | ||
2757 | #else | ||
2758 | /* It makes more sense to use 0.5 */ | ||
2759 | for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1); | ||
2760 | #endif | ||
2761 | if( infop->type==SXFMT_FLOAT ) realvalue += rounder; | ||
2762 | /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ | ||
2763 | exp = 0; | ||
2764 | if( realvalue>0.0 ){ | ||
2765 | while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; } | ||
2766 | while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; } | ||
2767 | while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; } | ||
2768 | while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; } | ||
2769 | if( exp>350 || exp<-350 ){ | ||
2770 | bufpt = "NaN"; | ||
2771 | length = 3; | ||
2772 | break; | ||
2773 | } | ||
2774 | } | ||
2775 | bufpt = buf; | ||
2776 | /* | ||
2777 | ** If the field type is etGENERIC, then convert to either etEXP | ||
2778 | ** or etFLOAT, as appropriate. | ||
2779 | */ | ||
2780 | flag_exp = xtype==SXFMT_EXP; | ||
2781 | if( xtype!=SXFMT_FLOAT ){ | ||
2782 | realvalue += rounder; | ||
2783 | if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } | ||
2784 | } | ||
2785 | if( xtype==SXFMT_GENERIC ){ | ||
2786 | flag_rtz = !flag_alternateform; | ||
2787 | if( exp<-4 || exp>precision ){ | ||
2788 | xtype = SXFMT_EXP; | ||
2789 | }else{ | ||
2790 | precision = precision - exp; | ||
2791 | xtype = SXFMT_FLOAT; | ||
2792 | } | ||
2793 | }else{ | ||
2794 | flag_rtz = 0; | ||
2795 | } | ||
2796 | /* | ||
2797 | ** The "exp+precision" test causes output to be of type etEXP if | ||
2798 | ** the precision is too large to fit in buf[]. | ||
2799 | */ | ||
2800 | nsd = 0; | ||
2801 | if( xtype==SXFMT_FLOAT && exp+precision<SXFMT_BUFSIZ-30 ){ | ||
2802 | flag_dp = (precision>0 || flag_alternateform); | ||
2803 | if( prefix ) *(bufpt++) = prefix; /* Sign */ | ||
2804 | if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */ | ||
2805 | else for(; exp>=0; exp--) *(bufpt++) = (char)getdigit(&realvalue, &nsd); | ||
2806 | if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */ | ||
2807 | for(exp++; exp<0 && precision>0; precision--, exp++){ | ||
2808 | *(bufpt++) = '0'; | ||
2809 | } | ||
2810 | while( (precision--)>0 ) *(bufpt++) = (char)getdigit(&realvalue, &nsd); | ||
2811 | *(bufpt--) = 0; /* Null terminate */ | ||
2812 | if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */ | ||
2813 | while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; | ||
2814 | if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; | ||
2815 | } | ||
2816 | bufpt++; /* point to next free slot */ | ||
2817 | }else{ /* etEXP or etGENERIC */ | ||
2818 | flag_dp = (precision>0 || flag_alternateform); | ||
2819 | if( prefix ) *(bufpt++) = prefix; /* Sign */ | ||
2820 | *(bufpt++) = (char)getdigit(&realvalue, &nsd); /* First digit */ | ||
2821 | if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */ | ||
2822 | while( (precision--)>0 ) *(bufpt++) = (char)getdigit(&realvalue, &nsd); | ||
2823 | bufpt--; /* point to last digit */ | ||
2824 | if( flag_rtz && flag_dp ){ /* Remove tail zeros */ | ||
2825 | while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0; | ||
2826 | if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0; | ||
2827 | } | ||
2828 | bufpt++; /* point to next free slot */ | ||
2829 | if( exp || flag_exp ){ | ||
2830 | *(bufpt++) = infop->charset[0]; | ||
2831 | if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */ | ||
2832 | else { *(bufpt++) = '+'; } | ||
2833 | if( exp>=100 ){ | ||
2834 | *(bufpt++) = (char)((exp/100)+'0'); /* 100's digit */ | ||
2835 | exp %= 100; | ||
2836 | } | ||
2837 | *(bufpt++) = (char)(exp/10+'0'); /* 10's digit */ | ||
2838 | *(bufpt++) = (char)(exp%10+'0'); /* 1's digit */ | ||
2839 | } | ||
2840 | } | ||
2841 | /* The converted number is in buf[] and zero terminated.Output it. | ||
2842 | ** Note that the number is in the usual order, not reversed as with | ||
2843 | ** integer conversions.*/ | ||
2844 | length = bufpt-buf; | ||
2845 | bufpt = buf; | ||
2846 | |||
2847 | /* Special case: Add leading zeros if the flag_zeropad flag is | ||
2848 | ** set and we are not left justified */ | ||
2849 | if( flag_zeropad && !flag_leftjustify && length < width){ | ||
2850 | int i; | ||
2851 | int nPad = width - length; | ||
2852 | for(i=width; i>=nPad; i--){ | ||
2853 | bufpt[i] = bufpt[i-nPad]; | ||
2854 | } | ||
2855 | i = prefix!=0; | ||
2856 | while( nPad-- ) bufpt[i++] = '0'; | ||
2857 | length = width; | ||
2858 | } | ||
2859 | #else | ||
2860 | bufpt = " "; | ||
2861 | length = (int)sizeof(" ") - 1; | ||
2862 | #endif /* SX_OMIT_FLOATINGPOINT */ | ||
2863 | break; | ||
2864 | case SXFMT_SIZE:{ | ||
2865 | int *pSize = va_arg(ap, int *); | ||
2866 | *pSize = ((SyFmtConsumer *)pUserData)->nLen; | ||
2867 | length = width = 0; | ||
2868 | } | ||
2869 | break; | ||
2870 | case SXFMT_PERCENT: | ||
2871 | buf[0] = '%'; | ||
2872 | bufpt = buf; | ||
2873 | length = 1; | ||
2874 | break; | ||
2875 | case SXFMT_CHARX: | ||
2876 | c = va_arg(ap, int); | ||
2877 | buf[0] = (char)c; | ||
2878 | /* Limit the precision to prevent overflowing buf[] during conversion */ | ||
2879 | if( precision>SXFMT_BUFSIZ-40 ) precision = SXFMT_BUFSIZ-40; | ||
2880 | if( precision>=0 ){ | ||
2881 | for(idx=1; idx<precision; idx++) buf[idx] = (char)c; | ||
2882 | length = precision; | ||
2883 | }else{ | ||
2884 | length =1; | ||
2885 | } | ||
2886 | bufpt = buf; | ||
2887 | break; | ||
2888 | case SXFMT_STRING: | ||
2889 | bufpt = va_arg(ap, char*); | ||
2890 | if( bufpt==0 ){ | ||
2891 | bufpt = " "; | ||
2892 | length = (int)sizeof(" ")-1; | ||
2893 | break; | ||
2894 | } | ||
2895 | length = precision; | ||
2896 | if( precision < 0 ){ | ||
2897 | /* Symisc extension */ | ||
2898 | length = (int)SyStrlen(bufpt); | ||
2899 | } | ||
2900 | if( precision>=0 && precision<length ) length = precision; | ||
2901 | break; | ||
2902 | case SXFMT_RAWSTR:{ | ||
2903 | /* Symisc extension */ | ||
2904 | SyString *pStr = va_arg(ap, SyString *); | ||
2905 | if( pStr == 0 || pStr->zString == 0 ){ | ||
2906 | bufpt = " "; | ||
2907 | length = (int)sizeof(char); | ||
2908 | break; | ||
2909 | } | ||
2910 | bufpt = (char *)pStr->zString; | ||
2911 | length = (int)pStr->nByte; | ||
2912 | break; | ||
2913 | } | ||
2914 | case SXFMT_ERROR: | ||
2915 | buf[0] = '?'; | ||
2916 | bufpt = buf; | ||
2917 | length = (int)sizeof(char); | ||
2918 | if( c==0 ) zFormat--; | ||
2919 | break; | ||
2920 | }/* End switch over the format type */ | ||
2921 | /* | ||
2922 | ** The text of the conversion is pointed to by "bufpt" and is | ||
2923 | ** "length" characters long.The field width is "width".Do | ||
2924 | ** the output. | ||
2925 | */ | ||
2926 | if( !flag_leftjustify ){ | ||
2927 | register int nspace; | ||
2928 | nspace = width-length; | ||
2929 | if( nspace>0 ){ | ||
2930 | while( nspace>=etSPACESIZE ){ | ||
2931 | rc = xConsumer(spaces, etSPACESIZE, pUserData); | ||
2932 | if( rc != SXRET_OK ){ | ||
2933 | return SXERR_ABORT; /* Consumer routine request an operation abort */ | ||
2934 | } | ||
2935 | nspace -= etSPACESIZE; | ||
2936 | } | ||
2937 | if( nspace>0 ){ | ||
2938 | rc = xConsumer(spaces, (unsigned int)nspace, pUserData); | ||
2939 | if( rc != SXRET_OK ){ | ||
2940 | return SXERR_ABORT; /* Consumer routine request an operation abort */ | ||
2941 | } | ||
2942 | } | ||
2943 | } | ||
2944 | } | ||
2945 | if( length>0 ){ | ||
2946 | rc = xConsumer(bufpt, (unsigned int)length, pUserData); | ||
2947 | if( rc != SXRET_OK ){ | ||
2948 | return SXERR_ABORT; /* Consumer routine request an operation abort */ | ||
2949 | } | ||
2950 | } | ||
2951 | if( flag_leftjustify ){ | ||
2952 | register int nspace; | ||
2953 | nspace = width-length; | ||
2954 | if( nspace>0 ){ | ||
2955 | while( nspace>=etSPACESIZE ){ | ||
2956 | rc = xConsumer(spaces, etSPACESIZE, pUserData); | ||
2957 | if( rc != SXRET_OK ){ | ||
2958 | return SXERR_ABORT; /* Consumer routine request an operation abort */ | ||
2959 | } | ||
2960 | nspace -= etSPACESIZE; | ||
2961 | } | ||
2962 | if( nspace>0 ){ | ||
2963 | rc = xConsumer(spaces, (unsigned int)nspace, pUserData); | ||
2964 | if( rc != SXRET_OK ){ | ||
2965 | return SXERR_ABORT; /* Consumer routine request an operation abort */ | ||
2966 | } | ||
2967 | } | ||
2968 | } | ||
2969 | } | ||
2970 | }/* End for loop over the format string */ | ||
2971 | return errorflag ? SXERR_FORMAT : SXRET_OK; | ||
2972 | } | ||
2973 | static sxi32 FormatConsumer(const void *pSrc, unsigned int nLen, void *pData) | ||
2974 | { | ||
2975 | SyFmtConsumer *pConsumer = (SyFmtConsumer *)pData; | ||
2976 | sxi32 rc = SXERR_ABORT; | ||
2977 | switch(pConsumer->nType){ | ||
2978 | case SXFMT_CONS_PROC: | ||
2979 | /* User callback */ | ||
2980 | rc = pConsumer->uConsumer.sFunc.xUserConsumer(pSrc, nLen, pConsumer->uConsumer.sFunc.pUserData); | ||
2981 | break; | ||
2982 | case SXFMT_CONS_BLOB: | ||
2983 | /* Blob consumer */ | ||
2984 | rc = SyBlobAppend(pConsumer->uConsumer.pBlob, pSrc, (sxu32)nLen); | ||
2985 | break; | ||
2986 | default: | ||
2987 | /* Unknown consumer */ | ||
2988 | break; | ||
2989 | } | ||
2990 | /* Update total number of bytes consumed so far */ | ||
2991 | pConsumer->nLen += nLen; | ||
2992 | pConsumer->rc = rc; | ||
2993 | return rc; | ||
2994 | } | ||
2995 | static sxi32 FormatMount(sxi32 nType, void *pConsumer, ProcConsumer xUserCons, void *pUserData, sxu32 *pOutLen, const char *zFormat, va_list ap) | ||
2996 | { | ||
2997 | SyFmtConsumer sCons; | ||
2998 | sCons.nType = nType; | ||
2999 | sCons.rc = SXRET_OK; | ||
3000 | sCons.nLen = 0; | ||
3001 | if( pOutLen ){ | ||
3002 | *pOutLen = 0; | ||
3003 | } | ||
3004 | switch(nType){ | ||
3005 | case SXFMT_CONS_PROC: | ||
3006 | #if defined(UNTRUST) | ||
3007 | if( xUserCons == 0 ){ | ||
3008 | return SXERR_EMPTY; | ||
3009 | } | ||
3010 | #endif | ||
3011 | sCons.uConsumer.sFunc.xUserConsumer = xUserCons; | ||
3012 | sCons.uConsumer.sFunc.pUserData = pUserData; | ||
3013 | break; | ||
3014 | case SXFMT_CONS_BLOB: | ||
3015 | sCons.uConsumer.pBlob = (SyBlob *)pConsumer; | ||
3016 | break; | ||
3017 | default: | ||
3018 | return SXERR_UNKNOWN; | ||
3019 | } | ||
3020 | InternFormat(FormatConsumer, &sCons, zFormat, ap); | ||
3021 | if( pOutLen ){ | ||
3022 | *pOutLen = sCons.nLen; | ||
3023 | } | ||
3024 | return sCons.rc; | ||
3025 | } | ||
3026 | JX9_PRIVATE sxi32 SyProcFormat(ProcConsumer xConsumer, void *pData, const char *zFormat, ...) | ||
3027 | { | ||
3028 | va_list ap; | ||
3029 | sxi32 rc; | ||
3030 | #if defined(UNTRUST) | ||
3031 | if( SX_EMPTY_STR(zFormat) ){ | ||
3032 | return SXERR_EMPTY; | ||
3033 | } | ||
3034 | #endif | ||
3035 | va_start(ap, zFormat); | ||
3036 | rc = FormatMount(SXFMT_CONS_PROC, 0, xConsumer, pData, 0, zFormat, ap); | ||
3037 | va_end(ap); | ||
3038 | return rc; | ||
3039 | } | ||
3040 | JX9_PRIVATE sxu32 SyBlobFormat(SyBlob *pBlob, const char *zFormat, ...) | ||
3041 | { | ||
3042 | va_list ap; | ||
3043 | sxu32 n; | ||
3044 | #if defined(UNTRUST) | ||
3045 | if( SX_EMPTY_STR(zFormat) ){ | ||
3046 | return 0; | ||
3047 | } | ||
3048 | #endif | ||
3049 | va_start(ap, zFormat); | ||
3050 | FormatMount(SXFMT_CONS_BLOB, &(*pBlob), 0, 0, &n, zFormat, ap); | ||
3051 | va_end(ap); | ||
3052 | return n; | ||
3053 | } | ||
3054 | JX9_PRIVATE sxu32 SyBlobFormatAp(SyBlob *pBlob, const char *zFormat, va_list ap) | ||
3055 | { | ||
3056 | sxu32 n = 0; /* cc warning */ | ||
3057 | #if defined(UNTRUST) | ||
3058 | if( SX_EMPTY_STR(zFormat) ){ | ||
3059 | return 0; | ||
3060 | } | ||
3061 | #endif | ||
3062 | FormatMount(SXFMT_CONS_BLOB, &(*pBlob), 0, 0, &n, zFormat, ap); | ||
3063 | return n; | ||
3064 | } | ||
3065 | JX9_PRIVATE sxu32 SyBufferFormat(char *zBuf, sxu32 nLen, const char *zFormat, ...) | ||
3066 | { | ||
3067 | SyBlob sBlob; | ||
3068 | va_list ap; | ||
3069 | sxu32 n; | ||
3070 | #if defined(UNTRUST) | ||
3071 | if( SX_EMPTY_STR(zFormat) ){ | ||
3072 | return 0; | ||
3073 | } | ||
3074 | #endif | ||
3075 | if( SXRET_OK != SyBlobInitFromBuf(&sBlob, zBuf, nLen - 1) ){ | ||
3076 | return 0; | ||
3077 | } | ||
3078 | va_start(ap, zFormat); | ||
3079 | FormatMount(SXFMT_CONS_BLOB, &sBlob, 0, 0, 0, zFormat, ap); | ||
3080 | va_end(ap); | ||
3081 | n = SyBlobLength(&sBlob); | ||
3082 | /* Append the null terminator */ | ||
3083 | sBlob.mByte++; | ||
3084 | SyBlobAppend(&sBlob, "\0", sizeof(char)); | ||
3085 | return n; | ||
3086 | } | ||
3087 | #ifndef JX9_DISABLE_BUILTIN_FUNC | ||
3088 | /* | ||
3089 | * Zip File Format: | ||
3090 | * | ||
3091 | * Byte order: Little-endian | ||
3092 | * | ||
3093 | * [Local file header + Compressed data [+ Extended local header]?]* | ||
3094 | * [Central directory]* | ||
3095 | * [End of central directory record] | ||
3096 | * | ||
3097 | * Local file header:* | ||
3098 | * Offset Length Contents | ||
3099 | * 0 4 bytes Local file header signature (0x04034b50) | ||
3100 | * 4 2 bytes Version needed to extract | ||
3101 | * 6 2 bytes General purpose bit flag | ||
3102 | * 8 2 bytes Compression method | ||
3103 | * 10 2 bytes Last mod file time | ||
3104 | * 12 2 bytes Last mod file date | ||
3105 | * 14 4 bytes CRC-32 | ||
3106 | * 18 4 bytes Compressed size (n) | ||
3107 | * 22 4 bytes Uncompressed size | ||
3108 | * 26 2 bytes Filename length (f) | ||
3109 | * 28 2 bytes Extra field length (e) | ||
3110 | * 30 (f)bytes Filename | ||
3111 | * (e)bytes Extra field | ||
3112 | * (n)bytes Compressed data | ||
3113 | * | ||
3114 | * Extended local header:* | ||
3115 | * Offset Length Contents | ||
3116 | * 0 4 bytes Extended Local file header signature (0x08074b50) | ||
3117 | * 4 4 bytes CRC-32 | ||
3118 | * 8 4 bytes Compressed size | ||
3119 | * 12 4 bytes Uncompressed size | ||
3120 | * | ||
3121 | * Extra field:?(if any) | ||
3122 | * Offset Length Contents | ||
3123 | * 0 2 bytes Header ID (0x001 until 0xfb4a) see extended appnote from Info-zip | ||
3124 | * 2 2 bytes Data size (g) | ||
3125 | * (g) bytes (g) bytes of extra field | ||
3126 | * | ||
3127 | * Central directory:* | ||
3128 | * Offset Length Contents | ||
3129 | * 0 4 bytes Central file header signature (0x02014b50) | ||
3130 | * 4 2 bytes Version made by | ||
3131 | * 6 2 bytes Version needed to extract | ||
3132 | * 8 2 bytes General purpose bit flag | ||
3133 | * 10 2 bytes Compression method | ||
3134 | * 12 2 bytes Last mod file time | ||
3135 | * 14 2 bytes Last mod file date | ||
3136 | * 16 4 bytes CRC-32 | ||
3137 | * 20 4 bytes Compressed size | ||
3138 | * 24 4 bytes Uncompressed size | ||
3139 | * 28 2 bytes Filename length (f) | ||
3140 | * 30 2 bytes Extra field length (e) | ||
3141 | * 32 2 bytes File comment length (c) | ||
3142 | * 34 2 bytes Disk number start | ||
3143 | * 36 2 bytes Internal file attributes | ||
3144 | * 38 4 bytes External file attributes | ||
3145 | * 42 4 bytes Relative offset of local header | ||
3146 | * 46 (f)bytes Filename | ||
3147 | * (e)bytes Extra field | ||
3148 | * (c)bytes File comment | ||
3149 | * | ||
3150 | * End of central directory record: | ||
3151 | * Offset Length Contents | ||
3152 | * 0 4 bytes End of central dir signature (0x06054b50) | ||
3153 | * 4 2 bytes Number of this disk | ||
3154 | * 6 2 bytes Number of the disk with the start of the central directory | ||
3155 | * 8 2 bytes Total number of entries in the central dir on this disk | ||
3156 | * 10 2 bytes Total number of entries in the central dir | ||
3157 | * 12 4 bytes Size of the central directory | ||
3158 | * 16 4 bytes Offset of start of central directory with respect to the starting disk number | ||
3159 | * 20 2 bytes zipfile comment length (c) | ||
3160 | * 22 (c)bytes zipfile comment | ||
3161 | * | ||
3162 | * compression method: (2 bytes) | ||
3163 | * 0 - The file is stored (no compression) | ||
3164 | * 1 - The file is Shrunk | ||
3165 | * 2 - The file is Reduced with compression factor 1 | ||
3166 | * 3 - The file is Reduced with compression factor 2 | ||
3167 | * 4 - The file is Reduced with compression factor 3 | ||
3168 | * 5 - The file is Reduced with compression factor 4 | ||
3169 | * 6 - The file is Imploded | ||
3170 | * 7 - Reserved for Tokenizing compression algorithm | ||
3171 | * 8 - The file is Deflated | ||
3172 | */ | ||
3173 | |||
3174 | #define SXMAKE_ZIP_WORKBUF (SXU16_HIGH/2) /* 32KB Initial working buffer size */ | ||
3175 | #define SXMAKE_ZIP_EXTRACT_VER 0x000a /* Version needed to extract */ | ||
3176 | #define SXMAKE_ZIP_VER 0x003 /* Version made by */ | ||
3177 | |||
3178 | #define SXZIP_CENTRAL_MAGIC 0x02014b50 | ||
3179 | #define SXZIP_END_CENTRAL_MAGIC 0x06054b50 | ||
3180 | #define SXZIP_LOCAL_MAGIC 0x04034b50 | ||
3181 | /*#define SXZIP_CRC32_START 0xdebb20e3*/ | ||
3182 | |||
3183 | #define SXZIP_LOCAL_HDRSZ 30 /* Local header size */ | ||
3184 | #define SXZIP_LOCAL_EXT_HDRZ 16 /* Extended local header(footer) size */ | ||
3185 | #define SXZIP_CENTRAL_HDRSZ 46 /* Central directory header size */ | ||
3186 | #define SXZIP_END_CENTRAL_HDRSZ 22 /* End of central directory header size */ | ||
3187 | |||
3188 | #define SXARCHIVE_HASH_SIZE 64 /* Starting hash table size(MUST BE POWER OF 2)*/ | ||
3189 | static sxi32 SyLittleEndianUnpack32(sxu32 *uNB, const unsigned char *buf, sxu32 Len) | ||
3190 | { | ||
3191 | if( Len < sizeof(sxu32) ){ | ||
3192 | return SXERR_SHORT; | ||
3193 | } | ||
3194 | *uNB = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24); | ||
3195 | return SXRET_OK; | ||
3196 | } | ||
3197 | static sxi32 SyLittleEndianUnpack16(sxu16 *pOut, const unsigned char *zBuf, sxu32 nLen) | ||
3198 | { | ||
3199 | if( nLen < sizeof(sxu16) ){ | ||
3200 | return SXERR_SHORT; | ||
3201 | } | ||
3202 | *pOut = zBuf[0] + (zBuf[1] <<8); | ||
3203 | |||
3204 | return SXRET_OK; | ||
3205 | } | ||
3206 | /* | ||
3207 | * Archive hashtable manager | ||
3208 | */ | ||
3209 | static sxi32 ArchiveHashGetEntry(SyArchive *pArch, const char *zName, sxu32 nLen, SyArchiveEntry **ppEntry) | ||
3210 | { | ||
3211 | SyArchiveEntry *pBucketEntry; | ||
3212 | SyString sEntry; | ||
3213 | sxu32 nHash; | ||
3214 | |||
3215 | nHash = pArch->xHash(zName, nLen); | ||
3216 | pBucketEntry = pArch->apHash[nHash & (pArch->nSize - 1)]; | ||
3217 | |||
3218 | SyStringInitFromBuf(&sEntry, zName, nLen); | ||
3219 | |||
3220 | for(;;){ | ||
3221 | if( pBucketEntry == 0 ){ | ||
3222 | break; | ||
3223 | } | ||
3224 | if( nHash == pBucketEntry->nHash && pArch->xCmp(&sEntry, &pBucketEntry->sFileName) == 0 ){ | ||
3225 | if( ppEntry ){ | ||
3226 | *ppEntry = pBucketEntry; | ||
3227 | } | ||
3228 | return SXRET_OK; | ||
3229 | } | ||
3230 | pBucketEntry = pBucketEntry->pNextHash; | ||
3231 | } | ||
3232 | return SXERR_NOTFOUND; | ||
3233 | } | ||
3234 | static void ArchiveHashBucketInstall(SyArchiveEntry **apTable, sxu32 nBucket, SyArchiveEntry *pEntry) | ||
3235 | { | ||
3236 | pEntry->pNextHash = apTable[nBucket]; | ||
3237 | if( apTable[nBucket] != 0 ){ | ||
3238 | apTable[nBucket]->pPrevHash = pEntry; | ||
3239 | } | ||
3240 | apTable[nBucket] = pEntry; | ||
3241 | } | ||
3242 | static sxi32 ArchiveHashGrowTable(SyArchive *pArch) | ||
3243 | { | ||
3244 | sxu32 nNewSize = pArch->nSize * 2; | ||
3245 | SyArchiveEntry **apNew; | ||
3246 | SyArchiveEntry *pEntry; | ||
3247 | sxu32 n; | ||
3248 | |||
3249 | /* Allocate a new table */ | ||
3250 | apNew = (SyArchiveEntry **)SyMemBackendAlloc(pArch->pAllocator, nNewSize * sizeof(SyArchiveEntry *)); | ||
3251 | if( apNew == 0 ){ | ||
3252 | return SXRET_OK; /* Not so fatal, simply a performance hit */ | ||
3253 | } | ||
3254 | SyZero(apNew, nNewSize * sizeof(SyArchiveEntry *)); | ||
3255 | /* Rehash old entries */ | ||
3256 | for( n = 0 , pEntry = pArch->pList ; n < pArch->nLoaded ; n++ , pEntry = pEntry->pNext ){ | ||
3257 | pEntry->pNextHash = pEntry->pPrevHash = 0; | ||
3258 | ArchiveHashBucketInstall(apNew, pEntry->nHash & (nNewSize - 1), pEntry); | ||
3259 | } | ||
3260 | /* Release the old table */ | ||
3261 | SyMemBackendFree(pArch->pAllocator, pArch->apHash); | ||
3262 | pArch->apHash = apNew; | ||
3263 | pArch->nSize = nNewSize; | ||
3264 | |||
3265 | return SXRET_OK; | ||
3266 | } | ||
3267 | static sxi32 ArchiveHashInstallEntry(SyArchive *pArch, SyArchiveEntry *pEntry) | ||
3268 | { | ||
3269 | if( pArch->nLoaded > pArch->nSize * 3 ){ | ||
3270 | ArchiveHashGrowTable(&(*pArch)); | ||
3271 | } | ||
3272 | pEntry->nHash = pArch->xHash(SyStringData(&pEntry->sFileName), SyStringLength(&pEntry->sFileName)); | ||
3273 | /* Install the entry in its bucket */ | ||
3274 | ArchiveHashBucketInstall(pArch->apHash, pEntry->nHash & (pArch->nSize - 1), pEntry); | ||
3275 | MACRO_LD_PUSH(pArch->pList, pEntry); | ||
3276 | pArch->nLoaded++; | ||
3277 | |||
3278 | return SXRET_OK; | ||
3279 | } | ||
3280 | /* | ||
3281 | * Parse the End of central directory and report status | ||
3282 | */ | ||
3283 | static sxi32 ParseEndOfCentralDirectory(SyArchive *pArch, const unsigned char *zBuf) | ||
3284 | { | ||
3285 | sxu32 nMagic = 0; /* cc -O6 warning */ | ||
3286 | sxi32 rc; | ||
3287 | |||
3288 | /* Sanity check */ | ||
3289 | rc = SyLittleEndianUnpack32(&nMagic, zBuf, sizeof(sxu32)); | ||
3290 | if( /* rc != SXRET_OK || */nMagic != SXZIP_END_CENTRAL_MAGIC ){ | ||
3291 | return SXERR_CORRUPT; | ||
3292 | } | ||
3293 | /* # of entries */ | ||
3294 | rc = SyLittleEndianUnpack16((sxu16 *)&pArch->nEntry, &zBuf[8], sizeof(sxu16)); | ||
3295 | if( /* rc != SXRET_OK || */ pArch->nEntry > SXI16_HIGH /* SXU16_HIGH */ ){ | ||
3296 | return SXERR_CORRUPT; | ||
3297 | } | ||
3298 | /* Size of central directory */ | ||
3299 | rc = SyLittleEndianUnpack32(&pArch->nCentralSize, &zBuf[12], sizeof(sxu32)); | ||
3300 | if( /*rc != SXRET_OK ||*/ pArch->nCentralSize > SXI32_HIGH ){ | ||
3301 | return SXERR_CORRUPT; | ||
3302 | } | ||
3303 | /* Starting offset of central directory */ | ||
3304 | rc = SyLittleEndianUnpack32(&pArch->nCentralOfft, &zBuf[16], sizeof(sxu32)); | ||
3305 | if( /*rc != SXRET_OK ||*/ pArch->nCentralSize > SXI32_HIGH ){ | ||
3306 | return SXERR_CORRUPT; | ||
3307 | } | ||
3308 | |||
3309 | return SXRET_OK; | ||
3310 | } | ||
3311 | /* | ||
3312 | * Fill the zip entry with the appropriate information from the central directory | ||
3313 | */ | ||
3314 | static sxi32 GetCentralDirectoryEntry(SyArchive *pArch, SyArchiveEntry *pEntry, const unsigned char *zCentral, sxu32 *pNextOffset) | ||
3315 | { | ||
3316 | SyString *pName = &pEntry->sFileName; /* File name */ | ||
3317 | sxu16 nDosDate, nDosTime; | ||
3318 | sxu16 nComment = 0 ; | ||
3319 | sxu32 nMagic = 0; /* cc -O6 warning */ | ||
3320 | sxi32 rc; | ||
3321 | nDosDate = nDosTime = 0; /* cc -O6 warning */ | ||
3322 | SXUNUSED(pArch); | ||
3323 | /* Sanity check */ | ||
3324 | rc = SyLittleEndianUnpack32(&nMagic, zCentral, sizeof(sxu32)); | ||
3325 | if( /* rc != SXRET_OK || */ nMagic != SXZIP_CENTRAL_MAGIC ){ | ||
3326 | rc = SXERR_CORRUPT; | ||
3327 | /* | ||
3328 | * Try to recover by examing the next central directory record. | ||
3329 | * Dont worry here, there is no risk of an infinite loop since | ||
3330 | * the buffer size is delimited. | ||
3331 | */ | ||
3332 | |||
3333 | /* pName->nByte = 0; nComment = 0; pName->nExtra = 0 */ | ||
3334 | goto update; | ||
3335 | } | ||
3336 | /* | ||
3337 | * entry name length | ||
3338 | */ | ||
3339 | SyLittleEndianUnpack16((sxu16 *)&pName->nByte, &zCentral[28], sizeof(sxu16)); | ||
3340 | if( pName->nByte > SXI16_HIGH /* SXU16_HIGH */){ | ||
3341 | rc = SXERR_BIG; | ||
3342 | goto update; | ||
3343 | } | ||
3344 | /* Extra information */ | ||
3345 | SyLittleEndianUnpack16(&pEntry->nExtra, &zCentral[30], sizeof(sxu16)); | ||
3346 | /* Comment length */ | ||
3347 | SyLittleEndianUnpack16(&nComment, &zCentral[32], sizeof(sxu16)); | ||
3348 | /* Compression method 0 == stored / 8 == deflated */ | ||
3349 | rc = SyLittleEndianUnpack16(&pEntry->nComprMeth, &zCentral[10], sizeof(sxu16)); | ||
3350 | /* DOS Timestamp */ | ||
3351 | SyLittleEndianUnpack16(&nDosTime, &zCentral[12], sizeof(sxu16)); | ||
3352 | SyLittleEndianUnpack16(&nDosDate, &zCentral[14], sizeof(sxu16)); | ||
3353 | SyDosTimeFormat((nDosDate << 16 | nDosTime), &pEntry->sFmt); | ||
3354 | /* Little hack to fix month index */ | ||
3355 | pEntry->sFmt.tm_mon--; | ||
3356 | /* CRC32 */ | ||
3357 | rc = SyLittleEndianUnpack32(&pEntry->nCrc, &zCentral[16], sizeof(sxu32)); | ||
3358 | /* Content size before compression */ | ||
3359 | rc = SyLittleEndianUnpack32(&pEntry->nByte, &zCentral[24], sizeof(sxu32)); | ||
3360 | if( pEntry->nByte > SXI32_HIGH ){ | ||
3361 | rc = SXERR_BIG; | ||
3362 | goto update; | ||
3363 | } | ||
3364 | /* | ||
3365 | * Content size after compression. | ||
3366 | * Note that if the file is stored pEntry->nByte should be equal to pEntry->nByteCompr | ||
3367 | */ | ||
3368 | rc = SyLittleEndianUnpack32(&pEntry->nByteCompr, &zCentral[20], sizeof(sxu32)); | ||
3369 | if( pEntry->nByteCompr > SXI32_HIGH ){ | ||
3370 | rc = SXERR_BIG; | ||
3371 | goto update; | ||
3372 | } | ||
3373 | /* Finally grab the contents offset */ | ||
3374 | SyLittleEndianUnpack32(&pEntry->nOfft, &zCentral[42], sizeof(sxu32)); | ||
3375 | if( pEntry->nOfft > SXI32_HIGH ){ | ||
3376 | rc = SXERR_BIG; | ||
3377 | goto update; | ||
3378 | } | ||
3379 | rc = SXRET_OK; | ||
3380 | update: | ||
3381 | /* Update the offset to point to the next central directory record */ | ||
3382 | *pNextOffset = SXZIP_CENTRAL_HDRSZ + pName->nByte + pEntry->nExtra + nComment; | ||
3383 | return rc; /* Report failure or success */ | ||
3384 | } | ||
3385 | static sxi32 ZipFixOffset(SyArchiveEntry *pEntry, void *pSrc) | ||
3386 | { | ||
3387 | sxu16 nExtra, nNameLen; | ||
3388 | unsigned char *zHdr; | ||
3389 | nExtra = nNameLen = 0; | ||
3390 | zHdr = (unsigned char *)pSrc; | ||
3391 | zHdr = &zHdr[pEntry->nOfft]; | ||
3392 | if( SyMemcmp(zHdr, "PK\003\004", sizeof(sxu32)) != 0 ){ | ||
3393 | return SXERR_CORRUPT; | ||
3394 | } | ||
3395 | SyLittleEndianUnpack16(&nNameLen, &zHdr[26], sizeof(sxu16)); | ||
3396 | SyLittleEndianUnpack16(&nExtra, &zHdr[28], sizeof(sxu16)); | ||
3397 | /* Fix contents offset */ | ||
3398 | pEntry->nOfft += SXZIP_LOCAL_HDRSZ + nExtra + nNameLen; | ||
3399 | return SXRET_OK; | ||
3400 | } | ||
3401 | /* | ||
3402 | * Extract all valid entries from the central directory | ||
3403 | */ | ||
3404 | static sxi32 ZipExtract(SyArchive *pArch, const unsigned char *zCentral, sxu32 nLen, void *pSrc) | ||
3405 | { | ||
3406 | SyArchiveEntry *pEntry, *pDup; | ||
3407 | const unsigned char *zEnd ; /* End of central directory */ | ||
3408 | sxu32 nIncr, nOfft; /* Central Offset */ | ||
3409 | SyString *pName; /* Entry name */ | ||
3410 | char *zName; | ||
3411 | sxi32 rc; | ||
3412 | |||
3413 | nOfft = nIncr = 0; | ||
3414 | zEnd = &zCentral[nLen]; | ||
3415 | |||
3416 | for(;;){ | ||
3417 | if( &zCentral[nOfft] >= zEnd ){ | ||
3418 | break; | ||
3419 | } | ||
3420 | /* Add a new entry */ | ||
3421 | pEntry = (SyArchiveEntry *)SyMemBackendPoolAlloc(pArch->pAllocator, sizeof(SyArchiveEntry)); | ||
3422 | if( pEntry == 0 ){ | ||
3423 | break; | ||
3424 | } | ||
3425 | SyZero(pEntry, sizeof(SyArchiveEntry)); | ||
3426 | pEntry->nMagic = SXARCH_MAGIC; | ||
3427 | nIncr = 0; | ||
3428 | rc = GetCentralDirectoryEntry(&(*pArch), pEntry, &zCentral[nOfft], &nIncr); | ||
3429 | if( rc == SXRET_OK ){ | ||
3430 | /* Fix the starting record offset so we can access entry contents correctly */ | ||
3431 | rc = ZipFixOffset(pEntry, pSrc); | ||
3432 | } | ||
3433 | if(rc != SXRET_OK ){ | ||
3434 | sxu32 nJmp = 0; | ||
3435 | SyMemBackendPoolFree(pArch->pAllocator, pEntry); | ||
3436 | /* Try to recover by brute-forcing for a valid central directory record */ | ||
3437 | if( SXRET_OK == SyBlobSearch((const void *)&zCentral[nOfft + nIncr], (sxu32)(zEnd - &zCentral[nOfft + nIncr]), | ||
3438 | (const void *)"PK\001\002", sizeof(sxu32), &nJmp)){ | ||
3439 | nOfft += nIncr + nJmp; /* Check next entry */ | ||
3440 | continue; | ||
3441 | } | ||
3442 | break; /* Giving up, archive is hopelessly corrupted */ | ||
3443 | } | ||
3444 | pName = &pEntry->sFileName; | ||
3445 | pName->zString = (const char *)&zCentral[nOfft + SXZIP_CENTRAL_HDRSZ]; | ||
3446 | if( pName->nByte <= 0 || ( pEntry->nByte <= 0 && pName->zString[pName->nByte - 1] != '/') ){ | ||
3447 | /* Ignore zero length records (except folders) and records without names */ | ||
3448 | SyMemBackendPoolFree(pArch->pAllocator, pEntry); | ||
3449 | nOfft += nIncr; /* Check next entry */ | ||
3450 | continue; | ||
3451 | } | ||
3452 | zName = SyMemBackendStrDup(pArch->pAllocator, pName->zString, pName->nByte); | ||
3453 | if( zName == 0 ){ | ||
3454 | SyMemBackendPoolFree(pArch->pAllocator, pEntry); | ||
3455 | nOfft += nIncr; /* Check next entry */ | ||
3456 | continue; | ||
3457 | } | ||
3458 | pName->zString = (const char *)zName; | ||
3459 | /* Check for duplicates */ | ||
3460 | rc = ArchiveHashGetEntry(&(*pArch), pName->zString, pName->nByte, &pDup); | ||
3461 | if( rc == SXRET_OK ){ | ||
3462 | /* Another entry with the same name exists ; link them together */ | ||
3463 | pEntry->pNextName = pDup->pNextName; | ||
3464 | pDup->pNextName = pEntry; | ||
3465 | pDup->nDup++; | ||
3466 | }else{ | ||
3467 | /* Insert in hashtable */ | ||
3468 | ArchiveHashInstallEntry(pArch, pEntry); | ||
3469 | } | ||
3470 | nOfft += nIncr; /* Check next record */ | ||
3471 | } | ||
3472 | pArch->pCursor = pArch->pList; | ||
3473 | |||
3474 | return pArch->nLoaded > 0 ? SXRET_OK : SXERR_EMPTY; | ||
3475 | } | ||
3476 | JX9_PRIVATE sxi32 SyZipExtractFromBuf(SyArchive *pArch, const char *zBuf, sxu32 nLen) | ||
3477 | { | ||
3478 | const unsigned char *zCentral, *zEnd; | ||
3479 | sxi32 rc; | ||
3480 | #if defined(UNTRUST) | ||
3481 | if( SXARCH_INVALID(pArch) || zBuf == 0 ){ | ||
3482 | return SXERR_INVALID; | ||
3483 | } | ||
3484 | #endif | ||
3485 | /* The miminal size of a zip archive: | ||
3486 | * LOCAL_HDR_SZ + CENTRAL_HDR_SZ + END_OF_CENTRAL_HDR_SZ | ||
3487 | * 30 46 22 | ||
3488 | */ | ||
3489 | if( nLen < SXZIP_LOCAL_HDRSZ + SXZIP_CENTRAL_HDRSZ + SXZIP_END_CENTRAL_HDRSZ ){ | ||
3490 | return SXERR_CORRUPT; /* Don't bother processing return immediately */ | ||
3491 | } | ||
3492 | |||
3493 | zEnd = (unsigned char *)&zBuf[nLen - SXZIP_END_CENTRAL_HDRSZ]; | ||
3494 | /* Find the end of central directory */ | ||
3495 | while( ((sxu32)((unsigned char *)&zBuf[nLen] - zEnd) < (SXZIP_END_CENTRAL_HDRSZ + SXI16_HIGH)) && | ||
3496 | zEnd > (unsigned char *)zBuf && SyMemcmp(zEnd, "PK\005\006", sizeof(sxu32)) != 0 ){ | ||
3497 | zEnd--; | ||
3498 | } | ||
3499 | /* Parse the end of central directory */ | ||
3500 | rc = ParseEndOfCentralDirectory(&(*pArch), zEnd); | ||
3501 | if( rc != SXRET_OK ){ | ||
3502 | return rc; | ||
3503 | } | ||
3504 | |||
3505 | /* Find the starting offset of the central directory */ | ||
3506 | zCentral = &zEnd[-(sxi32)pArch->nCentralSize]; | ||
3507 | if( zCentral <= (unsigned char *)zBuf || SyMemcmp(zCentral, "PK\001\002", sizeof(sxu32)) != 0 ){ | ||
3508 | if( pArch->nCentralOfft >= nLen ){ | ||
3509 | /* Corrupted central directory offset */ | ||
3510 | return SXERR_CORRUPT; | ||
3511 | } | ||
3512 | zCentral = (unsigned char *)&zBuf[pArch->nCentralOfft]; | ||
3513 | if( SyMemcmp(zCentral, "PK\001\002", sizeof(sxu32)) != 0 ){ | ||
3514 | /* Corrupted zip archive */ | ||
3515 | return SXERR_CORRUPT; | ||
3516 | } | ||
3517 | /* Fall thru and extract all valid entries from the central directory */ | ||
3518 | } | ||
3519 | rc = ZipExtract(&(*pArch), zCentral, (sxu32)(zEnd - zCentral), (void *)zBuf); | ||
3520 | return rc; | ||
3521 | } | ||
3522 | /* | ||
3523 | * Default comparison function. | ||
3524 | */ | ||
3525 | static sxi32 ArchiveHashCmp(const SyString *pStr1, const SyString *pStr2) | ||
3526 | { | ||
3527 | sxi32 rc; | ||
3528 | rc = SyStringCmp(pStr1, pStr2, SyMemcmp); | ||
3529 | return rc; | ||
3530 | } | ||
3531 | JX9_PRIVATE sxi32 SyArchiveInit(SyArchive *pArch, SyMemBackend *pAllocator, ProcHash xHash, ProcRawStrCmp xCmp) | ||
3532 | { | ||
3533 | SyArchiveEntry **apHash; | ||
3534 | #if defined(UNTRUST) | ||
3535 | if( pArch == 0 ){ | ||
3536 | return SXERR_EMPTY; | ||
3537 | } | ||
3538 | #endif | ||
3539 | SyZero(pArch, sizeof(SyArchive)); | ||
3540 | /* Allocate a new hashtable */ | ||
3541 | apHash = (SyArchiveEntry **)SyMemBackendAlloc(&(*pAllocator), SXARCHIVE_HASH_SIZE * sizeof(SyArchiveEntry *)); | ||
3542 | if( apHash == 0){ | ||
3543 | return SXERR_MEM; | ||
3544 | } | ||
3545 | SyZero(apHash, SXARCHIVE_HASH_SIZE * sizeof(SyArchiveEntry *)); | ||
3546 | pArch->apHash = apHash; | ||
3547 | pArch->xHash = xHash ? xHash : SyBinHash; | ||
3548 | pArch->xCmp = xCmp ? xCmp : ArchiveHashCmp; | ||
3549 | pArch->nSize = SXARCHIVE_HASH_SIZE; | ||
3550 | pArch->pAllocator = &(*pAllocator); | ||
3551 | pArch->nMagic = SXARCH_MAGIC; | ||
3552 | return SXRET_OK; | ||
3553 | } | ||
3554 | static sxi32 ArchiveReleaseEntry(SyMemBackend *pAllocator, SyArchiveEntry *pEntry) | ||
3555 | { | ||
3556 | SyArchiveEntry *pDup = pEntry->pNextName; | ||
3557 | SyArchiveEntry *pNextDup; | ||
3558 | |||
3559 | /* Release duplicates first since there are not stored in the hashtable */ | ||
3560 | for(;;){ | ||
3561 | if( pEntry->nDup == 0 ){ | ||
3562 | break; | ||
3563 | } | ||
3564 | pNextDup = pDup->pNextName; | ||
3565 | pDup->nMagic = 0x2661; | ||
3566 | SyMemBackendFree(pAllocator, (void *)SyStringData(&pDup->sFileName)); | ||
3567 | SyMemBackendPoolFree(pAllocator, pDup); | ||
3568 | pDup = pNextDup; | ||
3569 | pEntry->nDup--; | ||
3570 | } | ||
3571 | pEntry->nMagic = 0x2661; | ||
3572 | SyMemBackendFree(pAllocator, (void *)SyStringData(&pEntry->sFileName)); | ||
3573 | SyMemBackendPoolFree(pAllocator, pEntry); | ||
3574 | return SXRET_OK; | ||
3575 | } | ||
3576 | JX9_PRIVATE sxi32 SyArchiveRelease(SyArchive *pArch) | ||
3577 | { | ||
3578 | SyArchiveEntry *pEntry, *pNext; | ||
3579 | pEntry = pArch->pList; | ||
3580 | for(;;){ | ||
3581 | if( pArch->nLoaded < 1 ){ | ||
3582 | break; | ||
3583 | } | ||
3584 | pNext = pEntry->pNext; | ||
3585 | MACRO_LD_REMOVE(pArch->pList, pEntry); | ||
3586 | ArchiveReleaseEntry(pArch->pAllocator, pEntry); | ||
3587 | pEntry = pNext; | ||
3588 | pArch->nLoaded--; | ||
3589 | } | ||
3590 | SyMemBackendFree(pArch->pAllocator, pArch->apHash); | ||
3591 | pArch->pCursor = 0; | ||
3592 | pArch->nMagic = 0x2626; | ||
3593 | return SXRET_OK; | ||
3594 | } | ||
3595 | JX9_PRIVATE sxi32 SyArchiveResetLoopCursor(SyArchive *pArch) | ||
3596 | { | ||
3597 | pArch->pCursor = pArch->pList; | ||
3598 | return SXRET_OK; | ||
3599 | } | ||
3600 | JX9_PRIVATE sxi32 SyArchiveGetNextEntry(SyArchive *pArch, SyArchiveEntry **ppEntry) | ||
3601 | { | ||
3602 | SyArchiveEntry *pNext; | ||
3603 | if( pArch->pCursor == 0 ){ | ||
3604 | /* Rewind the cursor */ | ||
3605 | pArch->pCursor = pArch->pList; | ||
3606 | return SXERR_EOF; | ||
3607 | } | ||
3608 | *ppEntry = pArch->pCursor; | ||
3609 | pNext = pArch->pCursor->pNext; | ||
3610 | /* Advance the cursor to the next entry */ | ||
3611 | pArch->pCursor = pNext; | ||
3612 | return SXRET_OK; | ||
3613 | } | ||
3614 | #endif /* JX9_DISABLE_BUILTIN_FUNC */ | ||
3615 | /* | ||
3616 | * Psuedo Random Number Generator (PRNG) | ||
3617 | * @authors: SQLite authors <http://www.sqlite.org/> | ||
3618 | * @status: Public Domain | ||
3619 | * NOTE: | ||
3620 | * Nothing in this file or anywhere else in the library does any kind of | ||
3621 | * encryption.The RC4 algorithm is being used as a PRNG (pseudo-random | ||
3622 | * number generator) not as an encryption device. | ||
3623 | */ | ||
3624 | #define SXPRNG_MAGIC 0x13C4 | ||
3625 | #ifdef __UNIXES__ | ||
3626 | #include <sys/types.h> | ||
3627 | #include <sys/stat.h> | ||
3628 | #include <fcntl.h> | ||
3629 | #include <unistd.h> | ||
3630 | #include <errno.h> | ||
3631 | #include <time.h> | ||
3632 | #include <sys/time.h> | ||
3633 | #endif | ||
3634 | static sxi32 SyOSUtilRandomSeed(void *pBuf, sxu32 nLen, void *pUnused) | ||
3635 | { | ||
3636 | char *zBuf = (char *)pBuf; | ||
3637 | #ifdef __WINNT__ | ||
3638 | DWORD nProcessID; /* Yes, keep it uninitialized when compiling using the MinGW32 builds tools */ | ||
3639 | #elif defined(__UNIXES__) | ||
3640 | pid_t pid; | ||
3641 | int fd; | ||
3642 | #else | ||
3643 | char zGarbage[128]; /* Yes, keep this buffer uninitialized */ | ||
3644 | #endif | ||
3645 | SXUNUSED(pUnused); | ||
3646 | #ifdef __WINNT__ | ||
3647 | #ifndef __MINGW32__ | ||
3648 | nProcessID = GetProcessId(GetCurrentProcess()); | ||
3649 | #endif | ||
3650 | SyMemcpy((const void *)&nProcessID, zBuf, SXMIN(nLen, sizeof(DWORD))); | ||
3651 | if( (sxu32)(&zBuf[nLen] - &zBuf[sizeof(DWORD)]) >= sizeof(SYSTEMTIME) ){ | ||
3652 | GetSystemTime((LPSYSTEMTIME)&zBuf[sizeof(DWORD)]); | ||
3653 | } | ||
3654 | #elif defined(__UNIXES__) | ||
3655 | fd = open("/dev/urandom", O_RDONLY); | ||
3656 | if (fd >= 0 ){ | ||
3657 | if( read(fd, zBuf, nLen) > 0 ){ | ||
3658 | return SXRET_OK; | ||
3659 | } | ||
3660 | /* FALL THRU */ | ||
3661 | } | ||
3662 | pid = getpid(); | ||
3663 | SyMemcpy((const void *)&pid, zBuf, SXMIN(nLen, sizeof(pid_t))); | ||
3664 | if( &zBuf[nLen] - &zBuf[sizeof(pid_t)] >= (int)sizeof(struct timeval) ){ | ||
3665 | gettimeofday((struct timeval *)&zBuf[sizeof(pid_t)], 0); | ||
3666 | } | ||
3667 | #else | ||
3668 | /* Fill with uninitialized data */ | ||
3669 | SyMemcpy(zGarbage, zBuf, SXMIN(nLen, sizeof(zGarbage))); | ||
3670 | #endif | ||
3671 | return SXRET_OK; | ||
3672 | } | ||
3673 | JX9_PRIVATE sxi32 SyRandomnessInit(SyPRNGCtx *pCtx, ProcRandomSeed xSeed, void * pUserData) | ||
3674 | { | ||
3675 | char zSeed[256]; | ||
3676 | sxu8 t; | ||
3677 | sxi32 rc; | ||
3678 | sxu32 i; | ||
3679 | if( pCtx->nMagic == SXPRNG_MAGIC ){ | ||
3680 | return SXRET_OK; /* Already initialized */ | ||
3681 | } | ||
3682 | /* Initialize the state of the random number generator once, | ||
3683 | ** the first time this routine is called.The seed value does | ||
3684 | ** not need to contain a lot of randomness since we are not | ||
3685 | ** trying to do secure encryption or anything like that... | ||
3686 | */ | ||
3687 | if( xSeed == 0 ){ | ||
3688 | xSeed = SyOSUtilRandomSeed; | ||
3689 | } | ||
3690 | rc = xSeed(zSeed, sizeof(zSeed), pUserData); | ||
3691 | if( rc != SXRET_OK ){ | ||
3692 | return rc; | ||
3693 | } | ||
3694 | pCtx->i = pCtx->j = 0; | ||
3695 | for(i=0; i < SX_ARRAYSIZE(pCtx->s) ; i++){ | ||
3696 | pCtx->s[i] = (unsigned char)i; | ||
3697 | } | ||
3698 | for(i=0; i < sizeof(zSeed) ; i++){ | ||
3699 | pCtx->j += pCtx->s[i] + zSeed[i]; | ||
3700 | t = pCtx->s[pCtx->j]; | ||
3701 | pCtx->s[pCtx->j] = pCtx->s[i]; | ||
3702 | pCtx->s[i] = t; | ||
3703 | } | ||
3704 | pCtx->nMagic = SXPRNG_MAGIC; | ||
3705 | |||
3706 | return SXRET_OK; | ||
3707 | } | ||
3708 | /* | ||
3709 | * Get a single 8-bit random value using the RC4 PRNG. | ||
3710 | */ | ||
3711 | static sxu8 randomByte(SyPRNGCtx *pCtx) | ||
3712 | { | ||
3713 | sxu8 t; | ||
3714 | |||
3715 | /* Generate and return single random byte */ | ||
3716 | pCtx->i++; | ||
3717 | t = pCtx->s[pCtx->i]; | ||
3718 | pCtx->j += t; | ||
3719 | pCtx->s[pCtx->i] = pCtx->s[pCtx->j]; | ||
3720 | pCtx->s[pCtx->j] = t; | ||
3721 | t += pCtx->s[pCtx->i]; | ||
3722 | return pCtx->s[t]; | ||
3723 | } | ||
3724 | JX9_PRIVATE sxi32 SyRandomness(SyPRNGCtx *pCtx, void *pBuf, sxu32 nLen) | ||
3725 | { | ||
3726 | unsigned char *zBuf = (unsigned char *)pBuf; | ||
3727 | unsigned char *zEnd = &zBuf[nLen]; | ||
3728 | #if defined(UNTRUST) | ||
3729 | if( pCtx == 0 || pBuf == 0 || nLen <= 0 ){ | ||
3730 | return SXERR_EMPTY; | ||
3731 | } | ||
3732 | #endif | ||
3733 | if(pCtx->nMagic != SXPRNG_MAGIC ){ | ||
3734 | return SXERR_CORRUPT; | ||
3735 | } | ||
3736 | for(;;){ | ||
3737 | if( zBuf >= zEnd ){break;} zBuf[0] = randomByte(pCtx); zBuf++; | ||
3738 | if( zBuf >= zEnd ){break;} zBuf[0] = randomByte(pCtx); zBuf++; | ||
3739 | if( zBuf >= zEnd ){break;} zBuf[0] = randomByte(pCtx); zBuf++; | ||
3740 | if( zBuf >= zEnd ){break;} zBuf[0] = randomByte(pCtx); zBuf++; | ||
3741 | } | ||
3742 | return SXRET_OK; | ||
3743 | } | ||
3744 | #ifndef JX9_DISABLE_BUILTIN_FUNC | ||
3745 | #ifndef JX9_DISABLE_HASH_FUNC | ||
3746 | /* SyRunTimeApi: sxhash.c */ | ||
3747 | /* | ||
3748 | * This code implements the MD5 message-digest algorithm. | ||
3749 | * The algorithm is due to Ron Rivest.This code was | ||
3750 | * written by Colin Plumb in 1993, no copyright is claimed. | ||
3751 | * This code is in the public domain; do with it what you wish. | ||
3752 | * | ||
3753 | * Equivalent code is available from RSA Data Security, Inc. | ||
3754 | * This code has been tested against that, and is equivalent, | ||
3755 | * except that you don't need to include two pages of legalese | ||
3756 | * with every copy. | ||
3757 | * | ||
3758 | * To compute the message digest of a chunk of bytes, declare an | ||
3759 | * MD5Context structure, pass it to MD5Init, call MD5Update as | ||
3760 | * needed on buffers full of bytes, and then call MD5Final, which | ||
3761 | * will fill a supplied 16-byte array with the digest. | ||
3762 | */ | ||
3763 | #define SX_MD5_BINSZ 16 | ||
3764 | #define SX_MD5_HEXSZ 32 | ||
3765 | /* | ||
3766 | * Note: this code is harmless on little-endian machines. | ||
3767 | */ | ||
3768 | static void byteReverse (unsigned char *buf, unsigned longs) | ||
3769 | { | ||
3770 | sxu32 t; | ||
3771 | do { | ||
3772 | t = (sxu32)((unsigned)buf[3]<<8 | buf[2]) << 16 | | ||
3773 | ((unsigned)buf[1]<<8 | buf[0]); | ||
3774 | *(sxu32*)buf = t; | ||
3775 | buf += 4; | ||
3776 | } while (--longs); | ||
3777 | } | ||
3778 | /* The four core functions - F1 is optimized somewhat */ | ||
3779 | |||
3780 | /* #define F1(x, y, z) (x & y | ~x & z) */ | ||
3781 | #ifdef F1 | ||
3782 | #undef F1 | ||
3783 | #endif | ||
3784 | #ifdef F2 | ||
3785 | #undef F2 | ||
3786 | #endif | ||
3787 | #ifdef F3 | ||
3788 | #undef F3 | ||
3789 | #endif | ||
3790 | #ifdef F4 | ||
3791 | #undef F4 | ||
3792 | #endif | ||
3793 | |||
3794 | #define F1(x, y, z) (z ^ (x & (y ^ z))) | ||
3795 | #define F2(x, y, z) F1(z, x, y) | ||
3796 | #define F3(x, y, z) (x ^ y ^ z) | ||
3797 | #define F4(x, y, z) (y ^ (x | ~z)) | ||
3798 | |||
3799 | /* This is the central step in the MD5 algorithm.*/ | ||
3800 | #define SX_MD5STEP(f, w, x, y, z, data, s) \ | ||
3801 | ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) | ||
3802 | |||
3803 | /* | ||
3804 | * The core of the MD5 algorithm, this alters an existing MD5 hash to | ||
3805 | * reflect the addition of 16 longwords of new data.MD5Update blocks | ||
3806 | * the data and converts bytes into longwords for this routine. | ||
3807 | */ | ||
3808 | static void MD5Transform(sxu32 buf[4], const sxu32 in[16]) | ||
3809 | { | ||
3810 | register sxu32 a, b, c, d; | ||
3811 | |||
3812 | a = buf[0]; | ||
3813 | b = buf[1]; | ||
3814 | c = buf[2]; | ||
3815 | d = buf[3]; | ||
3816 | |||
3817 | SX_MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); | ||
3818 | SX_MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); | ||
3819 | SX_MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); | ||
3820 | SX_MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); | ||
3821 | SX_MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); | ||
3822 | SX_MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); | ||
3823 | SX_MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); | ||
3824 | SX_MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); | ||
3825 | SX_MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); | ||
3826 | SX_MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); | ||
3827 | SX_MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); | ||
3828 | SX_MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); | ||
3829 | SX_MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); | ||
3830 | SX_MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); | ||
3831 | SX_MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); | ||
3832 | SX_MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); | ||
3833 | |||
3834 | SX_MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); | ||
3835 | SX_MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); | ||
3836 | SX_MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); | ||
3837 | SX_MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); | ||
3838 | SX_MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); | ||
3839 | SX_MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); | ||
3840 | SX_MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); | ||
3841 | SX_MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); | ||
3842 | SX_MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); | ||
3843 | SX_MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); | ||
3844 | SX_MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); | ||
3845 | SX_MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); | ||
3846 | SX_MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); | ||
3847 | SX_MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); | ||
3848 | SX_MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); | ||
3849 | SX_MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); | ||
3850 | |||
3851 | SX_MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); | ||
3852 | SX_MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); | ||
3853 | SX_MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); | ||
3854 | SX_MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); | ||
3855 | SX_MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); | ||
3856 | SX_MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); | ||
3857 | SX_MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); | ||
3858 | SX_MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); | ||
3859 | SX_MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); | ||
3860 | SX_MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); | ||
3861 | SX_MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); | ||
3862 | SX_MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); | ||
3863 | SX_MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); | ||
3864 | SX_MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); | ||
3865 | SX_MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); | ||
3866 | SX_MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); | ||
3867 | |||
3868 | SX_MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); | ||
3869 | SX_MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); | ||
3870 | SX_MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); | ||
3871 | SX_MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); | ||
3872 | SX_MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); | ||
3873 | SX_MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); | ||
3874 | SX_MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); | ||
3875 | SX_MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); | ||
3876 | SX_MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); | ||
3877 | SX_MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); | ||
3878 | SX_MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); | ||
3879 | SX_MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); | ||
3880 | SX_MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); | ||
3881 | SX_MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); | ||
3882 | SX_MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); | ||
3883 | SX_MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); | ||
3884 | |||
3885 | buf[0] += a; | ||
3886 | buf[1] += b; | ||
3887 | buf[2] += c; | ||
3888 | buf[3] += d; | ||
3889 | } | ||
3890 | /* | ||
3891 | * Update context to reflect the concatenation of another buffer full | ||
3892 | * of bytes. | ||
3893 | */ | ||
3894 | JX9_PRIVATE void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len) | ||
3895 | { | ||
3896 | sxu32 t; | ||
3897 | |||
3898 | /* Update bitcount */ | ||
3899 | t = ctx->bits[0]; | ||
3900 | if ((ctx->bits[0] = t + ((sxu32)len << 3)) < t) | ||
3901 | ctx->bits[1]++; /* Carry from low to high */ | ||
3902 | ctx->bits[1] += len >> 29; | ||
3903 | t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ | ||
3904 | /* Handle any leading odd-sized chunks */ | ||
3905 | if ( t ) { | ||
3906 | unsigned char *p = (unsigned char *)ctx->in + t; | ||
3907 | |||
3908 | t = 64-t; | ||
3909 | if (len < t) { | ||
3910 | SyMemcpy(buf, p, len); | ||
3911 | return; | ||
3912 | } | ||
3913 | SyMemcpy(buf, p, t); | ||
3914 | byteReverse(ctx->in, 16); | ||
3915 | MD5Transform(ctx->buf, (sxu32*)ctx->in); | ||
3916 | buf += t; | ||
3917 | len -= t; | ||
3918 | } | ||
3919 | /* Process data in 64-byte chunks */ | ||
3920 | while (len >= 64) { | ||
3921 | SyMemcpy(buf, ctx->in, 64); | ||
3922 | byteReverse(ctx->in, 16); | ||
3923 | MD5Transform(ctx->buf, (sxu32*)ctx->in); | ||
3924 | buf += 64; | ||
3925 | len -= 64; | ||
3926 | } | ||
3927 | /* Handle any remaining bytes of data.*/ | ||
3928 | SyMemcpy(buf, ctx->in, len); | ||
3929 | } | ||
3930 | /* | ||
3931 | * Final wrapup - pad to 64-byte boundary with the bit pattern | ||
3932 | * 1 0* (64-bit count of bits processed, MSB-first) | ||
3933 | */ | ||
3934 | JX9_PRIVATE void MD5Final(unsigned char digest[16], MD5Context *ctx){ | ||
3935 | unsigned count; | ||
3936 | unsigned char *p; | ||
3937 | |||
3938 | /* Compute number of bytes mod 64 */ | ||
3939 | count = (ctx->bits[0] >> 3) & 0x3F; | ||
3940 | |||
3941 | /* Set the first char of padding to 0x80.This is safe since there is | ||
3942 | always at least one byte free */ | ||
3943 | p = ctx->in + count; | ||
3944 | *p++ = 0x80; | ||
3945 | |||
3946 | /* Bytes of padding needed to make 64 bytes */ | ||
3947 | count = 64 - 1 - count; | ||
3948 | |||
3949 | /* Pad out to 56 mod 64 */ | ||
3950 | if (count < 8) { | ||
3951 | /* Two lots of padding: Pad the first block to 64 bytes */ | ||
3952 | SyZero(p, count); | ||
3953 | byteReverse(ctx->in, 16); | ||
3954 | MD5Transform(ctx->buf, (sxu32*)ctx->in); | ||
3955 | |||
3956 | /* Now fill the next block with 56 bytes */ | ||
3957 | SyZero(ctx->in, 56); | ||
3958 | } else { | ||
3959 | /* Pad block to 56 bytes */ | ||
3960 | SyZero(p, count-8); | ||
3961 | } | ||
3962 | byteReverse(ctx->in, 14); | ||
3963 | |||
3964 | /* Append length in bits and transform */ | ||
3965 | ((sxu32*)ctx->in)[ 14 ] = ctx->bits[0]; | ||
3966 | ((sxu32*)ctx->in)[ 15 ] = ctx->bits[1]; | ||
3967 | |||
3968 | MD5Transform(ctx->buf, (sxu32*)ctx->in); | ||
3969 | byteReverse((unsigned char *)ctx->buf, 4); | ||
3970 | SyMemcpy(ctx->buf, digest, 0x10); | ||
3971 | SyZero(ctx, sizeof(ctx)); /* In case it's sensitive */ | ||
3972 | } | ||
3973 | #undef F1 | ||
3974 | #undef F2 | ||
3975 | #undef F3 | ||
3976 | #undef F4 | ||
3977 | JX9_PRIVATE sxi32 MD5Init(MD5Context *pCtx) | ||
3978 | { | ||
3979 | pCtx->buf[0] = 0x67452301; | ||
3980 | pCtx->buf[1] = 0xefcdab89; | ||
3981 | pCtx->buf[2] = 0x98badcfe; | ||
3982 | pCtx->buf[3] = 0x10325476; | ||
3983 | pCtx->bits[0] = 0; | ||
3984 | pCtx->bits[1] = 0; | ||
3985 | |||
3986 | return SXRET_OK; | ||
3987 | } | ||
3988 | JX9_PRIVATE sxi32 SyMD5Compute(const void *pIn, sxu32 nLen, unsigned char zDigest[16]) | ||
3989 | { | ||
3990 | MD5Context sCtx; | ||
3991 | MD5Init(&sCtx); | ||
3992 | MD5Update(&sCtx, (const unsigned char *)pIn, nLen); | ||
3993 | MD5Final(zDigest, &sCtx); | ||
3994 | return SXRET_OK; | ||
3995 | } | ||
3996 | /* | ||
3997 | * SHA-1 in C | ||
3998 | * By Steve Reid <steve@edmweb.com> | ||
3999 | * Status: Public Domain | ||
4000 | */ | ||
4001 | /* | ||
4002 | * blk0() and blk() perform the initial expand. | ||
4003 | * I got the idea of expanding during the round function from SSLeay | ||
4004 | * | ||
4005 | * blk0le() for little-endian and blk0be() for big-endian. | ||
4006 | */ | ||
4007 | #if __GNUC__ && (defined(__i386__) || defined(__x86_64__)) | ||
4008 | /* | ||
4009 | * GCC by itself only generates left rotates. Use right rotates if | ||
4010 | * possible to be kinder to dinky implementations with iterative rotate | ||
4011 | * instructions. | ||
4012 | */ | ||
4013 | #define SHA_ROT(op, x, k) \ | ||
4014 | ({ unsigned int y; asm(op " %1, %0" : "=r" (y) : "I" (k), "0" (x)); y; }) | ||
4015 | #define rol(x, k) SHA_ROT("roll", x, k) | ||
4016 | #define ror(x, k) SHA_ROT("rorl", x, k) | ||
4017 | |||
4018 | #else | ||
4019 | /* Generic C equivalent */ | ||
4020 | #define SHA_ROT(x, l, r) ((x) << (l) | (x) >> (r)) | ||
4021 | #define rol(x, k) SHA_ROT(x, k, 32-(k)) | ||
4022 | #define ror(x, k) SHA_ROT(x, 32-(k), k) | ||
4023 | #endif | ||
4024 | |||
4025 | #define blk0le(i) (block[i] = (ror(block[i], 8)&0xFF00FF00) \ | ||
4026 | |(rol(block[i], 8)&0x00FF00FF)) | ||
4027 | #define blk0be(i) block[i] | ||
4028 | #define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \ | ||
4029 | ^block[(i+2)&15]^block[i&15], 1)) | ||
4030 | |||
4031 | /* | ||
4032 | * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 | ||
4033 | * | ||
4034 | * Rl0() for little-endian and Rb0() for big-endian. Endianness is | ||
4035 | * determined at run-time. | ||
4036 | */ | ||
4037 | #define Rl0(v, w, x, y, z, i) \ | ||
4038 | z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v, 5);w=ror(w, 2); | ||
4039 | #define Rb0(v, w, x, y, z, i) \ | ||
4040 | z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v, 5);w=ror(w, 2); | ||
4041 | #define R1(v, w, x, y, z, i) \ | ||
4042 | z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v, 5);w=ror(w, 2); | ||
4043 | #define R2(v, w, x, y, z, i) \ | ||
4044 | z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v, 5);w=ror(w, 2); | ||
4045 | #define R3(v, w, x, y, z, i) \ | ||
4046 | z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v, 5);w=ror(w, 2); | ||
4047 | #define R4(v, w, x, y, z, i) \ | ||
4048 | z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v, 5);w=ror(w, 2); | ||
4049 | |||
4050 | /* | ||
4051 | * Hash a single 512-bit block. This is the core of the algorithm. | ||
4052 | */ | ||
4053 | #define a qq[0] | ||
4054 | #define b qq[1] | ||
4055 | #define c qq[2] | ||
4056 | #define d qq[3] | ||
4057 | #define e qq[4] | ||
4058 | |||
4059 | static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]) | ||
4060 | { | ||
4061 | unsigned int qq[5]; /* a, b, c, d, e; */ | ||
4062 | static int one = 1; | ||
4063 | unsigned int block[16]; | ||
4064 | SyMemcpy(buffer, (void *)block, 64); | ||
4065 | SyMemcpy(state, qq, 5*sizeof(unsigned int)); | ||
4066 | |||
4067 | /* Copy context->state[] to working vars */ | ||
4068 | /* | ||
4069 | a = state[0]; | ||
4070 | b = state[1]; | ||
4071 | c = state[2]; | ||
4072 | d = state[3]; | ||
4073 | e = state[4]; | ||
4074 | */ | ||
4075 | |||
4076 | /* 4 rounds of 20 operations each. Loop unrolled. */ | ||
4077 | if( 1 == *(unsigned char*)&one ){ | ||
4078 | Rl0(a, b, c, d, e, 0); Rl0(e, a, b, c, d, 1); Rl0(d, e, a, b, c, 2); Rl0(c, d, e, a, b, 3); | ||
4079 | Rl0(b, c, d, e, a, 4); Rl0(a, b, c, d, e, 5); Rl0(e, a, b, c, d, 6); Rl0(d, e, a, b, c, 7); | ||
4080 | Rl0(c, d, e, a, b, 8); Rl0(b, c, d, e, a, 9); Rl0(a, b, c, d, e, 10); Rl0(e, a, b, c, d, 11); | ||
4081 | Rl0(d, e, a, b, c, 12); Rl0(c, d, e, a, b, 13); Rl0(b, c, d, e, a, 14); Rl0(a, b, c, d, e, 15); | ||
4082 | }else{ | ||
4083 | Rb0(a, b, c, d, e, 0); Rb0(e, a, b, c, d, 1); Rb0(d, e, a, b, c, 2); Rb0(c, d, e, a, b, 3); | ||
4084 | Rb0(b, c, d, e, a, 4); Rb0(a, b, c, d, e, 5); Rb0(e, a, b, c, d, 6); Rb0(d, e, a, b, c, 7); | ||
4085 | Rb0(c, d, e, a, b, 8); Rb0(b, c, d, e, a, 9); Rb0(a, b, c, d, e, 10); Rb0(e, a, b, c, d, 11); | ||
4086 | Rb0(d, e, a, b, c, 12); Rb0(c, d, e, a, b, 13); Rb0(b, c, d, e, a, 14); Rb0(a, b, c, d, e, 15); | ||
4087 | } | ||
4088 | R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19); | ||
4089 | R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23); | ||
4090 | R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27); | ||
4091 | R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31); | ||
4092 | R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35); | ||
4093 | R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39); | ||
4094 | R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43); | ||
4095 | R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47); | ||
4096 | R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51); | ||
4097 | R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55); | ||
4098 | R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59); | ||
4099 | R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63); | ||
4100 | R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67); | ||
4101 | R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71); | ||
4102 | R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75); | ||
4103 | R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79); | ||
4104 | |||
4105 | /* Add the working vars back into context.state[] */ | ||
4106 | state[0] += a; | ||
4107 | state[1] += b; | ||
4108 | state[2] += c; | ||
4109 | state[3] += d; | ||
4110 | state[4] += e; | ||
4111 | } | ||
4112 | #undef a | ||
4113 | #undef b | ||
4114 | #undef c | ||
4115 | #undef d | ||
4116 | #undef e | ||
4117 | /* | ||
4118 | * SHA1Init - Initialize new context | ||
4119 | */ | ||
4120 | JX9_PRIVATE void SHA1Init(SHA1Context *context){ | ||
4121 | /* SHA1 initialization constants */ | ||
4122 | context->state[0] = 0x67452301; | ||
4123 | context->state[1] = 0xEFCDAB89; | ||
4124 | context->state[2] = 0x98BADCFE; | ||
4125 | context->state[3] = 0x10325476; | ||
4126 | context->state[4] = 0xC3D2E1F0; | ||
4127 | context->count[0] = context->count[1] = 0; | ||
4128 | } | ||
4129 | /* | ||
4130 | * Run your data through this. | ||
4131 | */ | ||
4132 | JX9_PRIVATE void SHA1Update(SHA1Context *context, const unsigned char *data, unsigned int len){ | ||
4133 | unsigned int i, j; | ||
4134 | |||
4135 | j = context->count[0]; | ||
4136 | if ((context->count[0] += len << 3) < j) | ||
4137 | context->count[1] += (len>>29)+1; | ||
4138 | j = (j >> 3) & 63; | ||
4139 | if ((j + len) > 63) { | ||
4140 | (void)SyMemcpy(data, &context->buffer[j], (i = 64-j)); | ||
4141 | SHA1Transform(context->state, context->buffer); | ||
4142 | for ( ; i + 63 < len; i += 64) | ||
4143 | SHA1Transform(context->state, &data[i]); | ||
4144 | j = 0; | ||
4145 | } else { | ||
4146 | i = 0; | ||
4147 | } | ||
4148 | (void)SyMemcpy(&data[i], &context->buffer[j], len - i); | ||
4149 | } | ||
4150 | /* | ||
4151 | * Add padding and return the message digest. | ||
4152 | */ | ||
4153 | JX9_PRIVATE void SHA1Final(SHA1Context *context, unsigned char digest[20]){ | ||
4154 | unsigned int i; | ||
4155 | unsigned char finalcount[8]; | ||
4156 | |||
4157 | for (i = 0; i < 8; i++) { | ||
4158 | finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] | ||
4159 | >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ | ||
4160 | } | ||
4161 | SHA1Update(context, (const unsigned char *)"\200", 1); | ||
4162 | while ((context->count[0] & 504) != 448) | ||
4163 | SHA1Update(context, (const unsigned char *)"\0", 1); | ||
4164 | SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ | ||
4165 | |||
4166 | if (digest) { | ||
4167 | for (i = 0; i < 20; i++) | ||
4168 | digest[i] = (unsigned char) | ||
4169 | ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); | ||
4170 | } | ||
4171 | } | ||
4172 | #undef Rl0 | ||
4173 | #undef Rb0 | ||
4174 | #undef R1 | ||
4175 | #undef R2 | ||
4176 | #undef R3 | ||
4177 | #undef R4 | ||
4178 | |||
4179 | JX9_PRIVATE sxi32 SySha1Compute(const void *pIn, sxu32 nLen, unsigned char zDigest[20]) | ||
4180 | { | ||
4181 | SHA1Context sCtx; | ||
4182 | SHA1Init(&sCtx); | ||
4183 | SHA1Update(&sCtx, (const unsigned char *)pIn, nLen); | ||
4184 | SHA1Final(&sCtx, zDigest); | ||
4185 | return SXRET_OK; | ||
4186 | } | ||
4187 | static const sxu32 crc32_table[] = { | ||
4188 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, | ||
4189 | 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, | ||
4190 | 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, | ||
4191 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, | ||
4192 | 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, | ||
4193 | 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, | ||
4194 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, | ||
4195 | 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, | ||
4196 | 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, | ||
4197 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, | ||
4198 | 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, | ||
4199 | 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, | ||
4200 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, | ||
4201 | 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, | ||
4202 | 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, | ||
4203 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, | ||
4204 | 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, | ||
4205 | 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, | ||
4206 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, | ||
4207 | 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, | ||
4208 | 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, | ||
4209 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, | ||
4210 | 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, | ||
4211 | 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, | ||
4212 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, | ||
4213 | 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, | ||
4214 | 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, | ||
4215 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, | ||
4216 | 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, | ||
4217 | 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, | ||
4218 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, | ||
4219 | 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, | ||
4220 | 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, | ||
4221 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, | ||
4222 | 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, | ||
4223 | 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, | ||
4224 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, | ||
4225 | 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, | ||
4226 | 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, | ||
4227 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, | ||
4228 | 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, | ||
4229 | 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, | ||
4230 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, | ||
4231 | 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, | ||
4232 | 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, | ||
4233 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, | ||
4234 | 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, | ||
4235 | 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, | ||
4236 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, | ||
4237 | 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, | ||
4238 | 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, | ||
4239 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, | ||
4240 | 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, | ||
4241 | 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, | ||
4242 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, | ||
4243 | 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, | ||
4244 | 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, | ||
4245 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, | ||
4246 | 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, | ||
4247 | 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, | ||
4248 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, | ||
4249 | 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, | ||
4250 | 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, | ||
4251 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, | ||
4252 | }; | ||
4253 | #define CRC32C(c, d) (c = ( crc32_table[(c ^ (d)) & 0xFF] ^ (c>>8) ) ) | ||
4254 | static sxu32 SyCrc32Update(sxu32 crc32, const void *pSrc, sxu32 nLen) | ||
4255 | { | ||
4256 | register unsigned char *zIn = (unsigned char *)pSrc; | ||
4257 | unsigned char *zEnd; | ||
4258 | if( zIn == 0 ){ | ||
4259 | return crc32; | ||
4260 | } | ||
4261 | zEnd = &zIn[nLen]; | ||
4262 | for(;;){ | ||
4263 | if(zIn >= zEnd ){ break; } CRC32C(crc32, zIn[0]); zIn++; | ||
4264 | if(zIn >= zEnd ){ break; } CRC32C(crc32, zIn[0]); zIn++; | ||
4265 | if(zIn >= zEnd ){ break; } CRC32C(crc32, zIn[0]); zIn++; | ||
4266 | if(zIn >= zEnd ){ break; } CRC32C(crc32, zIn[0]); zIn++; | ||
4267 | } | ||
4268 | |||
4269 | return crc32; | ||
4270 | } | ||
4271 | JX9_PRIVATE sxu32 SyCrc32(const void *pSrc, sxu32 nLen) | ||
4272 | { | ||
4273 | return SyCrc32Update(SXU32_HIGH, pSrc, nLen); | ||
4274 | } | ||
4275 | #endif /* JX9_DISABLE_HASH_FUNC */ | ||
4276 | #endif /* JX9_DISABLE_BUILTIN_FUNC */ | ||
4277 | #ifndef JX9_DISABLE_BUILTIN_FUNC | ||
4278 | JX9_PRIVATE sxi32 SyBinToHexConsumer(const void *pIn, sxu32 nLen, ProcConsumer xConsumer, void *pConsumerData) | ||
4279 | { | ||
4280 | static const unsigned char zHexTab[] = "0123456789abcdef"; | ||
4281 | const unsigned char *zIn, *zEnd; | ||
4282 | unsigned char zOut[3]; | ||
4283 | sxi32 rc; | ||
4284 | #if defined(UNTRUST) | ||
4285 | if( pIn == 0 || xConsumer == 0 ){ | ||
4286 | return SXERR_EMPTY; | ||
4287 | } | ||
4288 | #endif | ||
4289 | zIn = (const unsigned char *)pIn; | ||
4290 | zEnd = &zIn[nLen]; | ||
4291 | for(;;){ | ||
4292 | if( zIn >= zEnd ){ | ||
4293 | break; | ||
4294 | } | ||
4295 | zOut[0] = zHexTab[zIn[0] >> 4]; zOut[1] = zHexTab[zIn[0] & 0x0F]; | ||
4296 | rc = xConsumer((const void *)zOut, sizeof(char)*2, pConsumerData); | ||
4297 | if( rc != SXRET_OK ){ | ||
4298 | return rc; | ||
4299 | } | ||
4300 | zIn++; | ||
4301 | } | ||
4302 | return SXRET_OK; | ||
4303 | } | ||
4304 | #endif /* JX9_DISABLE_BUILTIN_FUNC */ | ||
4305 | JX9_PRIVATE void SyBigEndianPack32(unsigned char *buf,sxu32 nb) | ||
4306 | { | ||
4307 | buf[3] = nb & 0xFF ; nb >>=8; | ||
4308 | buf[2] = nb & 0xFF ; nb >>=8; | ||
4309 | buf[1] = nb & 0xFF ; nb >>=8; | ||
4310 | buf[0] = (unsigned char)nb ; | ||
4311 | } | ||
4312 | JX9_PRIVATE void SyBigEndianUnpack32(const unsigned char *buf,sxu32 *uNB) | ||
4313 | { | ||
4314 | *uNB = buf[3] + (buf[2] << 8) + (buf[1] << 16) + (buf[0] << 24); | ||
4315 | } | ||
4316 | JX9_PRIVATE void SyBigEndianPack16(unsigned char *buf,sxu16 nb) | ||
4317 | { | ||
4318 | buf[1] = nb & 0xFF ; nb >>=8; | ||
4319 | buf[0] = (unsigned char)nb ; | ||
4320 | } | ||
4321 | JX9_PRIVATE void SyBigEndianUnpack16(const unsigned char *buf,sxu16 *uNB) | ||
4322 | { | ||
4323 | *uNB = buf[1] + (buf[0] << 8); | ||
4324 | } | ||
4325 | JX9_PRIVATE void SyBigEndianPack64(unsigned char *buf,sxu64 n64) | ||
4326 | { | ||
4327 | buf[7] = n64 & 0xFF; n64 >>=8; | ||
4328 | buf[6] = n64 & 0xFF; n64 >>=8; | ||
4329 | buf[5] = n64 & 0xFF; n64 >>=8; | ||
4330 | buf[4] = n64 & 0xFF; n64 >>=8; | ||
4331 | buf[3] = n64 & 0xFF; n64 >>=8; | ||
4332 | buf[2] = n64 & 0xFF; n64 >>=8; | ||
4333 | buf[1] = n64 & 0xFF; n64 >>=8; | ||
4334 | buf[0] = (sxu8)n64 ; | ||
4335 | } | ||
4336 | JX9_PRIVATE void SyBigEndianUnpack64(const unsigned char *buf,sxu64 *n64) | ||
4337 | { | ||
4338 | sxu32 u1,u2; | ||
4339 | u1 = buf[7] + (buf[6] << 8) + (buf[5] << 16) + (buf[4] << 24); | ||
4340 | u2 = buf[3] + (buf[2] << 8) + (buf[1] << 16) + (buf[0] << 24); | ||
4341 | *n64 = (((sxu64)u2) << 32) | u1; | ||
4342 | } | ||
4343 | JX9_PRIVATE sxi32 SyBlobAppendBig64(SyBlob *pBlob,sxu64 n64) | ||
4344 | { | ||
4345 | unsigned char zBuf[8]; | ||
4346 | sxi32 rc; | ||
4347 | SyBigEndianPack64(zBuf,n64); | ||
4348 | rc = SyBlobAppend(pBlob,(const void *)zBuf,sizeof(zBuf)); | ||
4349 | return rc; | ||
4350 | } | ||
4351 | JX9_PRIVATE sxi32 SyBlobAppendBig32(SyBlob *pBlob,sxu32 n32) | ||
4352 | { | ||
4353 | unsigned char zBuf[4]; | ||
4354 | sxi32 rc; | ||
4355 | SyBigEndianPack32(zBuf,n32); | ||
4356 | rc = SyBlobAppend(pBlob,(const void *)zBuf,sizeof(zBuf)); | ||
4357 | return rc; | ||
4358 | } | ||
4359 | JX9_PRIVATE sxi32 SyBlobAppendBig16(SyBlob *pBlob,sxu16 n16) | ||
4360 | { | ||
4361 | unsigned char zBuf[2]; | ||
4362 | sxi32 rc; | ||
4363 | SyBigEndianPack16(zBuf,n16); | ||
4364 | rc = SyBlobAppend(pBlob,(const void *)zBuf,sizeof(zBuf)); | ||
4365 | return rc; | ||
4366 | } | ||
4367 | JX9_PRIVATE void SyTimeFormatToDos(Sytm *pFmt,sxu32 *pOut) | ||
4368 | { | ||
4369 | sxi32 nDate,nTime; | ||
4370 | nDate = ((pFmt->tm_year - 1980) << 9) + (pFmt->tm_mon << 5) + pFmt->tm_mday; | ||
4371 | nTime = (pFmt->tm_hour << 11) + (pFmt->tm_min << 5)+ (pFmt->tm_sec >> 1); | ||
4372 | *pOut = (nDate << 16) | nTime; | ||
4373 | } | ||
4374 | JX9_PRIVATE void SyDosTimeFormat(sxu32 nDosDate, Sytm *pOut) | ||
4375 | { | ||
4376 | sxu16 nDate; | ||
4377 | sxu16 nTime; | ||
4378 | nDate = nDosDate >> 16; | ||
4379 | nTime = nDosDate & 0xFFFF; | ||
4380 | pOut->tm_isdst = 0; | ||
4381 | pOut->tm_year = 1980 + (nDate >> 9); | ||
4382 | pOut->tm_mon = (nDate % (1<<9))>>5; | ||
4383 | pOut->tm_mday = (nDate % (1<<9))&0x1F; | ||
4384 | pOut->tm_hour = nTime >> 11; | ||
4385 | pOut->tm_min = (nTime % (1<<11)) >> 5; | ||
4386 | pOut->tm_sec = ((nTime % (1<<11))& 0x1F )<<1; | ||
4387 | } | ||