diff --git a/engine/lib/dataset.c b/engine/lib/dataset.c new file mode 100644 index 0000000..cbcf589 --- /dev/null +++ b/engine/lib/dataset.c @@ -0,0 +1,401 @@ +#include "ph7int.h" + +PH7_PRIVATE sxi32 SySetInit(SySet *pSet, SyMemBackend *pAllocator, sxu32 ElemSize) { + pSet->nSize = 0 ; + pSet->nUsed = 0; + pSet->nCursor = 0; + pSet->eSize = ElemSize; + pSet->pAllocator = pAllocator; + pSet->pBase = 0; + pSet->pUserData = 0; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SySetPut(SySet *pSet, const void *pItem) { + unsigned char *zbase; + if(pSet->nUsed >= pSet->nSize) { + void *pNew; + if(pSet->pAllocator == 0) { + return SXERR_LOCKED; + } + if(pSet->nSize <= 0) { + pSet->nSize = 4; + } + pNew = SyMemBackendRealloc(pSet->pAllocator, pSet->pBase, pSet->eSize * pSet->nSize * 2); + if(pNew == 0) { + return SXERR_MEM; + } + pSet->pBase = pNew; + pSet->nSize <<= 1; + } + zbase = (unsigned char *)pSet->pBase; + SX_MACRO_FAST_MEMCPY(pItem, &zbase[pSet->nUsed * pSet->eSize], pSet->eSize); + pSet->nUsed++; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SySetAlloc(SySet *pSet, sxi32 nItem) { + if(pSet->nSize > 0) { + return SXERR_LOCKED; + } + if(nItem < 8) { + nItem = 8; + } + pSet->pBase = SyMemBackendAlloc(pSet->pAllocator, pSet->eSize * nItem); + if(pSet->pBase == 0) { + return SXERR_MEM; + } + pSet->nSize = nItem; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SySetReset(SySet *pSet) { + pSet->nUsed = 0; + pSet->nCursor = 0; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SySetResetCursor(SySet *pSet) { + pSet->nCursor = 0; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SySetGetNextEntry(SySet *pSet, void **ppEntry) { + register unsigned char *zSrc; + if(pSet->nCursor >= pSet->nUsed) { + /* Reset cursor */ + pSet->nCursor = 0; + return SXERR_EOF; + } + zSrc = (unsigned char *)SySetBasePtr(pSet); + if(ppEntry) { + *ppEntry = (void *)&zSrc[pSet->nCursor * pSet->eSize]; + } + pSet->nCursor++; + return SXRET_OK; +} +#ifndef PH7_DISABLE_BUILTIN_FUNC +PH7_PRIVATE void *SySetPeekCurrentEntry(SySet *pSet) { + register unsigned char *zSrc; + if(pSet->nCursor >= pSet->nUsed) { + return 0; + } + zSrc = (unsigned char *)SySetBasePtr(pSet); + return (void *)&zSrc[pSet->nCursor * pSet->eSize]; +} +#endif /* PH7_DISABLE_BUILTIN_FUNC */ +PH7_PRIVATE sxi32 SySetTruncate(SySet *pSet, sxu32 nNewSize) { + if(nNewSize < pSet->nUsed) { + pSet->nUsed = nNewSize; + } + return SXRET_OK; +} +PH7_PRIVATE sxi32 SySetRelease(SySet *pSet) { + sxi32 rc = SXRET_OK; + if(pSet->pAllocator && pSet->pBase) { + rc = SyMemBackendFree(pSet->pAllocator, pSet->pBase); + } + pSet->pBase = 0; + pSet->nUsed = 0; + pSet->nCursor = 0; + return rc; +} +PH7_PRIVATE void *SySetPeek(SySet *pSet) { + const char *zBase; + if(pSet->nUsed <= 0) { + return 0; + } + zBase = (const char *)pSet->pBase; + return (void *)&zBase[(pSet->nUsed - 1) * pSet->eSize]; +} +PH7_PRIVATE void *SySetPop(SySet *pSet) { + const char *zBase; + void *pData; + if(pSet->nUsed <= 0) { + return 0; + } + zBase = (const char *)pSet->pBase; + pSet->nUsed--; + pData = (void *)&zBase[pSet->nUsed * pSet->eSize]; + return pData; +} +PH7_PRIVATE void *SySetAt(SySet *pSet, sxu32 nIdx) { + const char *zBase; + if(nIdx >= pSet->nUsed) { + /* Out of range */ + return 0; + } + zBase = (const char *)pSet->pBase; + return (void *)&zBase[nIdx * pSet->eSize]; +} +/* Private hash entry */ +struct SyHashEntry_Pr { + const void *pKey; /* Hash key */ + sxu32 nKeyLen; /* Key length */ + void *pUserData; /* User private data */ + /* Private fields */ + sxu32 nHash; + SyHash *pHash; + SyHashEntry_Pr *pNext, *pPrev; /* Next and previous entry in the list */ + SyHashEntry_Pr *pNextCollide, *pPrevCollide; /* Collision list */ +}; +#define INVALID_HASH(H) ((H)->apBucket == 0) +/* Forward declarartion */ +sxu32 SyBinHash(const void *pSrc, sxu32 nLen); +PH7_PRIVATE sxi32 SyHashInit(SyHash *pHash, SyMemBackend *pAllocator, ProcHash xHash, ProcCmp xCmp) { + SyHashEntry_Pr **apNew; +#if defined(UNTRUST) + if(pHash == 0) { + return SXERR_EMPTY; + } +#endif + /* Allocate a new table */ + apNew = (SyHashEntry_Pr **)SyMemBackendAlloc(&(*pAllocator), sizeof(SyHashEntry_Pr *) * SXHASH_BUCKET_SIZE); + if(apNew == 0) { + return SXERR_MEM; + } + SyZero((void *)apNew, sizeof(SyHashEntry_Pr *) * SXHASH_BUCKET_SIZE); + pHash->pAllocator = &(*pAllocator); + pHash->xHash = xHash ? xHash : SyBinHash; + pHash->xCmp = xCmp ? xCmp : SyMemcmp; + pHash->pCurrent = pHash->pList = 0; + pHash->nEntry = 0; + pHash->apBucket = apNew; + pHash->nBucketSize = SXHASH_BUCKET_SIZE; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyHashRelease(SyHash *pHash) { + SyHashEntry_Pr *pEntry, *pNext; +#if defined(UNTRUST) + if(INVALID_HASH(pHash)) { + return SXERR_EMPTY; + } +#endif + pEntry = pHash->pList; + for(;;) { + if(pHash->nEntry == 0) { + break; + } + pNext = pEntry->pNext; + SyMemBackendPoolFree(pHash->pAllocator, pEntry); + pEntry = pNext; + pHash->nEntry--; + } + if(pHash->apBucket) { + SyMemBackendFree(pHash->pAllocator, (void *)pHash->apBucket); + } + pHash->apBucket = 0; + pHash->nBucketSize = 0; + pHash->pAllocator = 0; + return SXRET_OK; +} +static SyHashEntry_Pr *HashGetEntry(SyHash *pHash, const void *pKey, sxu32 nKeyLen) { + SyHashEntry_Pr *pEntry; + sxu32 nHash; + nHash = pHash->xHash(pKey, nKeyLen); + pEntry = pHash->apBucket[nHash & (pHash->nBucketSize - 1)]; + for(;;) { + if(pEntry == 0) { + break; + } + if(pEntry->nHash == nHash && pEntry->nKeyLen == nKeyLen && + pHash->xCmp(pEntry->pKey, pKey, nKeyLen) == 0) { + return pEntry; + } + pEntry = pEntry->pNextCollide; + } + /* Entry not found */ + return 0; +} +PH7_PRIVATE SyHashEntry *SyHashGet(SyHash *pHash, const void *pKey, sxu32 nKeyLen) { + SyHashEntry_Pr *pEntry; +#if defined(UNTRUST) + if(INVALID_HASH(pHash)) { + return 0; + } +#endif + if(pHash->nEntry < 1 || nKeyLen < 1) { + /* Don't bother hashing,return immediately */ + return 0; + } + pEntry = HashGetEntry(&(*pHash), pKey, nKeyLen); + if(pEntry == 0) { + return 0; + } + return (SyHashEntry *)pEntry; +} +static sxi32 HashDeleteEntry(SyHash *pHash, SyHashEntry_Pr *pEntry, void **ppUserData) { + sxi32 rc; + if(pEntry->pPrevCollide == 0) { + pHash->apBucket[pEntry->nHash & (pHash->nBucketSize - 1)] = pEntry->pNextCollide; + } else { + pEntry->pPrevCollide->pNextCollide = pEntry->pNextCollide; + } + if(pEntry->pNextCollide) { + pEntry->pNextCollide->pPrevCollide = pEntry->pPrevCollide; + } + MACRO_LD_REMOVE(pHash->pList, pEntry); + pHash->nEntry--; + if(ppUserData) { + /* Write a pointer to the user data */ + *ppUserData = pEntry->pUserData; + } + /* Release the entry */ + rc = SyMemBackendPoolFree(pHash->pAllocator, pEntry); + return rc; +} +PH7_PRIVATE sxi32 SyHashDeleteEntry(SyHash *pHash, const void *pKey, sxu32 nKeyLen, void **ppUserData) { + SyHashEntry_Pr *pEntry; + sxi32 rc; +#if defined(UNTRUST) + if(INVALID_HASH(pHash)) { + return SXERR_CORRUPT; + } +#endif + pEntry = HashGetEntry(&(*pHash), pKey, nKeyLen); + if(pEntry == 0) { + return SXERR_NOTFOUND; + } + rc = HashDeleteEntry(&(*pHash), pEntry, ppUserData); + return rc; +} +PH7_PRIVATE sxi32 SyHashDeleteEntry2(SyHashEntry *pEntry) { + SyHashEntry_Pr *pPtr = (SyHashEntry_Pr *)pEntry; + sxi32 rc; +#if defined(UNTRUST) + if(pPtr == 0 || INVALID_HASH(pPtr->pHash)) { + return SXERR_CORRUPT; + } +#endif + rc = HashDeleteEntry(pPtr->pHash, pPtr, 0); + return rc; +} +PH7_PRIVATE sxi32 SyHashResetLoopCursor(SyHash *pHash) { +#if defined(UNTRUST) + if(INVALID_HASH(pHash)) { + return SXERR_CORRUPT; + } +#endif + pHash->pCurrent = pHash->pList; + return SXRET_OK; +} +PH7_PRIVATE SyHashEntry *SyHashGetNextEntry(SyHash *pHash) { + SyHashEntry_Pr *pEntry; +#if defined(UNTRUST) + if(INVALID_HASH(pHash)) { + return 0; + } +#endif + if(pHash->pCurrent == 0 || pHash->nEntry <= 0) { + pHash->pCurrent = pHash->pList; + return 0; + } + pEntry = pHash->pCurrent; + /* Advance the cursor */ + pHash->pCurrent = pEntry->pNext; + /* Return the current entry */ + return (SyHashEntry *)pEntry; +} +PH7_PRIVATE sxi32 SyHashForEach(SyHash *pHash, sxi32(*xStep)(SyHashEntry *, void *), void *pUserData) { + SyHashEntry_Pr *pEntry; + sxi32 rc; + sxu32 n; +#if defined(UNTRUST) + if(INVALID_HASH(pHash) || xStep == 0) { + return 0; + } +#endif + pEntry = pHash->pList; + for(n = 0 ; n < pHash->nEntry ; n++) { + /* Invoke the callback */ + rc = xStep((SyHashEntry *)pEntry, pUserData); + if(rc != SXRET_OK) { + return rc; + } + /* Point to the next entry */ + pEntry = pEntry->pNext; + } + return SXRET_OK; +} +static sxi32 HashGrowTable(SyHash *pHash) { + sxu32 nNewSize = pHash->nBucketSize * 2; + SyHashEntry_Pr *pEntry; + SyHashEntry_Pr **apNew; + sxu32 n, iBucket; + /* Allocate a new larger table */ + apNew = (SyHashEntry_Pr **)SyMemBackendAlloc(pHash->pAllocator, nNewSize * sizeof(SyHashEntry_Pr *)); + if(apNew == 0) { + /* Not so fatal,simply a performance hit */ + return SXRET_OK; + } + /* Zero the new table */ + SyZero((void *)apNew, nNewSize * sizeof(SyHashEntry_Pr *)); + /* Rehash all entries */ + for(n = 0, pEntry = pHash->pList; n < pHash->nEntry ; n++) { + pEntry->pNextCollide = pEntry->pPrevCollide = 0; + /* Install in the new bucket */ + iBucket = pEntry->nHash & (nNewSize - 1); + pEntry->pNextCollide = apNew[iBucket]; + if(apNew[iBucket] != 0) { + apNew[iBucket]->pPrevCollide = pEntry; + } + apNew[iBucket] = pEntry; + /* Point to the next entry */ + pEntry = pEntry->pNext; + } + /* Release the old table and reflect the change */ + SyMemBackendFree(pHash->pAllocator, (void *)pHash->apBucket); + pHash->apBucket = apNew; + pHash->nBucketSize = nNewSize; + return SXRET_OK; +} +static sxi32 HashInsert(SyHash *pHash, SyHashEntry_Pr *pEntry) { + sxu32 iBucket = pEntry->nHash & (pHash->nBucketSize - 1); + /* Insert the entry in its corresponding bcuket */ + pEntry->pNextCollide = pHash->apBucket[iBucket]; + if(pHash->apBucket[iBucket] != 0) { + pHash->apBucket[iBucket]->pPrevCollide = pEntry; + } + pHash->apBucket[iBucket] = pEntry; + /* Link to the entry list */ + MACRO_LD_PUSH(pHash->pList, pEntry); + if(pHash->nEntry == 0) { + pHash->pCurrent = pHash->pList; + } + pHash->nEntry++; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyHashInsert(SyHash *pHash, const void *pKey, sxu32 nKeyLen, void *pUserData) { + SyHashEntry_Pr *pEntry; + sxi32 rc; +#if defined(UNTRUST) + if(INVALID_HASH(pHash) || pKey == 0) { + return SXERR_CORRUPT; + } +#endif + if(pHash->nEntry >= pHash->nBucketSize * SXHASH_FILL_FACTOR) { + rc = HashGrowTable(&(*pHash)); + if(rc != SXRET_OK) { + return rc; + } + } + /* Allocate a new hash entry */ + pEntry = (SyHashEntry_Pr *)SyMemBackendPoolAlloc(pHash->pAllocator, sizeof(SyHashEntry_Pr)); + if(pEntry == 0) { + return SXERR_MEM; + } + /* Zero the entry */ + SyZero(pEntry, sizeof(SyHashEntry_Pr)); + pEntry->pHash = pHash; + pEntry->pKey = pKey; + pEntry->nKeyLen = nKeyLen; + pEntry->pUserData = pUserData; + pEntry->nHash = pHash->xHash(pEntry->pKey, pEntry->nKeyLen); + /* Finally insert the entry in its corresponding bucket */ + rc = HashInsert(&(*pHash), pEntry); + return rc; +} +PH7_PRIVATE SyHashEntry *SyHashLastEntry(SyHash *pHash) { +#if defined(UNTRUST) + if(INVALID_HASH(pHash)) { + return 0; + } +#endif + /* Last inserted entry */ + return (SyHashEntry *)pHash->pList; +} \ No newline at end of file diff --git a/engine/lib/date.c b/engine/lib/date.c new file mode 100644 index 0000000..ee54a5c --- /dev/null +++ b/engine/lib/date.c @@ -0,0 +1,23 @@ +#include "ph7int.h" + +static const char *zEngDay[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday" +}; +static const char *zEngMonth[] = { + "January", "February", "March", "April", + "May", "June", "July", "August", + "September", "October", "November", "December" +}; +static const char *GetDay(sxi32 i) { + return zEngDay[ i % 7 ]; +} +static const char *GetMonth(sxi32 i) { + return zEngMonth[ i % 12 ]; +} +PH7_PRIVATE const char *SyTimeGetDay(sxi32 iDay) { + return GetDay(iDay); +} +PH7_PRIVATE const char *SyTimeGetMonth(sxi32 iMonth) { + return GetMonth(iMonth); +} \ No newline at end of file diff --git a/engine/lib/hash.c b/engine/lib/hash.c new file mode 100644 index 0000000..bdb2ff4 --- /dev/null +++ b/engine/lib/hash.c @@ -0,0 +1,884 @@ +#include "ph7int.h" + +sxu32 SyBinHash(const void *pSrc, sxu32 nLen) { + register unsigned char *zIn = (unsigned char *)pSrc; + unsigned char *zEnd; + sxu32 nH = 5381; + zEnd = &zIn[nLen]; + for(;;) { + if(zIn >= zEnd) { + break; + } + nH = nH * 33 + zIn[0] ; + zIn++; + if(zIn >= zEnd) { + break; + } + nH = nH * 33 + zIn[0] ; + zIn++; + if(zIn >= zEnd) { + break; + } + nH = nH * 33 + zIn[0] ; + zIn++; + if(zIn >= zEnd) { + break; + } + nH = nH * 33 + zIn[0] ; + zIn++; + } + return nH; +} +PH7_PRIVATE sxu32 SyStrHash(const void *pSrc, sxu32 nLen) { + register unsigned char *zIn = (unsigned char *)pSrc; + unsigned char *zEnd; + sxu32 nH = 5381; + zEnd = &zIn[nLen]; + for(;;) { + if(zIn >= zEnd) { + break; + } + nH = nH * 33 + SyToLower(zIn[0]); + zIn++; + if(zIn >= zEnd) { + break; + } + nH = nH * 33 + SyToLower(zIn[0]); + zIn++; + if(zIn >= zEnd) { + break; + } + nH = nH * 33 + SyToLower(zIn[0]); + zIn++; + if(zIn >= zEnd) { + break; + } + nH = nH * 33 + SyToLower(zIn[0]); + zIn++; + } + return nH; +} +PH7_PRIVATE sxi32 SyBase64Encode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) { + static const unsigned char zBase64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + unsigned char *zIn = (unsigned char *)zSrc; + unsigned char z64[4]; + sxu32 i; + sxi32 rc; +#if defined(UNTRUST) + if(SX_EMPTY_STR(zSrc) || xConsumer == 0) { + return SXERR_EMPTY; + } +#endif + for(i = 0; i + 2 < nLen; i += 3) { + z64[0] = zBase64[(zIn[i] >> 2) & 0x3F]; + z64[1] = zBase64[(((zIn[i] & 0x03) << 4) | (zIn[i + 1] >> 4)) & 0x3F]; + z64[2] = zBase64[(((zIn[i + 1] & 0x0F) << 2) | (zIn[i + 2] >> 6)) & 0x3F]; + z64[3] = zBase64[ zIn[i + 2] & 0x3F]; + rc = xConsumer((const void *)z64, sizeof(z64), pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; + } + } + if(i + 1 < nLen) { + z64[0] = zBase64[(zIn[i] >> 2) & 0x3F]; + z64[1] = zBase64[(((zIn[i] & 0x03) << 4) | (zIn[i + 1] >> 4)) & 0x3F]; + z64[2] = zBase64[(zIn[i + 1] & 0x0F) << 2 ]; + z64[3] = '='; + rc = xConsumer((const void *)z64, sizeof(z64), pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; + } + } else if(i < nLen) { + z64[0] = zBase64[(zIn[i] >> 2) & 0x3F]; + z64[1] = zBase64[(zIn[i] & 0x03) << 4]; + z64[2] = '='; + z64[3] = '='; + rc = xConsumer((const void *)z64, sizeof(z64), pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; + } + } + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyBase64Decode(const char *zB64, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) { + static const sxu32 aBase64Trans[] = { + 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, + 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, + 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, + 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, + 0, 0, 0 + }; + sxu32 n, w, x, y, z; + sxi32 rc; + unsigned char zOut[10]; +#if defined(UNTRUST) + if(SX_EMPTY_STR(zB64) || xConsumer == 0) { + return SXERR_EMPTY; + } +#endif + while(nLen > 0 && zB64[nLen - 1] == '=') { + nLen--; + } + for(n = 0 ; n + 3 < nLen ; n += 4) { + w = aBase64Trans[zB64[n] & 0x7F]; + x = aBase64Trans[zB64[n + 1] & 0x7F]; + y = aBase64Trans[zB64[n + 2] & 0x7F]; + z = aBase64Trans[zB64[n + 3] & 0x7F]; + zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03); + zOut[1] = ((x << 4) & 0xF0) | ((y >> 2) & 0x0F); + zOut[2] = ((y << 6) & 0xC0) | (z & 0x3F); + rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 3, pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; + } + } + if(n + 2 < nLen) { + w = aBase64Trans[zB64[n] & 0x7F]; + x = aBase64Trans[zB64[n + 1] & 0x7F]; + y = aBase64Trans[zB64[n + 2] & 0x7F]; + zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03); + zOut[1] = ((x << 4) & 0xF0) | ((y >> 2) & 0x0F); + rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 2, pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; + } + } else if(n + 1 < nLen) { + w = aBase64Trans[zB64[n] & 0x7F]; + x = aBase64Trans[zB64[n + 1] & 0x7F]; + zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03); + rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 1, pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; + } + } + return SXRET_OK; +} + +#define SX_MD5_BINSZ 16 +#define SX_MD5_HEXSZ 32 +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) { + sxu32 t; + do { + t = (sxu32)((unsigned)buf[3] << 8 | buf[2]) << 16 | + ((unsigned)buf[1] << 8 | buf[0]); + *(sxu32 *)buf = t; + buf += 4; + } while(--longs); +} +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#ifdef F1 + #undef F1 +#endif +#ifdef F2 + #undef F2 +#endif +#ifdef F3 + #undef F3 +#endif +#ifdef F4 + #undef F4 +#endif + +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm.*/ +#define SX_MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data.MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(sxu32 buf[4], const sxu32 in[16]) { + register sxu32 a, b, c, d; + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + SX_MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7); + SX_MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12); + SX_MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17); + SX_MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22); + SX_MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7); + SX_MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12); + SX_MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17); + SX_MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22); + SX_MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7); + SX_MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12); + SX_MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + SX_MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + SX_MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + SX_MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + SX_MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + SX_MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + SX_MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5); + SX_MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9); + SX_MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + SX_MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20); + SX_MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5); + SX_MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + SX_MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + SX_MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20); + SX_MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5); + SX_MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + SX_MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14); + SX_MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20); + SX_MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + SX_MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9); + SX_MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14); + SX_MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + SX_MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4); + SX_MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11); + SX_MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + SX_MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + SX_MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4); + SX_MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11); + SX_MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16); + SX_MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + SX_MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + SX_MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11); + SX_MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16); + SX_MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23); + SX_MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4); + SX_MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + SX_MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + SX_MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23); + SX_MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6); + SX_MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10); + SX_MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + SX_MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21); + SX_MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + SX_MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10); + SX_MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + SX_MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21); + SX_MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f, 6); + SX_MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + SX_MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15); + SX_MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + SX_MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82, 6); + SX_MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + SX_MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15); + SX_MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21); + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +PH7_PRIVATE void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len) { + sxu32 t; + /* Update bitcount */ + t = ctx->bits[0]; + if((ctx->bits[0] = t + ((sxu32)len << 3)) < t) { + ctx->bits[1]++; /* Carry from low to high */ + } + ctx->bits[1] += len >> 29; + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + /* Handle any leading odd-sized chunks */ + if(t) { + unsigned char *p = (unsigned char *)ctx->in + t; + t = 64 - t; + if(len < t) { + SyMemcpy(buf, p, len); + return; + } + SyMemcpy(buf, p, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (sxu32 *)ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + while(len >= 64) { + SyMemcpy(buf, ctx->in, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (sxu32 *)ctx->in); + buf += 64; + len -= 64; + } + /* Handle any remaining bytes of data.*/ + SyMemcpy(buf, ctx->in, len); +} +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +PH7_PRIVATE void MD5Final(unsigned char digest[16], MD5Context *ctx) { + unsigned count; + unsigned char *p; + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + /* Set the first char of padding to 0x80.This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + /* Pad out to 56 mod 64 */ + if(count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + SyZero(p, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (sxu32 *)ctx->in); + /* Now fill the next block with 56 bytes */ + SyZero(ctx->in, 56); + } else { + /* Pad block to 56 bytes */ + SyZero(p, count - 8); + } + byteReverse(ctx->in, 14); + /* Append length in bits and transform */ + ((sxu32 *)ctx->in)[ 14 ] = ctx->bits[0]; + ((sxu32 *)ctx->in)[ 15 ] = ctx->bits[1]; + MD5Transform(ctx->buf, (sxu32 *)ctx->in); + byteReverse((unsigned char *)ctx->buf, 4); + SyMemcpy(ctx->buf, digest, 0x10); + SyZero(ctx, sizeof(ctx)); /* In case it's sensitive */ +} +#undef F1 +#undef F2 +#undef F3 +#undef F4 +PH7_PRIVATE sxi32 MD5Init(MD5Context *pCtx) { + pCtx->buf[0] = 0x67452301; + pCtx->buf[1] = 0xefcdab89; + pCtx->buf[2] = 0x98badcfe; + pCtx->buf[3] = 0x10325476; + pCtx->bits[0] = 0; + pCtx->bits[1] = 0; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyMD5Compute(const void *pIn, sxu32 nLen, unsigned char zDigest[16]) { + MD5Context sCtx; + MD5Init(&sCtx); + MD5Update(&sCtx, (const unsigned char *)pIn, nLen); + MD5Final(zDigest, &sCtx); + return SXRET_OK; +} +/* + * SHA-1 in C + * By Steve Reid + * Status: Public Domain + */ +/* + * blk0() and blk() perform the initial expand. + * I got the idea of expanding during the round function from SSLeay + * + * blk0le() for little-endian and blk0be() for big-endian. + */ +#if __GNUC__ && (defined(__i386__) || defined(__x86_64__)) +/* + * GCC by itself only generates left rotates. Use right rotates if + * possible to be kinder to dinky implementations with iterative rotate + * instructions. + */ +#define SHA_ROT(op, x, k) \ + ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; }) +#define rol(x,k) SHA_ROT("roll", x, k) +#define ror(x,k) SHA_ROT("rorl", x, k) + +#else +/* Generic C equivalent */ +#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r)) +#define rol(x,k) SHA_ROT(x,k,32-(k)) +#define ror(x,k) SHA_ROT(x,32-(k),k) +#endif + +#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \ + |(rol(block[i],8)&0x00FF00FF)) +#define blk0be(i) block[i] +#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \ + ^block[(i+2)&15]^block[i&15],1)) + +/* + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 + * + * Rl0() for little-endian and Rb0() for big-endian. Endianness is + * determined at run-time. + */ +#define Rl0(v,w,x,y,z,i) \ + z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2); +#define Rb0(v,w,x,y,z,i) \ + z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2); +#define R1(v,w,x,y,z,i) \ + z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2); +#define R2(v,w,x,y,z,i) \ + z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2); +#define R3(v,w,x,y,z,i) \ + z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2); +#define R4(v,w,x,y,z,i) \ + z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2); + +/* + * Hash a single 512-bit block. This is the core of the algorithm. + */ +#define a qq[0] +#define b qq[1] +#define c qq[2] +#define d qq[3] +#define e qq[4] + +static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]) { + unsigned int qq[5]; /* a, b, c, d, e; */ + static int one = 1; + unsigned int block[16]; + SyMemcpy(buffer, (void *)block, 64); + SyMemcpy(state, qq, 5 * sizeof(unsigned int)); + /* Copy context->state[] to working vars */ + /* + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + */ + /* 4 rounds of 20 operations each. Loop unrolled. */ + if(1 == *(unsigned char *)&one) { + 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); + 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); + 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); + 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); + } else { + 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); + 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); + 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); + 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); + } + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + 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); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; +} +#undef a +#undef b +#undef c +#undef d +#undef e +/* + * SHA1Init - Initialize new context + */ +PH7_PRIVATE void SHA1Init(SHA1Context *context) { + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} +/* + * Run your data through this. + */ +PH7_PRIVATE void SHA1Update(SHA1Context *context, const unsigned char *data, unsigned int len) { + unsigned int i, j; + j = context->count[0]; + if((context->count[0] += len << 3) < j) { + context->count[1] += (len >> 29) + 1; + } + j = (j >> 3) & 63; + if((j + len) > 63) { + (void)SyMemcpy(data, &context->buffer[j], (i = 64 - j)); + SHA1Transform(context->state, context->buffer); + for(; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } else { + i = 0; + } + (void)SyMemcpy(&data[i], &context->buffer[j], len - i); +} +/* + * Add padding and return the message digest. + */ +PH7_PRIVATE void SHA1Final(SHA1Context *context, unsigned char digest[20]) { + unsigned int i; + unsigned char finalcount[8]; + for(i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ + } + SHA1Update(context, (const unsigned char *)"\200", 1); + while((context->count[0] & 504) != 448) { + SHA1Update(context, (const unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + if(digest) { + for(i = 0; i < 20; i++) + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } +} +#undef Rl0 +#undef Rb0 +#undef R1 +#undef R2 +#undef R3 +#undef R4 + +PH7_PRIVATE sxi32 SySha1Compute(const void *pIn, sxu32 nLen, unsigned char zDigest[20]) { + SHA1Context sCtx; + SHA1Init(&sCtx); + SHA1Update(&sCtx, (const unsigned char *)pIn, nLen); + SHA1Final(&sCtx, zDigest); + return SXRET_OK; +} +static const sxu32 crc32_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +}; +#define CRC32C(c,d) (c = ( crc32_table[(c ^ (d)) & 0xFF] ^ (c>>8) ) ) +static sxu32 SyCrc32Update(sxu32 crc32, const void *pSrc, sxu32 nLen) { + register unsigned char *zIn = (unsigned char *)pSrc; + unsigned char *zEnd; + if(zIn == 0) { + return crc32; + } + zEnd = &zIn[nLen]; + for(;;) { + if(zIn >= zEnd) { + break; + } + CRC32C(crc32, zIn[0]); + zIn++; + if(zIn >= zEnd) { + break; + } + CRC32C(crc32, zIn[0]); + zIn++; + if(zIn >= zEnd) { + break; + } + CRC32C(crc32, zIn[0]); + zIn++; + if(zIn >= zEnd) { + break; + } + CRC32C(crc32, zIn[0]); + zIn++; + } + return crc32; +} +PH7_PRIVATE sxu32 SyCrc32(const void *pSrc, sxu32 nLen) { + return SyCrc32Update(SXU32_HIGH, pSrc, nLen); +} +PH7_PRIVATE sxi32 SyBinToHexConsumer(const void *pIn, sxu32 nLen, ProcConsumer xConsumer, void *pConsumerData) { + static const unsigned char zHexTab[] = "0123456789abcdef"; + const unsigned char *zIn, *zEnd; + unsigned char zOut[3]; + sxi32 rc; +#if defined(UNTRUST) + if(pIn == 0 || xConsumer == 0) { + return SXERR_EMPTY; + } +#endif + zIn = (const unsigned char *)pIn; + zEnd = &zIn[nLen]; + for(;;) { + if(zIn >= zEnd) { + break; + } + zOut[0] = zHexTab[zIn[0] >> 4]; + zOut[1] = zHexTab[zIn[0] & 0x0F]; + rc = xConsumer((const void *)zOut, sizeof(char) * 2, pConsumerData); + if(rc != SXRET_OK) { + return rc; + } + zIn++; + } + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyUriDecode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData, int bUTF8) { + static const sxu8 Utf8Trans[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00 + }; + const char *zIn = zSrc; + const char *zEnd; + const char *zCur; + sxu8 *zOutPtr; + sxu8 zOut[10]; + sxi32 c, d; + sxi32 rc; +#if defined(UNTRUST) + if(SX_EMPTY_STR(zSrc) || xConsumer == 0) { + return SXERR_EMPTY; + } +#endif + rc = SXRET_OK; + zEnd = &zSrc[nLen]; + zCur = zIn; + for(;;) { + while(zCur < zEnd && zCur[0] != '%' && zCur[0] != '+') { + zCur++; + } + if(zCur != zIn) { + /* Consume input */ + rc = xConsumer(zIn, (unsigned int)(zCur - zIn), pUserData); + if(rc != SXRET_OK) { + /* User consumer routine request an operation abort */ + break; + } + } + if(zCur >= zEnd) { + rc = SXRET_OK; + break; + } + /* Decode unsafe HTTP characters */ + zOutPtr = zOut; + if(zCur[0] == '+') { + *zOutPtr++ = ' '; + zCur++; + } else { + if(&zCur[2] >= zEnd) { + rc = SXERR_OVERFLOW; + break; + } + c = (SyAsciiToHex(zCur[1]) << 4) | SyAsciiToHex(zCur[2]); + zCur += 3; + if(c < 0x000C0) { + *zOutPtr++ = (sxu8)c; + } else { + c = Utf8Trans[c - 0xC0]; + while(zCur[0] == '%') { + d = (SyAsciiToHex(zCur[1]) << 4) | SyAsciiToHex(zCur[2]); + if((d & 0xC0) != 0x80) { + break; + } + c = (c << 6) + (0x3f & d); + zCur += 3; + } + if(bUTF8 == FALSE) { + *zOutPtr++ = (sxu8)c; + } else { + SX_WRITE_UTF8(zOutPtr, c); + } + } + } + /* Consume the decoded characters */ + rc = xConsumer((const void *)zOut, (unsigned int)(zOutPtr - zOut), pUserData); + if(rc != SXRET_OK) { + break; + } + /* Synchronize pointers */ + zIn = zCur; + } + return rc; +} +#define SAFE_HTTP(C) (SyisAlphaNum(c) || c == '_' || c == '-' || c == '$' || c == '.' ) +PH7_PRIVATE sxi32 SyUriEncode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) { + unsigned char *zIn = (unsigned char *)zSrc; + unsigned char zHex[3] = { '%', 0, 0 }; + unsigned char zOut[2]; + unsigned char *zCur, *zEnd; + sxi32 c; + sxi32 rc; +#ifdef UNTRUST + if(SX_EMPTY_STR(zSrc) || xConsumer == 0) { + return SXERR_EMPTY; + } +#endif + rc = SXRET_OK; + zEnd = &zIn[nLen]; + zCur = zIn; + for(;;) { + if(zCur >= zEnd) { + if(zCur != zIn) { + rc = xConsumer(zIn, (sxu32)(zCur - zIn), pUserData); + } + break; + } + c = zCur[0]; + if(SAFE_HTTP(c)) { + zCur++; + continue; + } + if(zCur != zIn && SXRET_OK != (rc = xConsumer(zIn, (sxu32)(zCur - zIn), pUserData))) { + break; + } + if(c == ' ') { + zOut[0] = '+'; + rc = xConsumer((const void *)zOut, sizeof(unsigned char), pUserData); + } else { + zHex[1] = "0123456789ABCDEF"[(c >> 4) & 0x0F]; + zHex[2] = "0123456789ABCDEF"[c & 0x0F]; + rc = xConsumer(zHex, sizeof(zHex), pUserData); + } + if(SXRET_OK != rc) { + break; + } + zIn = &zCur[1]; + zCur = zIn ; + } + return rc == SXRET_OK ? SXRET_OK : SXERR_ABORT; +} \ No newline at end of file diff --git a/engine/lib/heap.c b/engine/lib/heap.c new file mode 100644 index 0000000..f6b1484 --- /dev/null +++ b/engine/lib/heap.c @@ -0,0 +1,32 @@ +#include "ph7int.h" +#if defined(__WINNT__) + #include +#else + #include +#endif + +void *SyOSHeapAlloc(sxu32 nByte) { + void *pNew; +#if defined(__WINNT__) + pNew = HeapAlloc(GetProcessHeap(), 0, nByte); +#else + pNew = malloc((size_t)nByte); +#endif + return pNew; +} +void *SyOSHeapRealloc(void *pOld, sxu32 nByte) { + void *pNew; +#if defined(__WINNT__) + pNew = HeapReAlloc(GetProcessHeap(), 0, pOld, nByte); +#else + pNew = realloc(pOld, (size_t)nByte); +#endif + return pNew; +} +void SyOSHeapFree(void *pPtr) { +#if defined(__WINNT__) + HeapFree(GetProcessHeap(), 0, pPtr); +#else + free(pPtr); +#endif +} \ No newline at end of file diff --git a/engine/lib/lib.c b/engine/lib/lib.c deleted file mode 100644 index 5ef803e..0000000 --- a/engine/lib/lib.c +++ /dev/null @@ -1,4901 +0,0 @@ -/* - * Symisc PH7: An embeddable bytecode compiler and a virtual machine for the PHP(5) programming language. - * Copyright (C) 2011-2012, Symisc Systems http://ph7.symisc.net/ - * Version 2.1.4 - * For information on licensing,redistribution of this file,and for a DISCLAIMER OF ALL WARRANTIES - * please contact Symisc Systems via: - * legal@symisc.net - * licensing@symisc.net - * contact@symisc.net - * or visit: - * http://ph7.symisc.net/ - */ -/* $SymiscID: lib.c v5.1 Win7 2012-08-08 04:19 stable $ */ -/* - * Symisc Run-Time API: A modern thread safe replacement of the standard libc - * Copyright (C) Symisc Systems 2007-2012, http://www.symisc.net/ - * - * The Symisc Run-Time API is an independent project developed by symisc systems - * internally as a secure replacement of the standard libc. - * The library is re-entrant,thread-safe and platform independent. - */ -#include "ph7int.h" -#if defined(__WINNT__) - #include -#else - #include -#endif -#if defined(PH7_ENABLE_THREADS) -/* SyRunTimeApi: sxmutex.c */ -#if defined(__WINNT__) -struct SyMutex { - CRITICAL_SECTION sMutex; - sxu32 nType; /* Mutex type,one of SXMUTEX_TYPE_* */ -}; -/* Preallocated static mutex */ -static SyMutex aStaticMutexes[] = { - {{0}, SXMUTEX_TYPE_STATIC_1}, - {{0}, SXMUTEX_TYPE_STATIC_2}, - {{0}, SXMUTEX_TYPE_STATIC_3}, - {{0}, SXMUTEX_TYPE_STATIC_4}, - {{0}, SXMUTEX_TYPE_STATIC_5}, - {{0}, SXMUTEX_TYPE_STATIC_6} -}; -static BOOL winMutexInit = FALSE; -static LONG winMutexLock = 0; - -static sxi32 WinMutexGlobaInit(void) { - LONG rc; - rc = InterlockedCompareExchange(&winMutexLock, 1, 0); - if(rc == 0) { - sxu32 n; - for(n = 0 ; n < SX_ARRAYSIZE(aStaticMutexes) ; ++n) { - InitializeCriticalSection(&aStaticMutexes[n].sMutex); - } - winMutexInit = TRUE; - } else { - /* Someone else is doing this for us */ - while(winMutexInit == FALSE) { - Sleep(1); - } - } - return SXRET_OK; -} -static void WinMutexGlobalRelease(void) { - LONG rc; - rc = InterlockedCompareExchange(&winMutexLock, 0, 1); - if(rc == 1) { - /* The first to decrement to zero does the actual global release */ - if(winMutexInit == TRUE) { - sxu32 n; - for(n = 0 ; n < SX_ARRAYSIZE(aStaticMutexes) ; ++n) { - DeleteCriticalSection(&aStaticMutexes[n].sMutex); - } - winMutexInit = FALSE; - } - } -} -static SyMutex *WinMutexNew(int nType) { - SyMutex *pMutex = 0; - if(nType == SXMUTEX_TYPE_FAST || nType == SXMUTEX_TYPE_RECURSIVE) { - /* Allocate a new mutex */ - pMutex = (SyMutex *)HeapAlloc(GetProcessHeap(), 0, sizeof(SyMutex)); - if(pMutex == 0) { - return 0; - } - InitializeCriticalSection(&pMutex->sMutex); - } else { - /* Use a pre-allocated static mutex */ - if(nType > SXMUTEX_TYPE_STATIC_6) { - nType = SXMUTEX_TYPE_STATIC_6; - } - pMutex = &aStaticMutexes[nType - 3]; - } - pMutex->nType = nType; - return pMutex; -} -static void WinMutexRelease(SyMutex *pMutex) { - if(pMutex->nType == SXMUTEX_TYPE_FAST || pMutex->nType == SXMUTEX_TYPE_RECURSIVE) { - DeleteCriticalSection(&pMutex->sMutex); - HeapFree(GetProcessHeap(), 0, pMutex); - } -} -static void WinMutexEnter(SyMutex *pMutex) { - EnterCriticalSection(&pMutex->sMutex); -} -static sxi32 WinMutexTryEnter(SyMutex *pMutex) { -#ifdef _WIN32_WINNT - BOOL rc; - /* Only WindowsNT platforms */ - rc = TryEnterCriticalSection(&pMutex->sMutex); - if(rc) { - return SXRET_OK; - } else { - return SXERR_BUSY; - } -#else - return SXERR_NOTIMPLEMENTED; -#endif -} -static void WinMutexLeave(SyMutex *pMutex) { - LeaveCriticalSection(&pMutex->sMutex); -} -/* Export Windows mutex interfaces */ -static const SyMutexMethods sWinMutexMethods = { - WinMutexGlobaInit, /* xGlobalInit() */ - WinMutexGlobalRelease, /* xGlobalRelease() */ - WinMutexNew, /* xNew() */ - WinMutexRelease, /* xRelease() */ - WinMutexEnter, /* xEnter() */ - WinMutexTryEnter, /* xTryEnter() */ - WinMutexLeave /* xLeave() */ -}; -PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) { - return &sWinMutexMethods; -} -#elif defined(__UNIXES__) -#include -struct SyMutex { - pthread_mutex_t sMutex; - sxu32 nType; -}; -static SyMutex *UnixMutexNew(int nType) { - static SyMutex aStaticMutexes[] = { - {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_1}, - {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_2}, - {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_3}, - {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_4}, - {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_5}, - {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_6} - }; - SyMutex *pMutex; - if(nType == SXMUTEX_TYPE_FAST || nType == SXMUTEX_TYPE_RECURSIVE) { - pthread_mutexattr_t sRecursiveAttr; - /* Allocate a new mutex */ - pMutex = (SyMutex *)malloc(sizeof(SyMutex)); - if(pMutex == 0) { - return 0; - } - if(nType == SXMUTEX_TYPE_RECURSIVE) { - pthread_mutexattr_init(&sRecursiveAttr); - pthread_mutexattr_settype(&sRecursiveAttr, PTHREAD_MUTEX_RECURSIVE); - } - pthread_mutex_init(&pMutex->sMutex, nType == SXMUTEX_TYPE_RECURSIVE ? &sRecursiveAttr : 0); - if(nType == SXMUTEX_TYPE_RECURSIVE) { - pthread_mutexattr_destroy(&sRecursiveAttr); - } - } else { - /* Use a pre-allocated static mutex */ - if(nType > SXMUTEX_TYPE_STATIC_6) { - nType = SXMUTEX_TYPE_STATIC_6; - } - pMutex = &aStaticMutexes[nType - 3]; - } - pMutex->nType = nType; - return pMutex; -} -static void UnixMutexRelease(SyMutex *pMutex) { - if(pMutex->nType == SXMUTEX_TYPE_FAST || pMutex->nType == SXMUTEX_TYPE_RECURSIVE) { - pthread_mutex_destroy(&pMutex->sMutex); - free(pMutex); - } -} -static void UnixMutexEnter(SyMutex *pMutex) { - pthread_mutex_lock(&pMutex->sMutex); -} -static void UnixMutexLeave(SyMutex *pMutex) { - pthread_mutex_unlock(&pMutex->sMutex); -} -/* Export pthread mutex interfaces */ -static const SyMutexMethods sPthreadMutexMethods = { - 0, /* xGlobalInit() */ - 0, /* xGlobalRelease() */ - UnixMutexNew, /* xNew() */ - UnixMutexRelease, /* xRelease() */ - UnixMutexEnter, /* xEnter() */ - 0, /* xTryEnter() */ - UnixMutexLeave /* xLeave() */ -}; -PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) { - return &sPthreadMutexMethods; -} -#else -/* Host application must register their own mutex subsystem if the target - * platform is not an UNIX-like or windows systems. - */ -struct SyMutex { - sxu32 nType; -}; -static SyMutex *DummyMutexNew(int nType) { - static SyMutex sMutex; - SXUNUSED(nType); - return &sMutex; -} -static void DummyMutexRelease(SyMutex *pMutex) { - SXUNUSED(pMutex); -} -static void DummyMutexEnter(SyMutex *pMutex) { - SXUNUSED(pMutex); -} -static void DummyMutexLeave(SyMutex *pMutex) { - SXUNUSED(pMutex); -} -/* Export the dummy mutex interfaces */ -static const SyMutexMethods sDummyMutexMethods = { - 0, /* xGlobalInit() */ - 0, /* xGlobalRelease() */ - DummyMutexNew, /* xNew() */ - DummyMutexRelease, /* xRelease() */ - DummyMutexEnter, /* xEnter() */ - 0, /* xTryEnter() */ - DummyMutexLeave /* xLeave() */ -}; -PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) { - return &sDummyMutexMethods; -} -#endif /* __WINNT__ */ -#endif /* PH7_ENABLE_THREADS */ -static void *SyOSHeapAlloc(sxu32 nByte) { - void *pNew; -#if defined(__WINNT__) - pNew = HeapAlloc(GetProcessHeap(), 0, nByte); -#else - pNew = malloc((size_t)nByte); -#endif - return pNew; -} -static void *SyOSHeapRealloc(void *pOld, sxu32 nByte) { - void *pNew; -#if defined(__WINNT__) - pNew = HeapReAlloc(GetProcessHeap(), 0, pOld, nByte); -#else - pNew = realloc(pOld, (size_t)nByte); -#endif - return pNew; -} -static void SyOSHeapFree(void *pPtr) { -#if defined(__WINNT__) - HeapFree(GetProcessHeap(), 0, pPtr); -#else - free(pPtr); -#endif -} -/* SyRunTimeApi:sxstr.c */ -PH7_PRIVATE sxu32 SyStrlen(const char *zSrc) { - register const char *zIn = zSrc; -#if defined(UNTRUST) - if(zIn == 0) { - return 0; - } -#endif - for(;;) { - if(!zIn[0]) { - break; - } - zIn++; - if(!zIn[0]) { - break; - } - zIn++; - if(!zIn[0]) { - break; - } - zIn++; - if(!zIn[0]) { - break; - } - zIn++; - } - return (sxu32)(zIn - zSrc); -} -PH7_PRIVATE sxi32 SyByteFind(const char *zStr, sxu32 nLen, sxi32 c, sxu32 *pPos) { - const char *zIn = zStr; - const char *zEnd; - zEnd = &zIn[nLen]; - for(;;) { - if(zIn >= zEnd) { - break; - } - if(zIn[0] == c) { - if(pPos) { - *pPos = (sxu32)(zIn - zStr); - } - return SXRET_OK; - } - zIn++; - if(zIn >= zEnd) { - break; - } - if(zIn[0] == c) { - if(pPos) { - *pPos = (sxu32)(zIn - zStr); - } - return SXRET_OK; - } - zIn++; - if(zIn >= zEnd) { - break; - } - if(zIn[0] == c) { - if(pPos) { - *pPos = (sxu32)(zIn - zStr); - } - return SXRET_OK; - } - zIn++; - if(zIn >= zEnd) { - break; - } - if(zIn[0] == c) { - if(pPos) { - *pPos = (sxu32)(zIn - zStr); - } - return SXRET_OK; - } - zIn++; - } - return SXERR_NOTFOUND; -} -#ifndef PH7_DISABLE_BUILTIN_FUNC -PH7_PRIVATE sxi32 SyByteFind2(const char *zStr, sxu32 nLen, sxi32 c, sxu32 *pPos) { - const char *zIn = zStr; - const char *zEnd; - zEnd = &zIn[nLen - 1]; - for(;;) { - if(zEnd < zIn) { - break; - } - if(zEnd[0] == c) { - if(pPos) { - *pPos = (sxu32)(zEnd - zIn); - } - return SXRET_OK; - } - zEnd--; - if(zEnd < zIn) { - break; - } - if(zEnd[0] == c) { - if(pPos) { - *pPos = (sxu32)(zEnd - zIn); - } - return SXRET_OK; - } - zEnd--; - if(zEnd < zIn) { - break; - } - if(zEnd[0] == c) { - if(pPos) { - *pPos = (sxu32)(zEnd - zIn); - } - return SXRET_OK; - } - zEnd--; - if(zEnd < zIn) { - break; - } - if(zEnd[0] == c) { - if(pPos) { - *pPos = (sxu32)(zEnd - zIn); - } - return SXRET_OK; - } - zEnd--; - } - return SXERR_NOTFOUND; -} -#endif /* PH7_DISABLE_BUILTIN_FUNC */ -PH7_PRIVATE sxi32 SyByteListFind(const char *zSrc, sxu32 nLen, const char *zList, sxu32 *pFirstPos) { - const char *zIn = zSrc; - const char *zPtr; - const char *zEnd; - sxi32 c; - zEnd = &zSrc[nLen]; - for(;;) { - 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++; - 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++; - 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++; - 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++; - } - return SXERR_NOTFOUND; -} -#ifndef PH7_DISABLE_BUILTIN_FUNC -PH7_PRIVATE sxi32 SyStrncmp(const char *zLeft, const char *zRight, sxu32 nLen) { - const unsigned char *zP = (const unsigned char *)zLeft; - const unsigned char *zQ = (const unsigned char *)zRight; - if(SX_EMPTY_STR(zP) || SX_EMPTY_STR(zQ)) { - return SX_EMPTY_STR(zP) ? (SX_EMPTY_STR(zQ) ? 0 : -1) : 1; - } - if(nLen <= 0) { - return 0; - } - for(;;) { - if(nLen <= 0) { - return 0; - } - if(zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0]) { - break; - } - zP++; - zQ++; - nLen--; - if(nLen <= 0) { - return 0; - } - if(zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0]) { - break; - } - zP++; - zQ++; - nLen--; - if(nLen <= 0) { - return 0; - } - if(zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0]) { - break; - } - zP++; - zQ++; - nLen--; - if(nLen <= 0) { - return 0; - } - if(zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0]) { - break; - } - zP++; - zQ++; - nLen--; - } - return (sxi32)(zP[0] - zQ[0]); -} -#endif -PH7_PRIVATE sxi32 SyStrnicmp(const char *zLeft, const char *zRight, sxu32 SLen) { - register unsigned char *p = (unsigned char *)zLeft; - register unsigned char *q = (unsigned char *)zRight; - if(SX_EMPTY_STR(p) || SX_EMPTY_STR(q)) { - return SX_EMPTY_STR(p) ? SX_EMPTY_STR(q) ? 0 : -1 : 1; - } - for(;;) { - if(!SLen) { - return 0; - } - if(!*p || !*q || SyCharToLower(*p) != SyCharToLower(*q)) { - break; - } - p++; - q++; - --SLen; - if(!SLen) { - return 0; - } - if(!*p || !*q || SyCharToLower(*p) != SyCharToLower(*q)) { - break; - } - p++; - q++; - --SLen; - if(!SLen) { - return 0; - } - if(!*p || !*q || SyCharToLower(*p) != SyCharToLower(*q)) { - break; - } - p++; - q++; - --SLen; - if(!SLen) { - return 0; - } - if(!*p || !*q || SyCharToLower(*p) != SyCharToLower(*q)) { - break; - } - p++; - q++; - --SLen; - } - return (sxi32)(SyCharToLower(p[0]) - SyCharToLower(q[0])); -} -PH7_PRIVATE sxi32 SyStrnmicmp(const void *pLeft, const void *pRight, sxu32 SLen) { - return SyStrnicmp((const char *)pLeft, (const char *)pRight, SLen); -} -static sxu32 Systrcpy(char *zDest, sxu32 nDestLen, const char *zSrc, sxu32 nLen) { - unsigned char *zBuf = (unsigned char *)zDest; - unsigned char *zIn = (unsigned char *)zSrc; - unsigned char *zEnd; -#if defined(UNTRUST) - if(zSrc == (const char *)zDest) { - return 0; - } -#endif - if(nLen <= 0) { - nLen = SyStrlen(zSrc); - } - zEnd = &zBuf[nDestLen - 1]; /* reserve a room for the null terminator */ - for(;;) { - if(zBuf >= zEnd || nLen == 0) { - break; - } - zBuf[0] = zIn[0]; - zIn++; - zBuf++; - nLen--; - if(zBuf >= zEnd || nLen == 0) { - break; - } - zBuf[0] = zIn[0]; - zIn++; - zBuf++; - nLen--; - if(zBuf >= zEnd || nLen == 0) { - break; - } - zBuf[0] = zIn[0]; - zIn++; - zBuf++; - nLen--; - if(zBuf >= zEnd || nLen == 0) { - break; - } - zBuf[0] = zIn[0]; - zIn++; - zBuf++; - nLen--; - } - zBuf[0] = 0; - return (sxu32)(zBuf - (unsigned char *)zDest); -} -/* SyRunTimeApi:sxmem.c */ -PH7_PRIVATE void SyZero(void *pSrc, sxu32 nSize) { - register unsigned char *zSrc = (unsigned char *)pSrc; - unsigned char *zEnd; -#if defined(UNTRUST) - if(zSrc == 0 || nSize <= 0) { - return ; - } -#endif - zEnd = &zSrc[nSize]; - for(;;) { - if(zSrc >= zEnd) { - break; - } - zSrc[0] = 0; - zSrc++; - if(zSrc >= zEnd) { - break; - } - zSrc[0] = 0; - zSrc++; - if(zSrc >= zEnd) { - break; - } - zSrc[0] = 0; - zSrc++; - if(zSrc >= zEnd) { - break; - } - zSrc[0] = 0; - zSrc++; - } -} -PH7_PRIVATE sxi32 SyMemcmp(const void *pB1, const void *pB2, sxu32 nSize) { - sxi32 rc; - if(nSize <= 0) { - return 0; - } - if(pB1 == 0 || pB2 == 0) { - return pB1 != 0 ? 1 : (pB2 == 0 ? 0 : -1); - } - SX_MACRO_FAST_CMP(pB1, pB2, nSize, rc); - return rc; -} -PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen) { -#if defined(UNTRUST) - if(pSrc == 0 || pDest == 0) { - return 0; - } -#endif - if(pSrc == (const void *)pDest) { - return nLen; - } - SX_MACRO_FAST_MEMCPY(pSrc, pDest, nLen); - return nLen; -} -static void *MemOSAlloc(sxu32 nBytes) { - sxu32 *pChunk; - pChunk = (sxu32 *)SyOSHeapAlloc(nBytes + sizeof(sxu32)); - if(pChunk == 0) { - return 0; - } - pChunk[0] = nBytes; - return (void *)&pChunk[1]; -} -static void *MemOSRealloc(void *pOld, sxu32 nBytes) { - sxu32 *pOldChunk; - sxu32 *pChunk; - pOldChunk = (sxu32 *)(((char *)pOld) - sizeof(sxu32)); - if(pOldChunk[0] >= nBytes) { - return pOld; - } - pChunk = (sxu32 *)SyOSHeapRealloc(pOldChunk, nBytes + sizeof(sxu32)); - if(pChunk == 0) { - return 0; - } - pChunk[0] = nBytes; - return (void *)&pChunk[1]; -} -static void MemOSFree(void *pBlock) { - void *pChunk; - pChunk = (void *)(((char *)pBlock) - sizeof(sxu32)); - SyOSHeapFree(pChunk); -} -static sxu32 MemOSChunkSize(void *pBlock) { - sxu32 *pChunk; - pChunk = (sxu32 *)(((char *)pBlock) - sizeof(sxu32)); - return pChunk[0]; -} -/* Export OS allocation methods */ -static const SyMemMethods sOSAllocMethods = { - MemOSAlloc, - MemOSRealloc, - MemOSFree, - MemOSChunkSize, - 0, - 0, - 0 -}; -static void *MemBackendAlloc(SyMemBackend *pBackend, sxu32 nByte) { - SyMemBlock *pBlock; - sxi32 nRetry = 0; - /* Append an extra block so we can tracks allocated chunks and avoid memory - * leaks. - */ - nByte += sizeof(SyMemBlock); - for(;;) { - pBlock = (SyMemBlock *)pBackend->pMethods->xAlloc(nByte); - if(pBlock != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY - || SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) { - break; - } - nRetry++; - } - if(pBlock == 0) { - return 0; - } - pBlock->pNext = pBlock->pPrev = 0; - /* Link to the list of already tracked blocks */ - MACRO_LD_PUSH(pBackend->pBlocks, pBlock); -#if defined(UNTRUST) - pBlock->nGuard = SXMEM_BACKEND_MAGIC; -#endif - pBackend->nBlock++; - return (void *)&pBlock[1]; -} -PH7_PRIVATE void *SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nByte) { - void *pChunk; -#if defined(UNTRUST) - if(SXMEM_BACKEND_CORRUPT(pBackend)) { - return 0; - } -#endif - if(pBackend->pMutexMethods) { - SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); - } - pChunk = MemBackendAlloc(&(*pBackend), nByte); - if(pBackend->pMutexMethods) { - SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); - } - return pChunk; -} -static void *MemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) { - SyMemBlock *pBlock, *pNew, *pPrev, *pNext; - sxu32 nRetry = 0; - if(pOld == 0) { - return MemBackendAlloc(&(*pBackend), nByte); - } - pBlock = (SyMemBlock *)(((char *)pOld) - sizeof(SyMemBlock)); -#if defined(UNTRUST) - if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) { - return 0; - } -#endif - nByte += sizeof(SyMemBlock); - pPrev = pBlock->pPrev; - pNext = pBlock->pNext; - for(;;) { - pNew = (SyMemBlock *)pBackend->pMethods->xRealloc(pBlock, nByte); - if(pNew != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY || - SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) { - break; - } - nRetry++; - } - if(pNew == 0) { - return 0; - } - if(pNew != pBlock) { - if(pPrev == 0) { - pBackend->pBlocks = pNew; - } else { - pPrev->pNext = pNew; - } - if(pNext) { - pNext->pPrev = pNew; - } -#if defined(UNTRUST) - pNew->nGuard = SXMEM_BACKEND_MAGIC; -#endif - } - return (void *)&pNew[1]; -} -PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) { - void *pChunk; -#if defined(UNTRUST) - if(SXMEM_BACKEND_CORRUPT(pBackend)) { - return 0; - } -#endif - if(pBackend->pMutexMethods) { - SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); - } - pChunk = MemBackendRealloc(&(*pBackend), pOld, nByte); - if(pBackend->pMutexMethods) { - SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); - } - return pChunk; -} -static sxi32 MemBackendFree(SyMemBackend *pBackend, void *pChunk) { - SyMemBlock *pBlock; - pBlock = (SyMemBlock *)(((char *)pChunk) - sizeof(SyMemBlock)); -#if defined(UNTRUST) - if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) { - return SXERR_CORRUPT; - } -#endif - /* Unlink from the list of active blocks */ - if(pBackend->nBlock > 0) { - /* Release the block */ -#if defined(UNTRUST) - /* Mark as stale block */ - pBlock->nGuard = 0x635B; -#endif - MACRO_LD_REMOVE(pBackend->pBlocks, pBlock); - pBackend->nBlock--; - pBackend->pMethods->xFree(pBlock); - } - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyMemBackendFree(SyMemBackend *pBackend, void *pChunk) { - sxi32 rc; -#if defined(UNTRUST) - if(SXMEM_BACKEND_CORRUPT(pBackend)) { - return SXERR_CORRUPT; - } -#endif - if(pChunk == 0) { - return SXRET_OK; - } - if(pBackend->pMutexMethods) { - SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); - } - rc = MemBackendFree(&(*pBackend), pChunk); - if(pBackend->pMutexMethods) { - SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); - } - return rc; -} -#if defined(PH7_ENABLE_THREADS) -PH7_PRIVATE sxi32 SyMemBackendMakeThreadSafe(SyMemBackend *pBackend, const SyMutexMethods *pMethods) { - SyMutex *pMutex; -#if defined(UNTRUST) - if(SXMEM_BACKEND_CORRUPT(pBackend) || pMethods == 0 || pMethods->xNew == 0) { - return SXERR_CORRUPT; - } -#endif - pMutex = pMethods->xNew(SXMUTEX_TYPE_FAST); - if(pMutex == 0) { - return SXERR_OS; - } - /* Attach the mutex to the memory backend */ - pBackend->pMutex = pMutex; - pBackend->pMutexMethods = pMethods; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyMemBackendDisbaleMutexing(SyMemBackend *pBackend) { -#if defined(UNTRUST) - if(SXMEM_BACKEND_CORRUPT(pBackend)) { - return SXERR_CORRUPT; - } -#endif - if(pBackend->pMutex == 0) { - /* There is no mutex subsystem at all */ - return SXRET_OK; - } - SyMutexRelease(pBackend->pMutexMethods, pBackend->pMutex); - pBackend->pMutexMethods = 0; - pBackend->pMutex = 0; - return SXRET_OK; -} -#endif -/* - * Memory pool allocator - */ -#define SXMEM_POOL_MAGIC 0xDEAD -#define SXMEM_POOL_MAXALLOC (1<<(SXMEM_POOL_NBUCKETS+SXMEM_POOL_INCR)) -#define SXMEM_POOL_MINALLOC (1<<(SXMEM_POOL_INCR)) -static sxi32 MemPoolBucketAlloc(SyMemBackend *pBackend, sxu32 nBucket) { - char *zBucket, *zBucketEnd; - SyMemHeader *pHeader; - sxu32 nBucketSize; - /* Allocate one big block first */ - zBucket = (char *)MemBackendAlloc(&(*pBackend), SXMEM_POOL_MAXALLOC); - if(zBucket == 0) { - return SXERR_MEM; - } - zBucketEnd = &zBucket[SXMEM_POOL_MAXALLOC]; - /* Divide the big block into mini bucket pool */ - nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR); - pBackend->apPool[nBucket] = pHeader = (SyMemHeader *)zBucket; - for(;;) { - if(&zBucket[nBucketSize] >= zBucketEnd) { - break; - } - pHeader->pNext = (SyMemHeader *)&zBucket[nBucketSize]; - /* Advance the cursor to the next available chunk */ - pHeader = pHeader->pNext; - zBucket += nBucketSize; - } - pHeader->pNext = 0; - return SXRET_OK; -} -static void *MemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nByte) { - SyMemHeader *pBucket, *pNext; - sxu32 nBucketSize; - sxu32 nBucket; - if(nByte + sizeof(SyMemHeader) >= SXMEM_POOL_MAXALLOC) { - /* Allocate a big chunk directly */ - pBucket = (SyMemHeader *)MemBackendAlloc(&(*pBackend), nByte + sizeof(SyMemHeader)); - if(pBucket == 0) { - return 0; - } - /* Record as big block */ - pBucket->nBucket = (sxu32)(SXMEM_POOL_MAGIC << 16) | SXU16_HIGH; - return (void *)(pBucket + 1); - } - /* Locate the appropriate bucket */ - nBucket = 0; - nBucketSize = SXMEM_POOL_MINALLOC; - while(nByte + sizeof(SyMemHeader) > nBucketSize) { - nBucketSize <<= 1; - nBucket++; - } - pBucket = pBackend->apPool[nBucket]; - if(pBucket == 0) { - sxi32 rc; - rc = MemPoolBucketAlloc(&(*pBackend), nBucket); - if(rc != SXRET_OK) { - return 0; - } - pBucket = pBackend->apPool[nBucket]; - } - /* Remove from the free list */ - pNext = pBucket->pNext; - pBackend->apPool[nBucket] = pNext; - /* Record bucket&magic number */ - pBucket->nBucket = (SXMEM_POOL_MAGIC << 16) | nBucket; - return (void *)&pBucket[1]; -} -PH7_PRIVATE void *SyMemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nByte) { - void *pChunk; -#if defined(UNTRUST) - if(SXMEM_BACKEND_CORRUPT(pBackend)) { - return 0; - } -#endif - if(pBackend->pMutexMethods) { - SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); - } - pChunk = MemBackendPoolAlloc(&(*pBackend), nByte); - if(pBackend->pMutexMethods) { - SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); - } - return pChunk; -} -static sxi32 MemBackendPoolFree(SyMemBackend *pBackend, void *pChunk) { - SyMemHeader *pHeader; - sxu32 nBucket; - /* Get the corresponding bucket */ - pHeader = (SyMemHeader *)(((char *)pChunk) - sizeof(SyMemHeader)); - /* Sanity check to avoid misuse */ - if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) { - return SXERR_CORRUPT; - } - nBucket = pHeader->nBucket & 0xFFFF; - if(nBucket == SXU16_HIGH) { - /* Free the big block */ - MemBackendFree(&(*pBackend), pHeader); - } else { - /* Return to the free list */ - pHeader->pNext = pBackend->apPool[nBucket & 0x0f]; - pBackend->apPool[nBucket & 0x0f] = pHeader; - } - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyMemBackendPoolFree(SyMemBackend *pBackend, void *pChunk) { - sxi32 rc; -#if defined(UNTRUST) - if(SXMEM_BACKEND_CORRUPT(pBackend) || pChunk == 0) { - return SXERR_CORRUPT; - } -#endif - if(pBackend->pMutexMethods) { - SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); - } - rc = MemBackendPoolFree(&(*pBackend), pChunk); - if(pBackend->pMutexMethods) { - SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); - } - return rc; -} -#if 0 -static void *MemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) { - sxu32 nBucket, nBucketSize; - SyMemHeader *pHeader; - void *pNew; - if(pOld == 0) { - /* Allocate a new pool */ - pNew = MemBackendPoolAlloc(&(*pBackend), nByte); - return pNew; - } - /* Get the corresponding bucket */ - pHeader = (SyMemHeader *)(((char *)pOld) - sizeof(SyMemHeader)); - /* Sanity check to avoid misuse */ - if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) { - return 0; - } - nBucket = pHeader->nBucket & 0xFFFF; - if(nBucket == SXU16_HIGH) { - /* Big block */ - return MemBackendRealloc(&(*pBackend), pHeader, nByte); - } - nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR); - if(nBucketSize >= nByte + sizeof(SyMemHeader)) { - /* The old bucket can honor the requested size */ - return pOld; - } - /* Allocate a new pool */ - pNew = MemBackendPoolAlloc(&(*pBackend), nByte); - if(pNew == 0) { - return 0; - } - /* Copy the old data into the new block */ - SyMemcpy(pOld, pNew, nBucketSize); - /* Free the stale block */ - MemBackendPoolFree(&(*pBackend), pOld); - return pNew; -} -PH7_PRIVATE void *SyMemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) { - void *pChunk; -#if defined(UNTRUST) - if(SXMEM_BACKEND_CORRUPT(pBackend)) { - return 0; - } -#endif - if(pBackend->pMutexMethods) { - SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); - } - pChunk = MemBackendPoolRealloc(&(*pBackend), pOld, nByte); - if(pBackend->pMutexMethods) { - SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); - } - return pChunk; -} -#endif -PH7_PRIVATE sxi32 SyMemBackendInit(SyMemBackend *pBackend, ProcMemError xMemErr, void *pUserData) { -#if defined(UNTRUST) - if(pBackend == 0) { - return SXERR_EMPTY; - } -#endif - /* Zero the allocator first */ - SyZero(&(*pBackend), sizeof(SyMemBackend)); - pBackend->xMemError = xMemErr; - pBackend->pUserData = pUserData; - /* Switch to the OS memory allocator */ - pBackend->pMethods = &sOSAllocMethods; - if(pBackend->pMethods->xInit) { - /* Initialize the backend */ - if(SXRET_OK != pBackend->pMethods->xInit(pBackend->pMethods->pUserData)) { - return SXERR_ABORT; - } - } -#if defined(UNTRUST) - pBackend->nMagic = SXMEM_BACKEND_MAGIC; -#endif - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyMemBackendInitFromOthers(SyMemBackend *pBackend, const SyMemMethods *pMethods, ProcMemError xMemErr, void *pUserData) { -#if defined(UNTRUST) - if(pBackend == 0 || pMethods == 0) { - return SXERR_EMPTY; - } -#endif - if(pMethods->xAlloc == 0 || pMethods->xRealloc == 0 || pMethods->xFree == 0 || pMethods->xChunkSize == 0) { - /* mandatory methods are missing */ - return SXERR_INVALID; - } - /* Zero the allocator first */ - SyZero(&(*pBackend), sizeof(SyMemBackend)); - pBackend->xMemError = xMemErr; - pBackend->pUserData = pUserData; - /* Switch to the host application memory allocator */ - pBackend->pMethods = pMethods; - if(pBackend->pMethods->xInit) { - /* Initialize the backend */ - if(SXRET_OK != pBackend->pMethods->xInit(pBackend->pMethods->pUserData)) { - return SXERR_ABORT; - } - } -#if defined(UNTRUST) - pBackend->nMagic = SXMEM_BACKEND_MAGIC; -#endif - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyMemBackendInitFromParent(SyMemBackend *pBackend, SyMemBackend *pParent) { - sxu8 bInheritMutex; -#if defined(UNTRUST) - if(pBackend == 0 || SXMEM_BACKEND_CORRUPT(pParent)) { - return SXERR_CORRUPT; - } -#endif - /* Zero the allocator first */ - SyZero(&(*pBackend), sizeof(SyMemBackend)); - pBackend->pMethods = pParent->pMethods; - pBackend->xMemError = pParent->xMemError; - pBackend->pUserData = pParent->pUserData; - bInheritMutex = pParent->pMutexMethods ? TRUE : FALSE; - if(bInheritMutex) { - pBackend->pMutexMethods = pParent->pMutexMethods; - /* Create a private mutex */ - pBackend->pMutex = pBackend->pMutexMethods->xNew(SXMUTEX_TYPE_FAST); - if(pBackend->pMutex == 0) { - return SXERR_OS; - } - } -#if defined(UNTRUST) - pBackend->nMagic = SXMEM_BACKEND_MAGIC; -#endif - return SXRET_OK; -} -static sxi32 MemBackendRelease(SyMemBackend *pBackend) { - SyMemBlock *pBlock, *pNext; - pBlock = pBackend->pBlocks; - for(;;) { - if(pBackend->nBlock == 0) { - break; - } - pNext = pBlock->pNext; - pBackend->pMethods->xFree(pBlock); - pBlock = pNext; - pBackend->nBlock--; - /* LOOP ONE */ - if(pBackend->nBlock == 0) { - break; - } - pNext = pBlock->pNext; - pBackend->pMethods->xFree(pBlock); - pBlock = pNext; - pBackend->nBlock--; - /* LOOP TWO */ - if(pBackend->nBlock == 0) { - break; - } - pNext = pBlock->pNext; - pBackend->pMethods->xFree(pBlock); - pBlock = pNext; - pBackend->nBlock--; - /* LOOP THREE */ - if(pBackend->nBlock == 0) { - break; - } - pNext = pBlock->pNext; - pBackend->pMethods->xFree(pBlock); - pBlock = pNext; - pBackend->nBlock--; - /* LOOP FOUR */ - } - if(pBackend->pMethods->xRelease) { - pBackend->pMethods->xRelease(pBackend->pMethods->pUserData); - } - pBackend->pMethods = 0; - pBackend->pBlocks = 0; -#if defined(UNTRUST) - pBackend->nMagic = 0x2626; -#endif - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyMemBackendRelease(SyMemBackend *pBackend) { - sxi32 rc; -#if defined(UNTRUST) - if(SXMEM_BACKEND_CORRUPT(pBackend)) { - return SXERR_INVALID; - } -#endif - if(pBackend->pMutexMethods) { - SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); - } - rc = MemBackendRelease(&(*pBackend)); - if(pBackend->pMutexMethods) { - SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); - SyMutexRelease(pBackend->pMutexMethods, pBackend->pMutex); - } - return SXRET_OK; -} -PH7_PRIVATE void *SyMemBackendDup(SyMemBackend *pBackend, const void *pSrc, sxu32 nSize) { - void *pNew; -#if defined(UNTRUST) - if(pSrc == 0 || nSize <= 0) { - return 0; - } -#endif - pNew = SyMemBackendAlloc(&(*pBackend), nSize); - if(pNew) { - SyMemcpy(pSrc, pNew, nSize); - } - return pNew; -} -PH7_PRIVATE char *SyMemBackendStrDup(SyMemBackend *pBackend, const char *zSrc, sxu32 nSize) { - char *zDest; - zDest = (char *)SyMemBackendAlloc(&(*pBackend), nSize + 1); - if(zDest) { - Systrcpy(zDest, nSize + 1, zSrc, nSize); - } - return zDest; -} -PH7_PRIVATE sxi32 SyBlobInitFromBuf(SyBlob *pBlob, void *pBuffer, sxu32 nSize) { -#if defined(UNTRUST) - if(pBlob == 0 || pBuffer == 0 || nSize < 1) { - return SXERR_EMPTY; - } -#endif - pBlob->pBlob = pBuffer; - pBlob->mByte = nSize; - pBlob->nByte = 0; - pBlob->pAllocator = 0; - pBlob->nFlags = SXBLOB_LOCKED | SXBLOB_STATIC; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyBlobInit(SyBlob *pBlob, SyMemBackend *pAllocator) { -#if defined(UNTRUST) - if(pBlob == 0) { - return SXERR_EMPTY; - } -#endif - pBlob->pBlob = 0; - pBlob->mByte = pBlob->nByte = 0; - pBlob->pAllocator = &(*pAllocator); - pBlob->nFlags = 0; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyBlobReadOnly(SyBlob *pBlob, const void *pData, sxu32 nByte) { -#if defined(UNTRUST) - if(pBlob == 0) { - return SXERR_EMPTY; - } -#endif - pBlob->pBlob = (void *)pData; - pBlob->nByte = nByte; - pBlob->mByte = 0; - pBlob->nFlags |= SXBLOB_RDONLY; - return SXRET_OK; -} -#ifndef SXBLOB_MIN_GROWTH - #define SXBLOB_MIN_GROWTH 16 -#endif -static sxi32 BlobPrepareGrow(SyBlob *pBlob, sxu32 *pByte) { - sxu32 nByte; - void *pNew; - nByte = *pByte; - if(pBlob->nFlags & (SXBLOB_LOCKED | SXBLOB_STATIC)) { - if(SyBlobFreeSpace(pBlob) < nByte) { - *pByte = SyBlobFreeSpace(pBlob); - if((*pByte) == 0) { - return SXERR_SHORT; - } - } - return SXRET_OK; - } - if(pBlob->nFlags & SXBLOB_RDONLY) { - /* Make a copy of the read-only item */ - if(pBlob->nByte > 0) { - pNew = SyMemBackendDup(pBlob->pAllocator, pBlob->pBlob, pBlob->nByte); - if(pNew == 0) { - return SXERR_MEM; - } - pBlob->pBlob = pNew; - pBlob->mByte = pBlob->nByte; - } else { - pBlob->pBlob = 0; - pBlob->mByte = 0; - } - /* Remove the read-only flag */ - pBlob->nFlags &= ~SXBLOB_RDONLY; - } - if(SyBlobFreeSpace(pBlob) >= nByte) { - return SXRET_OK; - } - if(pBlob->mByte > 0) { - nByte = nByte + pBlob->mByte * 2 + SXBLOB_MIN_GROWTH; - } else if(nByte < SXBLOB_MIN_GROWTH) { - nByte = SXBLOB_MIN_GROWTH; - } - pNew = SyMemBackendRealloc(pBlob->pAllocator, pBlob->pBlob, nByte); - if(pNew == 0) { - return SXERR_MEM; - } - pBlob->pBlob = pNew; - pBlob->mByte = nByte; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyBlobAppend(SyBlob *pBlob, const void *pData, sxu32 nSize) { - sxu8 *zBlob; - sxi32 rc; - if(nSize < 1) { - return SXRET_OK; - } - rc = BlobPrepareGrow(&(*pBlob), &nSize); - if(SXRET_OK != rc) { - return rc; - } - if(pData) { - zBlob = (sxu8 *)pBlob->pBlob ; - zBlob = &zBlob[pBlob->nByte]; - pBlob->nByte += nSize; - SX_MACRO_FAST_MEMCPY(pData, zBlob, nSize); - } - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyBlobNullAppend(SyBlob *pBlob) { - sxi32 rc; - sxu32 n; - n = pBlob->nByte; - rc = SyBlobAppend(&(*pBlob), (const void *)"\0", sizeof(char)); - if(rc == SXRET_OK) { - pBlob->nByte = n; - } - return rc; -} -PH7_PRIVATE sxi32 SyBlobDup(SyBlob *pSrc, SyBlob *pDest) { - sxi32 rc = SXRET_OK; -#ifdef UNTRUST - if(pSrc == 0 || pDest == 0) { - return SXERR_EMPTY; - } -#endif - if(pSrc->nByte > 0) { - rc = SyBlobAppend(&(*pDest), pSrc->pBlob, pSrc->nByte); - } - return rc; -} -PH7_PRIVATE sxi32 SyBlobCmp(SyBlob *pLeft, SyBlob *pRight) { - sxi32 rc; -#ifdef UNTRUST - if(pLeft == 0 || pRight == 0) { - return pLeft ? 1 : -1; - } -#endif - if(pLeft->nByte != pRight->nByte) { - /* Length differ */ - return pLeft->nByte - pRight->nByte; - } - if(pLeft->nByte == 0) { - return 0; - } - /* Perform a standard memcmp() operation */ - rc = SyMemcmp(pLeft->pBlob, pRight->pBlob, pLeft->nByte); - return rc; -} -PH7_PRIVATE sxi32 SyBlobReset(SyBlob *pBlob) { - pBlob->nByte = 0; - if(pBlob->nFlags & SXBLOB_RDONLY) { - pBlob->pBlob = 0; - pBlob->mByte = 0; - pBlob->nFlags &= ~SXBLOB_RDONLY; - } - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyBlobRelease(SyBlob *pBlob) { - if((pBlob->nFlags & (SXBLOB_STATIC | SXBLOB_RDONLY)) == 0 && pBlob->mByte > 0) { - SyMemBackendFree(pBlob->pAllocator, pBlob->pBlob); - } - pBlob->pBlob = 0; - pBlob->nByte = pBlob->mByte = 0; - pBlob->nFlags = 0; - return SXRET_OK; -} -#ifndef PH7_DISABLE_BUILTIN_FUNC -PH7_PRIVATE sxi32 SyBlobSearch(const void *pBlob, sxu32 nLen, const void *pPattern, sxu32 pLen, sxu32 *pOfft) { - const char *zIn = (const char *)pBlob; - const char *zEnd; - sxi32 rc; - if(pLen > nLen) { - return SXERR_NOTFOUND; - } - zEnd = &zIn[nLen - pLen]; - for(;;) { - 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++; - 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++; - 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++; - 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++; - } - return SXERR_NOTFOUND; -} -#endif /* PH7_DISABLE_BUILTIN_FUNC */ -/* SyRunTimeApi:sxds.c */ -PH7_PRIVATE sxi32 SySetInit(SySet *pSet, SyMemBackend *pAllocator, sxu32 ElemSize) { - pSet->nSize = 0 ; - pSet->nUsed = 0; - pSet->nCursor = 0; - pSet->eSize = ElemSize; - pSet->pAllocator = pAllocator; - pSet->pBase = 0; - pSet->pUserData = 0; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SySetPut(SySet *pSet, const void *pItem) { - unsigned char *zbase; - if(pSet->nUsed >= pSet->nSize) { - void *pNew; - if(pSet->pAllocator == 0) { - return SXERR_LOCKED; - } - if(pSet->nSize <= 0) { - pSet->nSize = 4; - } - pNew = SyMemBackendRealloc(pSet->pAllocator, pSet->pBase, pSet->eSize * pSet->nSize * 2); - if(pNew == 0) { - return SXERR_MEM; - } - pSet->pBase = pNew; - pSet->nSize <<= 1; - } - zbase = (unsigned char *)pSet->pBase; - SX_MACRO_FAST_MEMCPY(pItem, &zbase[pSet->nUsed * pSet->eSize], pSet->eSize); - pSet->nUsed++; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SySetAlloc(SySet *pSet, sxi32 nItem) { - if(pSet->nSize > 0) { - return SXERR_LOCKED; - } - if(nItem < 8) { - nItem = 8; - } - pSet->pBase = SyMemBackendAlloc(pSet->pAllocator, pSet->eSize * nItem); - if(pSet->pBase == 0) { - return SXERR_MEM; - } - pSet->nSize = nItem; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SySetReset(SySet *pSet) { - pSet->nUsed = 0; - pSet->nCursor = 0; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SySetResetCursor(SySet *pSet) { - pSet->nCursor = 0; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SySetGetNextEntry(SySet *pSet, void **ppEntry) { - register unsigned char *zSrc; - if(pSet->nCursor >= pSet->nUsed) { - /* Reset cursor */ - pSet->nCursor = 0; - return SXERR_EOF; - } - zSrc = (unsigned char *)SySetBasePtr(pSet); - if(ppEntry) { - *ppEntry = (void *)&zSrc[pSet->nCursor * pSet->eSize]; - } - pSet->nCursor++; - return SXRET_OK; -} -#ifndef PH7_DISABLE_BUILTIN_FUNC -PH7_PRIVATE void *SySetPeekCurrentEntry(SySet *pSet) { - register unsigned char *zSrc; - if(pSet->nCursor >= pSet->nUsed) { - return 0; - } - zSrc = (unsigned char *)SySetBasePtr(pSet); - return (void *)&zSrc[pSet->nCursor * pSet->eSize]; -} -#endif /* PH7_DISABLE_BUILTIN_FUNC */ -PH7_PRIVATE sxi32 SySetTruncate(SySet *pSet, sxu32 nNewSize) { - if(nNewSize < pSet->nUsed) { - pSet->nUsed = nNewSize; - } - return SXRET_OK; -} -PH7_PRIVATE sxi32 SySetRelease(SySet *pSet) { - sxi32 rc = SXRET_OK; - if(pSet->pAllocator && pSet->pBase) { - rc = SyMemBackendFree(pSet->pAllocator, pSet->pBase); - } - pSet->pBase = 0; - pSet->nUsed = 0; - pSet->nCursor = 0; - return rc; -} -PH7_PRIVATE void *SySetPeek(SySet *pSet) { - const char *zBase; - if(pSet->nUsed <= 0) { - return 0; - } - zBase = (const char *)pSet->pBase; - return (void *)&zBase[(pSet->nUsed - 1) * pSet->eSize]; -} -PH7_PRIVATE void *SySetPop(SySet *pSet) { - const char *zBase; - void *pData; - if(pSet->nUsed <= 0) { - return 0; - } - zBase = (const char *)pSet->pBase; - pSet->nUsed--; - pData = (void *)&zBase[pSet->nUsed * pSet->eSize]; - return pData; -} -PH7_PRIVATE void *SySetAt(SySet *pSet, sxu32 nIdx) { - const char *zBase; - if(nIdx >= pSet->nUsed) { - /* Out of range */ - return 0; - } - zBase = (const char *)pSet->pBase; - return (void *)&zBase[nIdx * pSet->eSize]; -} -/* Private hash entry */ -struct SyHashEntry_Pr { - const void *pKey; /* Hash key */ - sxu32 nKeyLen; /* Key length */ - void *pUserData; /* User private data */ - /* Private fields */ - sxu32 nHash; - SyHash *pHash; - SyHashEntry_Pr *pNext, *pPrev; /* Next and previous entry in the list */ - SyHashEntry_Pr *pNextCollide, *pPrevCollide; /* Collision list */ -}; -#define INVALID_HASH(H) ((H)->apBucket == 0) -/* Forward declarartion */ -static sxu32 SyBinHash(const void *pSrc, sxu32 nLen); -PH7_PRIVATE sxi32 SyHashInit(SyHash *pHash, SyMemBackend *pAllocator, ProcHash xHash, ProcCmp xCmp) { - SyHashEntry_Pr **apNew; -#if defined(UNTRUST) - if(pHash == 0) { - return SXERR_EMPTY; - } -#endif - /* Allocate a new table */ - apNew = (SyHashEntry_Pr **)SyMemBackendAlloc(&(*pAllocator), sizeof(SyHashEntry_Pr *) * SXHASH_BUCKET_SIZE); - if(apNew == 0) { - return SXERR_MEM; - } - SyZero((void *)apNew, sizeof(SyHashEntry_Pr *) * SXHASH_BUCKET_SIZE); - pHash->pAllocator = &(*pAllocator); - pHash->xHash = xHash ? xHash : SyBinHash; - pHash->xCmp = xCmp ? xCmp : SyMemcmp; - pHash->pCurrent = pHash->pList = 0; - pHash->nEntry = 0; - pHash->apBucket = apNew; - pHash->nBucketSize = SXHASH_BUCKET_SIZE; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyHashRelease(SyHash *pHash) { - SyHashEntry_Pr *pEntry, *pNext; -#if defined(UNTRUST) - if(INVALID_HASH(pHash)) { - return SXERR_EMPTY; - } -#endif - pEntry = pHash->pList; - for(;;) { - if(pHash->nEntry == 0) { - break; - } - pNext = pEntry->pNext; - SyMemBackendPoolFree(pHash->pAllocator, pEntry); - pEntry = pNext; - pHash->nEntry--; - } - if(pHash->apBucket) { - SyMemBackendFree(pHash->pAllocator, (void *)pHash->apBucket); - } - pHash->apBucket = 0; - pHash->nBucketSize = 0; - pHash->pAllocator = 0; - return SXRET_OK; -} -static SyHashEntry_Pr *HashGetEntry(SyHash *pHash, const void *pKey, sxu32 nKeyLen) { - SyHashEntry_Pr *pEntry; - sxu32 nHash; - nHash = pHash->xHash(pKey, nKeyLen); - pEntry = pHash->apBucket[nHash & (pHash->nBucketSize - 1)]; - for(;;) { - if(pEntry == 0) { - break; - } - if(pEntry->nHash == nHash && pEntry->nKeyLen == nKeyLen && - pHash->xCmp(pEntry->pKey, pKey, nKeyLen) == 0) { - return pEntry; - } - pEntry = pEntry->pNextCollide; - } - /* Entry not found */ - return 0; -} -PH7_PRIVATE SyHashEntry *SyHashGet(SyHash *pHash, const void *pKey, sxu32 nKeyLen) { - SyHashEntry_Pr *pEntry; -#if defined(UNTRUST) - if(INVALID_HASH(pHash)) { - return 0; - } -#endif - if(pHash->nEntry < 1 || nKeyLen < 1) { - /* Don't bother hashing,return immediately */ - return 0; - } - pEntry = HashGetEntry(&(*pHash), pKey, nKeyLen); - if(pEntry == 0) { - return 0; - } - return (SyHashEntry *)pEntry; -} -static sxi32 HashDeleteEntry(SyHash *pHash, SyHashEntry_Pr *pEntry, void **ppUserData) { - sxi32 rc; - if(pEntry->pPrevCollide == 0) { - pHash->apBucket[pEntry->nHash & (pHash->nBucketSize - 1)] = pEntry->pNextCollide; - } else { - pEntry->pPrevCollide->pNextCollide = pEntry->pNextCollide; - } - if(pEntry->pNextCollide) { - pEntry->pNextCollide->pPrevCollide = pEntry->pPrevCollide; - } - MACRO_LD_REMOVE(pHash->pList, pEntry); - pHash->nEntry--; - if(ppUserData) { - /* Write a pointer to the user data */ - *ppUserData = pEntry->pUserData; - } - /* Release the entry */ - rc = SyMemBackendPoolFree(pHash->pAllocator, pEntry); - return rc; -} -PH7_PRIVATE sxi32 SyHashDeleteEntry(SyHash *pHash, const void *pKey, sxu32 nKeyLen, void **ppUserData) { - SyHashEntry_Pr *pEntry; - sxi32 rc; -#if defined(UNTRUST) - if(INVALID_HASH(pHash)) { - return SXERR_CORRUPT; - } -#endif - pEntry = HashGetEntry(&(*pHash), pKey, nKeyLen); - if(pEntry == 0) { - return SXERR_NOTFOUND; - } - rc = HashDeleteEntry(&(*pHash), pEntry, ppUserData); - return rc; -} -PH7_PRIVATE sxi32 SyHashDeleteEntry2(SyHashEntry *pEntry) { - SyHashEntry_Pr *pPtr = (SyHashEntry_Pr *)pEntry; - sxi32 rc; -#if defined(UNTRUST) - if(pPtr == 0 || INVALID_HASH(pPtr->pHash)) { - return SXERR_CORRUPT; - } -#endif - rc = HashDeleteEntry(pPtr->pHash, pPtr, 0); - return rc; -} -PH7_PRIVATE sxi32 SyHashResetLoopCursor(SyHash *pHash) { -#if defined(UNTRUST) - if(INVALID_HASH(pHash)) { - return SXERR_CORRUPT; - } -#endif - pHash->pCurrent = pHash->pList; - return SXRET_OK; -} -PH7_PRIVATE SyHashEntry *SyHashGetNextEntry(SyHash *pHash) { - SyHashEntry_Pr *pEntry; -#if defined(UNTRUST) - if(INVALID_HASH(pHash)) { - return 0; - } -#endif - if(pHash->pCurrent == 0 || pHash->nEntry <= 0) { - pHash->pCurrent = pHash->pList; - return 0; - } - pEntry = pHash->pCurrent; - /* Advance the cursor */ - pHash->pCurrent = pEntry->pNext; - /* Return the current entry */ - return (SyHashEntry *)pEntry; -} -PH7_PRIVATE sxi32 SyHashForEach(SyHash *pHash, sxi32(*xStep)(SyHashEntry *, void *), void *pUserData) { - SyHashEntry_Pr *pEntry; - sxi32 rc; - sxu32 n; -#if defined(UNTRUST) - if(INVALID_HASH(pHash) || xStep == 0) { - return 0; - } -#endif - pEntry = pHash->pList; - for(n = 0 ; n < pHash->nEntry ; n++) { - /* Invoke the callback */ - rc = xStep((SyHashEntry *)pEntry, pUserData); - if(rc != SXRET_OK) { - return rc; - } - /* Point to the next entry */ - pEntry = pEntry->pNext; - } - return SXRET_OK; -} -static sxi32 HashGrowTable(SyHash *pHash) { - sxu32 nNewSize = pHash->nBucketSize * 2; - SyHashEntry_Pr *pEntry; - SyHashEntry_Pr **apNew; - sxu32 n, iBucket; - /* Allocate a new larger table */ - apNew = (SyHashEntry_Pr **)SyMemBackendAlloc(pHash->pAllocator, nNewSize * sizeof(SyHashEntry_Pr *)); - if(apNew == 0) { - /* Not so fatal,simply a performance hit */ - return SXRET_OK; - } - /* Zero the new table */ - SyZero((void *)apNew, nNewSize * sizeof(SyHashEntry_Pr *)); - /* Rehash all entries */ - for(n = 0, pEntry = pHash->pList; n < pHash->nEntry ; n++) { - pEntry->pNextCollide = pEntry->pPrevCollide = 0; - /* Install in the new bucket */ - iBucket = pEntry->nHash & (nNewSize - 1); - pEntry->pNextCollide = apNew[iBucket]; - if(apNew[iBucket] != 0) { - apNew[iBucket]->pPrevCollide = pEntry; - } - apNew[iBucket] = pEntry; - /* Point to the next entry */ - pEntry = pEntry->pNext; - } - /* Release the old table and reflect the change */ - SyMemBackendFree(pHash->pAllocator, (void *)pHash->apBucket); - pHash->apBucket = apNew; - pHash->nBucketSize = nNewSize; - return SXRET_OK; -} -static sxi32 HashInsert(SyHash *pHash, SyHashEntry_Pr *pEntry) { - sxu32 iBucket = pEntry->nHash & (pHash->nBucketSize - 1); - /* Insert the entry in its corresponding bcuket */ - pEntry->pNextCollide = pHash->apBucket[iBucket]; - if(pHash->apBucket[iBucket] != 0) { - pHash->apBucket[iBucket]->pPrevCollide = pEntry; - } - pHash->apBucket[iBucket] = pEntry; - /* Link to the entry list */ - MACRO_LD_PUSH(pHash->pList, pEntry); - if(pHash->nEntry == 0) { - pHash->pCurrent = pHash->pList; - } - pHash->nEntry++; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyHashInsert(SyHash *pHash, const void *pKey, sxu32 nKeyLen, void *pUserData) { - SyHashEntry_Pr *pEntry; - sxi32 rc; -#if defined(UNTRUST) - if(INVALID_HASH(pHash) || pKey == 0) { - return SXERR_CORRUPT; - } -#endif - if(pHash->nEntry >= pHash->nBucketSize * SXHASH_FILL_FACTOR) { - rc = HashGrowTable(&(*pHash)); - if(rc != SXRET_OK) { - return rc; - } - } - /* Allocate a new hash entry */ - pEntry = (SyHashEntry_Pr *)SyMemBackendPoolAlloc(pHash->pAllocator, sizeof(SyHashEntry_Pr)); - if(pEntry == 0) { - return SXERR_MEM; - } - /* Zero the entry */ - SyZero(pEntry, sizeof(SyHashEntry_Pr)); - pEntry->pHash = pHash; - pEntry->pKey = pKey; - pEntry->nKeyLen = nKeyLen; - pEntry->pUserData = pUserData; - pEntry->nHash = pHash->xHash(pEntry->pKey, pEntry->nKeyLen); - /* Finally insert the entry in its corresponding bucket */ - rc = HashInsert(&(*pHash), pEntry); - return rc; -} -PH7_PRIVATE SyHashEntry *SyHashLastEntry(SyHash *pHash) { -#if defined(UNTRUST) - if(INVALID_HASH(pHash)) { - return 0; - } -#endif - /* Last inserted entry */ - return (SyHashEntry *)pHash->pList; -} -/* SyRunTimeApi:sxutils.c */ -PH7_PRIVATE sxi32 SyStrIsNumeric(const char *zSrc, sxu32 nLen, sxu8 *pReal, const char **pzTail) { - const char *zCur, *zEnd; -#ifdef UNTRUST - if(SX_EMPTY_STR(zSrc)) { - return SXERR_EMPTY; - } -#endif - zEnd = &zSrc[nLen]; - /* Jump leading white spaces */ - while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) { - zSrc++; - } - zCur = zSrc; - if(pReal) { - *pReal = FALSE; - } - for(;;) { - if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) { - break; - } - zSrc++; - if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) { - break; - } - zSrc++; - if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) { - break; - } - zSrc++; - if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) { - break; - } - zSrc++; - }; - if(zSrc < zEnd && zSrc > zCur) { - int c = zSrc[0]; - if(c == '.') { - zSrc++; - if(pReal) { - *pReal = TRUE; - } - if(pzTail) { - while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) { - zSrc++; - } - if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) { - zSrc++; - if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) { - zSrc++; - } - while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) { - zSrc++; - } - } - } - } else if(c == 'e' || c == 'E') { - zSrc++; - if(pReal) { - *pReal = TRUE; - } - if(pzTail) { - if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) { - zSrc++; - } - while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) { - zSrc++; - } - } - } - } - if(pzTail) { - /* Point to the non numeric part */ - *pzTail = zSrc; - } - return zSrc > zCur ? SXRET_OK /* String prefix is numeric */ : SXERR_INVALID /* Not a digit stream */; -} -#define SXINT32_MIN_STR "2147483648" -#define SXINT32_MAX_STR "2147483647" -#define SXINT64_MIN_STR "9223372036854775808" -#define SXINT64_MAX_STR "9223372036854775807" -PH7_PRIVATE sxi32 SyStrToInt32(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { - int isNeg = FALSE; - const char *zEnd; - sxi32 nVal = 0; - sxi16 i; -#if defined(UNTRUST) - if(SX_EMPTY_STR(zSrc)) { - if(pOutVal) { - *(sxi32 *)pOutVal = 0; - } - return SXERR_EMPTY; - } -#endif - zEnd = &zSrc[nLen]; - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { - isNeg = (zSrc[0] == '-') ? TRUE : FALSE; - zSrc++; - } - /* Skip leading zero */ - while(zSrc < zEnd && zSrc[0] == '0') { - zSrc++; - } - i = 10; - if((sxu32)(zEnd - zSrc) >= 10) { - /* Handle overflow */ - i = SyMemcmp(zSrc, (isNeg == TRUE) ? SXINT32_MIN_STR : SXINT32_MAX_STR, nLen) <= 0 ? 10 : 9; - } - for(;;) { - if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { - break; - } - nVal = nVal * 10 + (zSrc[0] - '0') ; - --i ; - zSrc++; - if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { - break; - } - nVal = nVal * 10 + (zSrc[0] - '0') ; - --i ; - zSrc++; - if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { - break; - } - nVal = nVal * 10 + (zSrc[0] - '0') ; - --i ; - zSrc++; - if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { - break; - } - nVal = nVal * 10 + (zSrc[0] - '0') ; - --i ; - zSrc++; - } - /* Skip trailing spaces */ - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zRest) { - *zRest = (char *)zSrc; - } - if(pOutVal) { - if(isNeg == TRUE && nVal != 0) { - nVal = -nVal; - } - *(sxi32 *)pOutVal = nVal; - } - return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; -} -PH7_PRIVATE sxi32 SyStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { - int isNeg = FALSE; - const char *zEnd; - sxi64 nVal; - sxi16 i; -#if defined(UNTRUST) - if(SX_EMPTY_STR(zSrc)) { - if(pOutVal) { - *(sxi32 *)pOutVal = 0; - } - return SXERR_EMPTY; - } -#endif - zEnd = &zSrc[nLen]; - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { - isNeg = (zSrc[0] == '-') ? TRUE : FALSE; - zSrc++; - } - /* Skip leading zero */ - while(zSrc < zEnd && zSrc[0] == '0') { - zSrc++; - } - i = 19; - if((sxu32)(zEnd - zSrc) >= 19) { - i = SyMemcmp(zSrc, isNeg ? SXINT64_MIN_STR : SXINT64_MAX_STR, 19) <= 0 ? 19 : 18 ; - } - nVal = 0; - for(;;) { - if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { - break; - } - nVal = nVal * 10 + (zSrc[0] - '0') ; - --i ; - zSrc++; - if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { - break; - } - nVal = nVal * 10 + (zSrc[0] - '0') ; - --i ; - zSrc++; - if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { - break; - } - nVal = nVal * 10 + (zSrc[0] - '0') ; - --i ; - zSrc++; - if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { - break; - } - nVal = nVal * 10 + (zSrc[0] - '0') ; - --i ; - zSrc++; - } - /* Skip trailing spaces */ - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zRest) { - *zRest = (char *)zSrc; - } - if(pOutVal) { - if(isNeg == TRUE && nVal != 0) { - nVal = -nVal; - } - *(sxi64 *)pOutVal = nVal; - } - return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; -} -PH7_PRIVATE sxi32 SyHexToint(sxi32 c) { - switch(c) { - case '0': - return 0; - case '1': - return 1; - case '2': - return 2; - case '3': - return 3; - case '4': - return 4; - case '5': - return 5; - case '6': - return 6; - case '7': - return 7; - case '8': - return 8; - case '9': - return 9; - case 'A': - case 'a': - return 10; - case 'B': - case 'b': - return 11; - case 'C': - case 'c': - return 12; - case 'D': - case 'd': - return 13; - case 'E': - case 'e': - return 14; - case 'F': - case 'f': - return 15; - } - return -1; -} -PH7_PRIVATE sxi32 SyHexStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { - const char *zIn, *zEnd; - int isNeg = FALSE; - sxi64 nVal = 0; -#if defined(UNTRUST) - if(SX_EMPTY_STR(zSrc)) { - if(pOutVal) { - *(sxi32 *)pOutVal = 0; - } - return SXERR_EMPTY; - } -#endif - zEnd = &zSrc[nLen]; - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zSrc < zEnd && (*zSrc == '-' || *zSrc == '+')) { - isNeg = (zSrc[0] == '-') ? TRUE : FALSE; - zSrc++; - } - if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'x' || zSrc[1] == 'X')) { - /* Bypass hex prefix */ - zSrc += sizeof(char) * 2; - } - /* Skip leading zero */ - while(zSrc < zEnd && zSrc[0] == '0') { - zSrc++; - } - zIn = zSrc; - for(;;) { - if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) { - break; - } - nVal = nVal * 16 + SyHexToint(zSrc[0]); - zSrc++ ; - if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) { - break; - } - nVal = nVal * 16 + SyHexToint(zSrc[0]); - zSrc++ ; - if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) { - break; - } - nVal = nVal * 16 + SyHexToint(zSrc[0]); - zSrc++ ; - if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) { - break; - } - nVal = nVal * 16 + SyHexToint(zSrc[0]); - zSrc++ ; - } - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zRest) { - *zRest = zSrc; - } - if(pOutVal) { - if(isNeg == TRUE && nVal != 0) { - nVal = -nVal; - } - *(sxi64 *)pOutVal = nVal; - } - return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX; -} -PH7_PRIVATE sxi32 SyOctalStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { - const char *zIn, *zEnd; - int isNeg = FALSE; - sxi64 nVal = 0; - int c; -#if defined(UNTRUST) - if(SX_EMPTY_STR(zSrc)) { - if(pOutVal) { - *(sxi32 *)pOutVal = 0; - } - return SXERR_EMPTY; - } -#endif - zEnd = &zSrc[nLen]; - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { - isNeg = (zSrc[0] == '-') ? TRUE : FALSE; - zSrc++; - } - /* Skip leading zero */ - while(zSrc < zEnd && zSrc[0] == '0') { - zSrc++; - } - zIn = zSrc; - for(;;) { - if(zSrc >= zEnd || !SyisDigit(zSrc[0])) { - break; - } - if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) { - break; - } - nVal = nVal * 8 + c; - zSrc++; - if(zSrc >= zEnd || !SyisDigit(zSrc[0])) { - break; - } - if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) { - break; - } - nVal = nVal * 8 + c; - zSrc++; - if(zSrc >= zEnd || !SyisDigit(zSrc[0])) { - break; - } - if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) { - break; - } - nVal = nVal * 8 + c; - zSrc++; - if(zSrc >= zEnd || !SyisDigit(zSrc[0])) { - break; - } - if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) { - break; - } - nVal = nVal * 8 + c; - zSrc++; - } - /* Skip trailing spaces */ - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zRest) { - *zRest = zSrc; - } - if(pOutVal) { - if(isNeg == TRUE && nVal != 0) { - nVal = -nVal; - } - *(sxi64 *)pOutVal = nVal; - } - return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; -} -PH7_PRIVATE sxi32 SyBinaryStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { - const char *zIn, *zEnd; - int isNeg = FALSE; - sxi64 nVal = 0; - int c; -#if defined(UNTRUST) - if(SX_EMPTY_STR(zSrc)) { - if(pOutVal) { - *(sxi32 *)pOutVal = 0; - } - return SXERR_EMPTY; - } -#endif - zEnd = &zSrc[nLen]; - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { - isNeg = (zSrc[0] == '-') ? TRUE : FALSE; - zSrc++; - } - if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'b' || zSrc[1] == 'B')) { - /* Bypass binary prefix */ - zSrc += sizeof(char) * 2; - } - /* Skip leading zero */ - while(zSrc < zEnd && zSrc[0] == '0') { - zSrc++; - } - zIn = zSrc; - for(;;) { - if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) { - break; - } - c = zSrc[0] - '0'; - nVal = (nVal << 1) + c; - zSrc++; - if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) { - break; - } - c = zSrc[0] - '0'; - nVal = (nVal << 1) + c; - zSrc++; - if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) { - break; - } - c = zSrc[0] - '0'; - nVal = (nVal << 1) + c; - zSrc++; - if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) { - break; - } - c = zSrc[0] - '0'; - nVal = (nVal << 1) + c; - zSrc++; - } - /* Skip trailing spaces */ - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zRest) { - *zRest = zSrc; - } - if(pOutVal) { - if(isNeg == TRUE && nVal != 0) { - nVal = -nVal; - } - *(sxi64 *)pOutVal = nVal; - } - return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; -} -PH7_PRIVATE sxi32 SyStrToReal(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { -#define SXDBL_DIG 15 -#define SXDBL_MAX_EXP 308 -#define SXDBL_MIN_EXP_PLUS 307 - static const sxreal aTab[] = { - 10, - 1.0e2, - 1.0e4, - 1.0e8, - 1.0e16, - 1.0e32, - 1.0e64, - 1.0e128, - 1.0e256 - }; - sxu8 neg = FALSE; - sxreal Val = 0.0; - const char *zEnd; - sxi32 Lim, exp; - sxreal *p = 0; -#ifdef UNTRUST - if(SX_EMPTY_STR(zSrc)) { - if(pOutVal) { - *(sxreal *)pOutVal = 0.0; - } - return SXERR_EMPTY; - } -#endif - zEnd = &zSrc[nLen]; - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { - neg = zSrc[0] == '-' ? TRUE : FALSE ; - zSrc++; - } - Lim = SXDBL_DIG ; - for(;;) { - if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { - break ; - } - Val = Val * 10.0 + (zSrc[0] - '0') ; - zSrc++ ; - --Lim; - if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { - break ; - } - Val = Val * 10.0 + (zSrc[0] - '0') ; - zSrc++ ; - --Lim; - if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { - break ; - } - Val = Val * 10.0 + (zSrc[0] - '0') ; - zSrc++ ; - --Lim; - if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { - break ; - } - Val = Val * 10.0 + (zSrc[0] - '0') ; - zSrc++ ; - --Lim; - } - if(zSrc < zEnd && (zSrc[0] == '.' || zSrc[0] == ',')) { - sxreal dec = 1.0; - zSrc++; - for(;;) { - if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { - break ; - } - Val = Val * 10.0 + (zSrc[0] - '0') ; - dec *= 10.0; - zSrc++ ; - --Lim; - if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { - break ; - } - Val = Val * 10.0 + (zSrc[0] - '0') ; - dec *= 10.0; - zSrc++ ; - --Lim; - if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { - break ; - } - Val = Val * 10.0 + (zSrc[0] - '0') ; - dec *= 10.0; - zSrc++ ; - --Lim; - if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { - break ; - } - Val = Val * 10.0 + (zSrc[0] - '0') ; - dec *= 10.0; - zSrc++ ; - --Lim; - } - Val /= dec; - } - if(neg == TRUE && Val != 0.0) { - Val = -Val ; - } - if(Lim <= 0) { - /* jump overflow digit */ - while(zSrc < zEnd) { - if(zSrc[0] == 'e' || zSrc[0] == 'E') { - break; - } - zSrc++; - } - } - neg = FALSE; - if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) { - zSrc++; - if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { - neg = zSrc[0] == '-' ? TRUE : FALSE ; - zSrc++; - } - exp = 0; - while(zSrc < zEnd && SyisDigit(zSrc[0]) && exp < SXDBL_MAX_EXP) { - exp = exp * 10 + (zSrc[0] - '0'); - zSrc++; - } - if(neg) { - if(exp > SXDBL_MIN_EXP_PLUS) { - exp = SXDBL_MIN_EXP_PLUS ; - } - } else if(exp > SXDBL_MAX_EXP) { - exp = SXDBL_MAX_EXP; - } - for(p = (sxreal *)aTab ; exp ; exp >>= 1, p++) { - if(exp & 01) { - if(neg) { - Val /= *p ; - } else { - Val *= *p; - } - } - } - } - while(zSrc < zEnd && SyisSpace(zSrc[0])) { - zSrc++; - } - if(zRest) { - *zRest = zSrc; - } - if(pOutVal) { - *(sxreal *)pOutVal = Val; - } - return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX; -} -/* SyRunTimeApi:sxlib.c */ -static sxu32 SyBinHash(const void *pSrc, sxu32 nLen) { - register unsigned char *zIn = (unsigned char *)pSrc; - unsigned char *zEnd; - sxu32 nH = 5381; - zEnd = &zIn[nLen]; - for(;;) { - if(zIn >= zEnd) { - break; - } - nH = nH * 33 + zIn[0] ; - zIn++; - if(zIn >= zEnd) { - break; - } - nH = nH * 33 + zIn[0] ; - zIn++; - if(zIn >= zEnd) { - break; - } - nH = nH * 33 + zIn[0] ; - zIn++; - if(zIn >= zEnd) { - break; - } - nH = nH * 33 + zIn[0] ; - zIn++; - } - return nH; -} -PH7_PRIVATE sxu32 SyStrHash(const void *pSrc, sxu32 nLen) { - register unsigned char *zIn = (unsigned char *)pSrc; - unsigned char *zEnd; - sxu32 nH = 5381; - zEnd = &zIn[nLen]; - for(;;) { - if(zIn >= zEnd) { - break; - } - nH = nH * 33 + SyToLower(zIn[0]); - zIn++; - if(zIn >= zEnd) { - break; - } - nH = nH * 33 + SyToLower(zIn[0]); - zIn++; - if(zIn >= zEnd) { - break; - } - nH = nH * 33 + SyToLower(zIn[0]); - zIn++; - if(zIn >= zEnd) { - break; - } - nH = nH * 33 + SyToLower(zIn[0]); - zIn++; - } - return nH; -} -#ifndef PH7_DISABLE_BUILTIN_FUNC -PH7_PRIVATE sxi32 SyBase64Encode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) { - static const unsigned char zBase64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - unsigned char *zIn = (unsigned char *)zSrc; - unsigned char z64[4]; - sxu32 i; - sxi32 rc; -#if defined(UNTRUST) - if(SX_EMPTY_STR(zSrc) || xConsumer == 0) { - return SXERR_EMPTY; - } -#endif - for(i = 0; i + 2 < nLen; i += 3) { - z64[0] = zBase64[(zIn[i] >> 2) & 0x3F]; - z64[1] = zBase64[(((zIn[i] & 0x03) << 4) | (zIn[i + 1] >> 4)) & 0x3F]; - z64[2] = zBase64[(((zIn[i + 1] & 0x0F) << 2) | (zIn[i + 2] >> 6)) & 0x3F]; - z64[3] = zBase64[ zIn[i + 2] & 0x3F]; - rc = xConsumer((const void *)z64, sizeof(z64), pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; - } - } - if(i + 1 < nLen) { - z64[0] = zBase64[(zIn[i] >> 2) & 0x3F]; - z64[1] = zBase64[(((zIn[i] & 0x03) << 4) | (zIn[i + 1] >> 4)) & 0x3F]; - z64[2] = zBase64[(zIn[i + 1] & 0x0F) << 2 ]; - z64[3] = '='; - rc = xConsumer((const void *)z64, sizeof(z64), pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; - } - } else if(i < nLen) { - z64[0] = zBase64[(zIn[i] >> 2) & 0x3F]; - z64[1] = zBase64[(zIn[i] & 0x03) << 4]; - z64[2] = '='; - z64[3] = '='; - rc = xConsumer((const void *)z64, sizeof(z64), pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; - } - } - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyBase64Decode(const char *zB64, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) { - static const sxu32 aBase64Trans[] = { - 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, - 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, - 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, - 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, - 0, 0, 0 - }; - sxu32 n, w, x, y, z; - sxi32 rc; - unsigned char zOut[10]; -#if defined(UNTRUST) - if(SX_EMPTY_STR(zB64) || xConsumer == 0) { - return SXERR_EMPTY; - } -#endif - while(nLen > 0 && zB64[nLen - 1] == '=') { - nLen--; - } - for(n = 0 ; n + 3 < nLen ; n += 4) { - w = aBase64Trans[zB64[n] & 0x7F]; - x = aBase64Trans[zB64[n + 1] & 0x7F]; - y = aBase64Trans[zB64[n + 2] & 0x7F]; - z = aBase64Trans[zB64[n + 3] & 0x7F]; - zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03); - zOut[1] = ((x << 4) & 0xF0) | ((y >> 2) & 0x0F); - zOut[2] = ((y << 6) & 0xC0) | (z & 0x3F); - rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 3, pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; - } - } - if(n + 2 < nLen) { - w = aBase64Trans[zB64[n] & 0x7F]; - x = aBase64Trans[zB64[n + 1] & 0x7F]; - y = aBase64Trans[zB64[n + 2] & 0x7F]; - zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03); - zOut[1] = ((x << 4) & 0xF0) | ((y >> 2) & 0x0F); - rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 2, pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; - } - } else if(n + 1 < nLen) { - w = aBase64Trans[zB64[n] & 0x7F]; - x = aBase64Trans[zB64[n + 1] & 0x7F]; - zOut[0] = ((w << 2) & 0xFC) | ((x >> 4) & 0x03); - rc = xConsumer((const void *)zOut, sizeof(unsigned char) * 1, pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; - } - } - return SXRET_OK; -} -#endif /* PH7_DISABLE_BUILTIN_FUNC */ -#define INVALID_LEXER(LEX) ( LEX == 0 || LEX->xTokenizer == 0 ) -PH7_PRIVATE sxi32 SyLexInit(SyLex *pLex, SySet *pSet, ProcTokenizer xTokenizer, void *pUserData) { - SyStream *pStream; -#if defined (UNTRUST) - if(pLex == 0 || xTokenizer == 0) { - return SXERR_CORRUPT; - } -#endif - pLex->pTokenSet = 0; - /* Initialize lexer fields */ - if(pSet) { - if(SySetElemSize(pSet) != sizeof(SyToken)) { - return SXERR_INVALID; - } - pLex->pTokenSet = pSet; - } - pStream = &pLex->sStream; - pLex->xTokenizer = xTokenizer; - pLex->pUserData = pUserData; - pStream->nLine = 1; - pStream->nIgn = 0; - pStream->zText = pStream->zEnd = 0; - pStream->pSet = pSet; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyLexTokenizeInput(SyLex *pLex, const char *zInput, sxu32 nLen, void *pCtxData, ProcSort xSort, ProcCmp xCmp) { - const unsigned char *zCur; - SyStream *pStream; - SyToken sToken; - sxi32 rc; -#if defined (UNTRUST) - if(INVALID_LEXER(pLex) || zInput == 0) { - return SXERR_CORRUPT; - } -#endif - pStream = &pLex->sStream; - /* Point to the head of the input */ - pStream->zText = pStream->zInput = (const unsigned char *)zInput; - /* Point to the end of the input */ - pStream->zEnd = &pStream->zInput[nLen]; - for(;;) { - if(pStream->zText >= pStream->zEnd) { - /* End of the input reached */ - break; - } - zCur = pStream->zText; - /* Call the tokenizer callback */ - rc = pLex->xTokenizer(pStream, &sToken, pLex->pUserData, pCtxData); - if(rc != SXRET_OK && rc != SXERR_CONTINUE) { - /* Tokenizer callback request an operation abort */ - if(rc == SXERR_ABORT) { - return SXERR_ABORT; - } - break; - } - if(rc == SXERR_CONTINUE) { - /* Request to ignore this token */ - pStream->nIgn++; - } else if(pLex->pTokenSet) { - /* Put the token in the set */ - rc = SySetPut(pLex->pTokenSet, (const void *)&sToken); - if(rc != SXRET_OK) { - break; - } - } - if(zCur >= pStream->zText) { - /* Automatic advance of the stream cursor */ - pStream->zText = &zCur[1]; - } - } - if(xSort && pLex->pTokenSet) { - SyToken *aToken = (SyToken *)SySetBasePtr(pLex->pTokenSet); - /* Sort the extrated tokens */ - if(xCmp == 0) { - /* Use a default comparison function */ - xCmp = SyMemcmp; - } - xSort(aToken, SySetUsed(pLex->pTokenSet), sizeof(SyToken), xCmp); - } - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyLexRelease(SyLex *pLex) { - sxi32 rc = SXRET_OK; -#if defined (UNTRUST) - if(INVALID_LEXER(pLex)) { - return SXERR_CORRUPT; - } -#else - SXUNUSED(pLex); /* Prevent compiler warning */ -#endif - return rc; -} -#ifndef PH7_DISABLE_BUILTIN_FUNC -#define SAFE_HTTP(C) (SyisAlphaNum(c) || c == '_' || c == '-' || c == '$' || c == '.' ) -PH7_PRIVATE sxi32 SyUriEncode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData) { - unsigned char *zIn = (unsigned char *)zSrc; - unsigned char zHex[3] = { '%', 0, 0 }; - unsigned char zOut[2]; - unsigned char *zCur, *zEnd; - sxi32 c; - sxi32 rc; -#ifdef UNTRUST - if(SX_EMPTY_STR(zSrc) || xConsumer == 0) { - return SXERR_EMPTY; - } -#endif - rc = SXRET_OK; - zEnd = &zIn[nLen]; - zCur = zIn; - for(;;) { - if(zCur >= zEnd) { - if(zCur != zIn) { - rc = xConsumer(zIn, (sxu32)(zCur - zIn), pUserData); - } - break; - } - c = zCur[0]; - if(SAFE_HTTP(c)) { - zCur++; - continue; - } - if(zCur != zIn && SXRET_OK != (rc = xConsumer(zIn, (sxu32)(zCur - zIn), pUserData))) { - break; - } - if(c == ' ') { - zOut[0] = '+'; - rc = xConsumer((const void *)zOut, sizeof(unsigned char), pUserData); - } else { - zHex[1] = "0123456789ABCDEF"[(c >> 4) & 0x0F]; - zHex[2] = "0123456789ABCDEF"[c & 0x0F]; - rc = xConsumer(zHex, sizeof(zHex), pUserData); - } - if(SXRET_OK != rc) { - break; - } - zIn = &zCur[1]; - zCur = zIn ; - } - return rc == SXRET_OK ? SXRET_OK : SXERR_ABORT; -} -#endif /* PH7_DISABLE_BUILTIN_FUNC */ -static sxi32 SyAsciiToHex(sxi32 c) { - if(c >= 'a' && c <= 'f') { - c += 10 - 'a'; - return c; - } - if(c >= '0' && c <= '9') { - c -= '0'; - return c; - } - if(c >= 'A' && c <= 'F') { - c += 10 - 'A'; - return c; - } - return 0; -} -PH7_PRIVATE sxi32 SyUriDecode(const char *zSrc, sxu32 nLen, ProcConsumer xConsumer, void *pUserData, int bUTF8) { - static const sxu8 Utf8Trans[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00 - }; - const char *zIn = zSrc; - const char *zEnd; - const char *zCur; - sxu8 *zOutPtr; - sxu8 zOut[10]; - sxi32 c, d; - sxi32 rc; -#if defined(UNTRUST) - if(SX_EMPTY_STR(zSrc) || xConsumer == 0) { - return SXERR_EMPTY; - } -#endif - rc = SXRET_OK; - zEnd = &zSrc[nLen]; - zCur = zIn; - for(;;) { - while(zCur < zEnd && zCur[0] != '%' && zCur[0] != '+') { - zCur++; - } - if(zCur != zIn) { - /* Consume input */ - rc = xConsumer(zIn, (unsigned int)(zCur - zIn), pUserData); - if(rc != SXRET_OK) { - /* User consumer routine request an operation abort */ - break; - } - } - if(zCur >= zEnd) { - rc = SXRET_OK; - break; - } - /* Decode unsafe HTTP characters */ - zOutPtr = zOut; - if(zCur[0] == '+') { - *zOutPtr++ = ' '; - zCur++; - } else { - if(&zCur[2] >= zEnd) { - rc = SXERR_OVERFLOW; - break; - } - c = (SyAsciiToHex(zCur[1]) << 4) | SyAsciiToHex(zCur[2]); - zCur += 3; - if(c < 0x000C0) { - *zOutPtr++ = (sxu8)c; - } else { - c = Utf8Trans[c - 0xC0]; - while(zCur[0] == '%') { - d = (SyAsciiToHex(zCur[1]) << 4) | SyAsciiToHex(zCur[2]); - if((d & 0xC0) != 0x80) { - break; - } - c = (c << 6) + (0x3f & d); - zCur += 3; - } - if(bUTF8 == FALSE) { - *zOutPtr++ = (sxu8)c; - } else { - SX_WRITE_UTF8(zOutPtr, c); - } - } - } - /* Consume the decoded characters */ - rc = xConsumer((const void *)zOut, (unsigned int)(zOutPtr - zOut), pUserData); - if(rc != SXRET_OK) { - break; - } - /* Synchronize pointers */ - zIn = zCur; - } - return rc; -} -#ifndef PH7_DISABLE_BUILTIN_FUNC -static const char *zEngDay[] = { - "Sunday", "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday" -}; -static const char *zEngMonth[] = { - "January", "February", "March", "April", - "May", "June", "July", "August", - "September", "October", "November", "December" -}; -static const char *GetDay(sxi32 i) { - return zEngDay[ i % 7 ]; -} -static const char *GetMonth(sxi32 i) { - return zEngMonth[ i % 12 ]; -} -PH7_PRIVATE const char *SyTimeGetDay(sxi32 iDay) { - return GetDay(iDay); -} -PH7_PRIVATE const char *SyTimeGetMonth(sxi32 iMonth) { - return GetMonth(iMonth); -} -#endif /* PH7_DISABLE_BUILTIN_FUNC */ -/* SyRunTimeApi: sxfmt.c */ -#define SXFMT_BUFSIZ 1024 /* Conversion buffer size */ -/* -** Conversion types fall into various categories as defined by the -** following enumeration. -*/ -#define SXFMT_RADIX 1 /* Integer types.%d, %x, %o, and so forth */ -#define SXFMT_FLOAT 2 /* Floating point.%f */ -#define SXFMT_EXP 3 /* Exponentional notation.%e and %E */ -#define SXFMT_GENERIC 4 /* Floating or exponential, depending on exponent.%g */ -#define SXFMT_SIZE 5 /* Total number of characters processed so far.%n */ -#define SXFMT_STRING 6 /* Strings.%s */ -#define SXFMT_PERCENT 7 /* Percent symbol.%% */ -#define SXFMT_CHARX 8 /* Characters.%c */ -#define SXFMT_ERROR 9 /* Used to indicate no such conversion type */ -/* Extension by Symisc Systems */ -#define SXFMT_RAWSTR 13 /* %z Pointer to raw string (SyString *) */ -#define SXFMT_UNUSED 15 -/* -** Allowed values for SyFmtInfo.flags -*/ -#define SXFLAG_SIGNED 0x01 -#define SXFLAG_UNSIGNED 0x02 -/* Allowed values for SyFmtConsumer.nType */ -#define SXFMT_CONS_PROC 1 /* Consumer is a procedure */ -#define SXFMT_CONS_STR 2 /* Consumer is a managed string */ -#define SXFMT_CONS_FILE 5 /* Consumer is an open File */ -#define SXFMT_CONS_BLOB 6 /* Consumer is a BLOB */ -/* -** Each builtin conversion character (ex: the 'd' in "%d") is described -** by an instance of the following structure -*/ -typedef struct SyFmtInfo SyFmtInfo; -struct SyFmtInfo { - char fmttype; /* The format field code letter [i.e: 'd','s','x'] */ - sxu8 base; /* The base for radix conversion */ - int flags; /* One or more of SXFLAG_ constants below */ - sxu8 type; /* Conversion paradigm */ - const char *charset; /* The character set for conversion */ - const char *prefix; /* Prefix on non-zero values in alt format */ -}; -typedef struct SyFmtConsumer SyFmtConsumer; -struct SyFmtConsumer { - sxu32 nLen; /* Total output length */ - sxi32 nType; /* Type of the consumer see below */ - sxi32 rc; /* Consumer return value;Abort processing if rc != SXRET_OK */ - union { - struct { - ProcConsumer xUserConsumer; - void *pUserData; - } sFunc; - SyBlob *pBlob; - } uConsumer; -}; -#ifndef SX_OMIT_FLOATINGPOINT -static int getdigit(sxlongreal *val, int *cnt) { - sxlongreal d; - int digit; - if((*cnt)++ >= 16) { - return '0'; - } - digit = (int) * val; - d = digit; - *val = (*val - d) * 10.0; - return digit + '0' ; -} -#endif /* SX_OMIT_FLOATINGPOINT */ -/* - * The following routine was taken from the SQLITE2 source tree and was - * extended by Symisc Systems to fit its need. - * Status: Public Domain - */ -static sxi32 InternFormat(ProcConsumer xConsumer, void *pUserData, const char *zFormat, va_list ap) { - /* - * The following table is searched linearly, so it is good to put the most frequently - * used conversion types first. - */ - static const SyFmtInfo aFmt[] = { - { 'd', 10, SXFLAG_SIGNED, SXFMT_RADIX, "0123456789", 0 }, - { 's', 0, 0, SXFMT_STRING, 0, 0 }, - { 'c', 0, 0, SXFMT_CHARX, 0, 0 }, - { 'x', 16, 0, SXFMT_RADIX, "0123456789abcdef", "x0" }, - { 'X', 16, 0, SXFMT_RADIX, "0123456789ABCDEF", "X0" }, - /* -- Extensions by Symisc Systems -- */ - { 'z', 0, 0, SXFMT_RAWSTR, 0, 0 }, /* Pointer to a raw string (SyString *) */ - { 'B', 2, 0, SXFMT_RADIX, "01", "b0"}, - /* -- End of Extensions -- */ - { 'o', 8, 0, SXFMT_RADIX, "01234567", "0" }, - { 'u', 10, 0, SXFMT_RADIX, "0123456789", 0 }, -#ifndef SX_OMIT_FLOATINGPOINT - { 'f', 0, SXFLAG_SIGNED, SXFMT_FLOAT, 0, 0 }, - { 'e', 0, SXFLAG_SIGNED, SXFMT_EXP, "e", 0 }, - { 'E', 0, SXFLAG_SIGNED, SXFMT_EXP, "E", 0 }, - { 'g', 0, SXFLAG_SIGNED, SXFMT_GENERIC, "e", 0 }, - { 'G', 0, SXFLAG_SIGNED, SXFMT_GENERIC, "E", 0 }, -#endif - { 'i', 10, SXFLAG_SIGNED, SXFMT_RADIX, "0123456789", 0 }, - { 'n', 0, 0, SXFMT_SIZE, 0, 0 }, - { '%', 0, 0, SXFMT_PERCENT, 0, 0 }, - { 'p', 10, 0, SXFMT_RADIX, "0123456789", 0 } - }; - int c; /* Next character in the format string */ - char *bufpt; /* Pointer to the conversion buffer */ - int precision; /* Precision of the current field */ - int length; /* Length of the field */ - int idx; /* A general purpose loop counter */ - int width; /* Width of the current field */ - sxu8 flag_leftjustify; /* True if "-" flag is present */ - sxu8 flag_plussign; /* True if "+" flag is present */ - sxu8 flag_blanksign; /* True if " " flag is present */ - sxu8 flag_alternateform; /* True if "#" flag is present */ - sxu8 flag_zeropad; /* True if field width constant starts with zero */ - sxu8 flag_long; /* True if "l" flag is present */ - sxi64 longvalue; /* Value for integer types */ - const SyFmtInfo *infop; /* Pointer to the appropriate info structure */ - char buf[SXFMT_BUFSIZ]; /* Conversion buffer */ - char prefix; /* Prefix character."+" or "-" or " " or '\0'.*/ - sxu8 errorflag = 0; /* True if an error is encountered */ - sxu8 xtype; /* Conversion paradigm */ - char *zExtra; - static char spaces[] = " "; -#define etSPACESIZE ((int)sizeof(spaces)-1) -#ifndef SX_OMIT_FLOATINGPOINT - sxlongreal realvalue; /* Value for real types */ - int exp; /* exponent of real numbers */ - double rounder; /* Used for rounding floating point values */ - sxu8 flag_dp; /* True if decimal point should be shown */ - sxu8 flag_rtz; /* True if trailing zeros should be removed */ - sxu8 flag_exp; /* True to force display of the exponent */ - int nsd; /* Number of significant digits returned */ -#endif - int rc; - length = 0; - bufpt = 0; - for(; (c = (*zFormat)) != 0; ++zFormat) { - if(c != '%') { - unsigned int amt; - bufpt = (char *)zFormat; - amt = 1; - while((c = (*++zFormat)) != '%' && c != 0) { - amt++; - } - rc = xConsumer((const void *)bufpt, amt, pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; /* Consumer routine request an operation abort */ - } - if(c == 0) { - return errorflag > 0 ? SXERR_FORMAT : SXRET_OK; - } - } - if((c = (*++zFormat)) == 0) { - errorflag = 1; - rc = xConsumer("%", sizeof("%") - 1, pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; /* Consumer routine request an operation abort */ - } - return errorflag > 0 ? SXERR_FORMAT : SXRET_OK; - } - /* Find out what flags are present */ - flag_leftjustify = flag_plussign = flag_blanksign = - flag_alternateform = flag_zeropad = 0; - do { - switch(c) { - case '-': - flag_leftjustify = 1; - c = 0; - break; - case '+': - flag_plussign = 1; - c = 0; - break; - case ' ': - flag_blanksign = 1; - c = 0; - break; - case '#': - flag_alternateform = 1; - c = 0; - break; - case '0': - flag_zeropad = 1; - c = 0; - break; - default: - break; - } - } while(c == 0 && (c = (*++zFormat)) != 0); - /* Get the field width */ - width = 0; - if(c == '*') { - width = va_arg(ap, int); - if(width < 0) { - flag_leftjustify = 1; - width = -width; - } - c = *++zFormat; - } else { - while(c >= '0' && c <= '9') { - width = width * 10 + c - '0'; - c = *++zFormat; - } - } - if(width > SXFMT_BUFSIZ - 10) { - width = SXFMT_BUFSIZ - 10; - } - /* Get the precision */ - precision = -1; - if(c == '.') { - precision = 0; - c = *++zFormat; - if(c == '*') { - precision = va_arg(ap, int); - if(precision < 0) { - precision = -precision; - } - c = *++zFormat; - } else { - while(c >= '0' && c <= '9') { - precision = precision * 10 + c - '0'; - c = *++zFormat; - } - } - } - /* Get the conversion type modifier */ - flag_long = 0; - if(c == 'l' || c == 'q' /* BSD quad (expect a 64-bit integer) */) { - flag_long = (c == 'q') ? 2 : 1; - c = *++zFormat; - if(c == 'l') { - /* Standard printf emulation 'lld' (expect a 64bit integer) */ - flag_long = 2; - } - } - /* Fetch the info entry for the field */ - infop = 0; - xtype = SXFMT_ERROR; - for(idx = 0; idx < (int)SX_ARRAYSIZE(aFmt); idx++) { - if(c == aFmt[idx].fmttype) { - infop = &aFmt[idx]; - xtype = infop->type; - break; - } - } - zExtra = 0; - /* - ** At this point, variables are initialized as follows: - ** - ** flag_alternateform TRUE if a '#' is present. - ** flag_plussign TRUE if a '+' is present. - ** flag_leftjustify TRUE if a '-' is present or if the - ** field width was negative. - ** flag_zeropad TRUE if the width began with 0. - ** flag_long TRUE if the letter 'l' (ell) or 'q'(BSD quad) prefixed - ** the conversion character. - ** flag_blanksign TRUE if a ' ' is present. - ** width The specified field width.This is - ** always non-negative.Zero is the default. - ** precision The specified precision.The default - ** is -1. - ** xtype The class of the conversion. - ** infop Pointer to the appropriate info struct. - */ - switch(xtype) { - case SXFMT_RADIX: - if(flag_long > 0) { - if(flag_long > 1) { - /* BSD quad: expect a 64-bit integer */ - longvalue = va_arg(ap, sxi64); - } else { - longvalue = va_arg(ap, sxlong); - } - } else { - if(infop->flags & SXFLAG_SIGNED) { - longvalue = va_arg(ap, sxi32); - } else { - longvalue = va_arg(ap, sxu32); - } - } - /* Limit the precision to prevent overflowing buf[] during conversion */ - if(precision > SXFMT_BUFSIZ - 40) { - precision = SXFMT_BUFSIZ - 40; - } -#if 1 - /* For the format %#x, the value zero is printed "0" not "0x0". - ** I think this is stupid.*/ - if(longvalue == 0) { - flag_alternateform = 0; - } -#else - /* More sensible: turn off the prefix for octal (to prevent "00"), - ** but leave the prefix for hex.*/ - if(longvalue == 0 && infop->base == 8) { - flag_alternateform = 0; - } -#endif - if(infop->flags & SXFLAG_SIGNED) { - if(longvalue < 0) { - longvalue = -longvalue; - /* Ticket 1433-003 */ - if(longvalue < 0) { - /* Overflow */ - longvalue = SXI64_HIGH; - } - prefix = '-'; - } else if(flag_plussign) { - prefix = '+'; - } else if(flag_blanksign) { - prefix = ' '; - } else { - prefix = 0; - } - } else { - if(longvalue < 0) { - longvalue = -longvalue; - /* Ticket 1433-003 */ - if(longvalue < 0) { - /* Overflow */ - longvalue = SXI64_HIGH; - } - } - prefix = 0; - } - if(flag_zeropad && precision < width - (prefix != 0)) { - precision = width - (prefix != 0); - } - bufpt = &buf[SXFMT_BUFSIZ - 1]; - { - register const char *cset; /* Use registers for speed */ - register int base; - cset = infop->charset; - base = infop->base; - do { /* Convert to ascii */ - *(--bufpt) = cset[longvalue % base]; - longvalue = longvalue / base; - } while(longvalue > 0); - } - length = &buf[SXFMT_BUFSIZ - 1] - bufpt; - for(idx = precision - length; idx > 0; idx--) { - *(--bufpt) = '0'; /* Zero pad */ - } - if(prefix) { - *(--bufpt) = prefix; /* Add sign */ - } - if(flag_alternateform && infop->prefix) { /* Add "0" or "0x" */ - const char *pre; - char x; - pre = infop->prefix; - if(*bufpt != pre[0]) { - for(pre = infop->prefix; (x = (*pre)) != 0; pre++) { - *(--bufpt) = x; - } - } - } - length = &buf[SXFMT_BUFSIZ - 1] - bufpt; - break; - case SXFMT_FLOAT: - case SXFMT_EXP: - case SXFMT_GENERIC: -#ifndef SX_OMIT_FLOATINGPOINT - realvalue = va_arg(ap, double); - if(precision < 0) { - precision = 6; /* Set default precision */ - } - if(precision > SXFMT_BUFSIZ - 40) { - precision = SXFMT_BUFSIZ - 40; - } - if(realvalue < 0.0) { - realvalue = -realvalue; - prefix = '-'; - } else { - if(flag_plussign) { - prefix = '+'; - } else if(flag_blanksign) { - prefix = ' '; - } else { - prefix = 0; - } - } - if(infop->type == SXFMT_GENERIC && precision > 0) { - precision--; - } - rounder = 0.0; -#if 0 - /* Rounding works like BSD when the constant 0.4999 is used.Wierd! */ - for(idx = precision, rounder = 0.4999; idx > 0; idx--, rounder *= 0.1); -#else - /* It makes more sense to use 0.5 */ - for(idx = precision, rounder = 0.5; idx > 0; idx--, rounder *= 0.1); -#endif - if(infop->type == SXFMT_FLOAT) { - realvalue += rounder; - } - /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ - exp = 0; - if(realvalue > 0.0) { - while(realvalue >= 1e8 && exp <= 350) { - realvalue *= 1e-8; - exp += 8; - } - while(realvalue >= 10.0 && exp <= 350) { - realvalue *= 0.1; - exp++; - } - while(realvalue < 1e-8 && exp >= -350) { - realvalue *= 1e8; - exp -= 8; - } - while(realvalue < 1.0 && exp >= -350) { - realvalue *= 10.0; - exp--; - } - if(exp > 350 || exp < -350) { - bufpt = "NaN"; - length = 3; - break; - } - } - bufpt = buf; - /* - ** If the field type is etGENERIC, then convert to either etEXP - ** or etFLOAT, as appropriate. - */ - flag_exp = xtype == SXFMT_EXP; - if(xtype != SXFMT_FLOAT) { - realvalue += rounder; - if(realvalue >= 10.0) { - realvalue *= 0.1; - exp++; - } - } - if(xtype == SXFMT_GENERIC) { - flag_rtz = !flag_alternateform; - if(exp < -4 || exp > precision) { - xtype = SXFMT_EXP; - } else { - precision = precision - exp; - xtype = SXFMT_FLOAT; - } - } else { - flag_rtz = 0; - } - /* - ** The "exp+precision" test causes output to be of type etEXP if - ** the precision is too large to fit in buf[]. - */ - nsd = 0; - if(xtype == SXFMT_FLOAT && exp + precision < SXFMT_BUFSIZ - 30) { - flag_dp = (precision > 0 || flag_alternateform); - if(prefix) { - *(bufpt++) = prefix; /* Sign */ - } - if(exp < 0) { - *(bufpt++) = '0'; /* Digits before "." */ - } else - for(; exp >= 0; exp--) { - *(bufpt++) = (char)getdigit(&realvalue, &nsd); - } - if(flag_dp) { - *(bufpt++) = '.'; /* The decimal point */ - } - for(exp++; exp < 0 && precision > 0; precision--, exp++) { - *(bufpt++) = '0'; - } - while((precision--) > 0) { - *(bufpt++) = (char)getdigit(&realvalue, &nsd); - } - *(bufpt--) = 0; /* Null terminate */ - if(flag_rtz && flag_dp) { /* Remove trailing zeros and "." */ - while(bufpt >= buf && *bufpt == '0') { - *(bufpt--) = 0; - } - if(bufpt >= buf && *bufpt == '.') { - *(bufpt--) = 0; - } - } - bufpt++; /* point to next free slot */ - } else { /* etEXP or etGENERIC */ - flag_dp = (precision > 0 || flag_alternateform); - if(prefix) { - *(bufpt++) = prefix; /* Sign */ - } - *(bufpt++) = (char)getdigit(&realvalue, &nsd); /* First digit */ - if(flag_dp) { - *(bufpt++) = '.'; /* Decimal point */ - } - while((precision--) > 0) { - *(bufpt++) = (char)getdigit(&realvalue, &nsd); - } - bufpt--; /* point to last digit */ - if(flag_rtz && flag_dp) { /* Remove tail zeros */ - while(bufpt >= buf && *bufpt == '0') { - *(bufpt--) = 0; - } - if(bufpt >= buf && *bufpt == '.') { - *(bufpt--) = 0; - } - } - bufpt++; /* point to next free slot */ - if(exp || flag_exp) { - *(bufpt++) = infop->charset[0]; - if(exp < 0) { - *(bufpt++) = '-'; /* sign of exp */ - exp = -exp; - } else { - *(bufpt++) = '+'; - } - if(exp >= 100) { - *(bufpt++) = (char)((exp / 100) + '0'); /* 100's digit */ - exp %= 100; - } - *(bufpt++) = (char)(exp / 10 + '0'); /* 10's digit */ - *(bufpt++) = (char)(exp % 10 + '0'); /* 1's digit */ - } - } - /* The converted number is in buf[] and zero terminated.Output it. - ** Note that the number is in the usual order, not reversed as with - ** integer conversions.*/ - length = bufpt - buf; - bufpt = buf; - /* Special case: Add leading zeros if the flag_zeropad flag is - ** set and we are not left justified */ - if(flag_zeropad && !flag_leftjustify && length < width) { - int i; - int nPad = width - length; - for(i = width; i >= nPad; i--) { - bufpt[i] = bufpt[i - nPad]; - } - i = prefix != 0; - while(nPad--) { - bufpt[i++] = '0'; - } - length = width; - } -#else - bufpt = " "; - length = (int)sizeof(" ") - 1; -#endif /* SX_OMIT_FLOATINGPOINT */ - break; - case SXFMT_SIZE: { - int *pSize = va_arg(ap, int *); - *pSize = ((SyFmtConsumer *)pUserData)->nLen; - length = width = 0; - } - break; - case SXFMT_PERCENT: - buf[0] = '%'; - bufpt = buf; - length = 1; - break; - case SXFMT_CHARX: - c = va_arg(ap, int); - buf[0] = (char)c; - /* Limit the precision to prevent overflowing buf[] during conversion */ - if(precision > SXFMT_BUFSIZ - 40) { - precision = SXFMT_BUFSIZ - 40; - } - if(precision >= 0) { - for(idx = 1; idx < precision; idx++) { - buf[idx] = (char)c; - } - length = precision; - } else { - length = 1; - } - bufpt = buf; - break; - case SXFMT_STRING: - bufpt = va_arg(ap, char *); - if(bufpt == 0) { - bufpt = " "; - length = (int)sizeof(" ") - 1; - break; - } - length = precision; - if(precision < 0) { - /* Symisc extension */ - length = (int)SyStrlen(bufpt); - } - if(precision >= 0 && precision < length) { - length = precision; - } - break; - case SXFMT_RAWSTR: { - /* Symisc extension */ - SyString *pStr = va_arg(ap, SyString *); - if(pStr == 0 || pStr->zString == 0) { - bufpt = " "; - length = (int)sizeof(char); - break; - } - bufpt = (char *)pStr->zString; - length = (int)pStr->nByte; - break; - } - case SXFMT_ERROR: - buf[0] = '?'; - bufpt = buf; - length = (int)sizeof(char); - if(c == 0) { - zFormat--; - } - break; - }/* End switch over the format type */ - /* - ** The text of the conversion is pointed to by "bufpt" and is - ** "length" characters long.The field width is "width".Do - ** the output. - */ - if(!flag_leftjustify) { - register int nspace; - nspace = width - length; - if(nspace > 0) { - while(nspace >= etSPACESIZE) { - rc = xConsumer(spaces, etSPACESIZE, pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; /* Consumer routine request an operation abort */ - } - nspace -= etSPACESIZE; - } - if(nspace > 0) { - rc = xConsumer(spaces, (unsigned int)nspace, pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; /* Consumer routine request an operation abort */ - } - } - } - } - if(length > 0) { - rc = xConsumer(bufpt, (unsigned int)length, pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; /* Consumer routine request an operation abort */ - } - } - if(flag_leftjustify) { - register int nspace; - nspace = width - length; - if(nspace > 0) { - while(nspace >= etSPACESIZE) { - rc = xConsumer(spaces, etSPACESIZE, pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; /* Consumer routine request an operation abort */ - } - nspace -= etSPACESIZE; - } - if(nspace > 0) { - rc = xConsumer(spaces, (unsigned int)nspace, pUserData); - if(rc != SXRET_OK) { - return SXERR_ABORT; /* Consumer routine request an operation abort */ - } - } - } - } - }/* End for loop over the format string */ - return errorflag ? SXERR_FORMAT : SXRET_OK; -} -static sxi32 FormatConsumer(const void *pSrc, unsigned int nLen, void *pData) { - SyFmtConsumer *pConsumer = (SyFmtConsumer *)pData; - sxi32 rc = SXERR_ABORT; - switch(pConsumer->nType) { - case SXFMT_CONS_PROC: - /* User callback */ - rc = pConsumer->uConsumer.sFunc.xUserConsumer(pSrc, nLen, pConsumer->uConsumer.sFunc.pUserData); - break; - case SXFMT_CONS_BLOB: - /* Blob consumer */ - rc = SyBlobAppend(pConsumer->uConsumer.pBlob, pSrc, (sxu32)nLen); - break; - default: - /* Unknown consumer */ - break; - } - /* Update total number of bytes consumed so far */ - pConsumer->nLen += nLen; - pConsumer->rc = rc; - return rc; -} -static sxi32 FormatMount(sxi32 nType, void *pConsumer, ProcConsumer xUserCons, void *pUserData, sxu32 *pOutLen, const char *zFormat, va_list ap) { - SyFmtConsumer sCons; - sCons.nType = nType; - sCons.rc = SXRET_OK; - sCons.nLen = 0; - if(pOutLen) { - *pOutLen = 0; - } - switch(nType) { - case SXFMT_CONS_PROC: -#if defined(UNTRUST) - if(xUserCons == 0) { - return SXERR_EMPTY; - } -#endif - sCons.uConsumer.sFunc.xUserConsumer = xUserCons; - sCons.uConsumer.sFunc.pUserData = pUserData; - break; - case SXFMT_CONS_BLOB: - sCons.uConsumer.pBlob = (SyBlob *)pConsumer; - break; - default: - return SXERR_UNKNOWN; - } - InternFormat(FormatConsumer, &sCons, zFormat, ap); - if(pOutLen) { - *pOutLen = sCons.nLen; - } - return sCons.rc; -} -PH7_PRIVATE sxi32 SyProcFormat(ProcConsumer xConsumer, void *pData, const char *zFormat, ...) { - va_list ap; - sxi32 rc; -#if defined(UNTRUST) - if(SX_EMPTY_STR(zFormat)) { - return SXERR_EMPTY; - } -#endif - va_start(ap, zFormat); - rc = FormatMount(SXFMT_CONS_PROC, 0, xConsumer, pData, 0, zFormat, ap); - va_end(ap); - return rc; -} -PH7_PRIVATE sxu32 SyBlobFormat(SyBlob *pBlob, const char *zFormat, ...) { - va_list ap; - sxu32 n; -#if defined(UNTRUST) - if(SX_EMPTY_STR(zFormat)) { - return 0; - } -#endif - va_start(ap, zFormat); - FormatMount(SXFMT_CONS_BLOB, &(*pBlob), 0, 0, &n, zFormat, ap); - va_end(ap); - return n; -} -PH7_PRIVATE sxu32 SyBlobFormatAp(SyBlob *pBlob, const char *zFormat, va_list ap) { - sxu32 n = 0; /* cc warning */ -#if defined(UNTRUST) - if(SX_EMPTY_STR(zFormat)) { - return 0; - } -#endif - FormatMount(SXFMT_CONS_BLOB, &(*pBlob), 0, 0, &n, zFormat, ap); - return n; -} -PH7_PRIVATE sxu32 SyBufferFormat(char *zBuf, sxu32 nLen, const char *zFormat, ...) { - SyBlob sBlob; - va_list ap; - sxu32 n; -#if defined(UNTRUST) - if(SX_EMPTY_STR(zFormat)) { - return 0; - } -#endif - if(SXRET_OK != SyBlobInitFromBuf(&sBlob, zBuf, nLen - 1)) { - return 0; - } - va_start(ap, zFormat); - FormatMount(SXFMT_CONS_BLOB, &sBlob, 0, 0, 0, zFormat, ap); - va_end(ap); - n = SyBlobLength(&sBlob); - /* Append the null terminator */ - sBlob.mByte++; - SyBlobAppend(&sBlob, "\0", sizeof(char)); - return n; -} -#ifndef PH7_DISABLE_BUILTIN_FUNC - -/* - * Zip File Format: - * - * Byte order: Little-endian - * - * [Local file header + Compressed data [+ Extended local header]?]* - * [Central directory]* - * [End of central directory record] - * - * Local file header:* - * Offset Length Contents - * 0 4 bytes Local file header signature (0x04034b50) - * 4 2 bytes Version needed to extract - * 6 2 bytes General purpose bit flag - * 8 2 bytes Compression method - * 10 2 bytes Last mod file time - * 12 2 bytes Last mod file date - * 14 4 bytes CRC-32 - * 18 4 bytes Compressed size (n) - * 22 4 bytes Uncompressed size - * 26 2 bytes Filename length (f) - * 28 2 bytes Extra field length (e) - * 30 (f)bytes Filename - * (e)bytes Extra field - * (n)bytes Compressed data - * - * Extended local header:* - * Offset Length Contents - * 0 4 bytes Extended Local file header signature (0x08074b50) - * 4 4 bytes CRC-32 - * 8 4 bytes Compressed size - * 12 4 bytes Uncompressed size - * - * Extra field:?(if any) - * Offset Length Contents - * 0 2 bytes Header ID (0x001 until 0xfb4a) see extended appnote from Info-zip - * 2 2 bytes Data size (g) - * (g) bytes (g) bytes of extra field - * - * Central directory:* - * Offset Length Contents - * 0 4 bytes Central file header signature (0x02014b50) - * 4 2 bytes Version made by - * 6 2 bytes Version needed to extract - * 8 2 bytes General purpose bit flag - * 10 2 bytes Compression method - * 12 2 bytes Last mod file time - * 14 2 bytes Last mod file date - * 16 4 bytes CRC-32 - * 20 4 bytes Compressed size - * 24 4 bytes Uncompressed size - * 28 2 bytes Filename length (f) - * 30 2 bytes Extra field length (e) - * 32 2 bytes File comment length (c) - * 34 2 bytes Disk number start - * 36 2 bytes Internal file attributes - * 38 4 bytes External file attributes - * 42 4 bytes Relative offset of local header - * 46 (f)bytes Filename - * (e)bytes Extra field - * (c)bytes File comment - * - * End of central directory record: - * Offset Length Contents - * 0 4 bytes End of central dir signature (0x06054b50) - * 4 2 bytes Number of this disk - * 6 2 bytes Number of the disk with the start of the central directory - * 8 2 bytes Total number of entries in the central dir on this disk - * 10 2 bytes Total number of entries in the central dir - * 12 4 bytes Size of the central directory - * 16 4 bytes Offset of start of central directory with respect to the starting disk number - * 20 2 bytes zipfile comment length (c) - * 22 (c)bytes zipfile comment - * - * compression method: (2 bytes) - * 0 - The file is stored (no compression) - * 1 - The file is Shrunk - * 2 - The file is Reduced with compression factor 1 - * 3 - The file is Reduced with compression factor 2 - * 4 - The file is Reduced with compression factor 3 - * 5 - The file is Reduced with compression factor 4 - * 6 - The file is Imploded - * 7 - Reserved for Tokenizing compression algorithm - * 8 - The file is Deflated - */ - -#define SXMAKE_ZIP_WORKBUF (SXU16_HIGH/2) /* 32KB Initial working buffer size */ -#define SXMAKE_ZIP_EXTRACT_VER 0x000a /* Version needed to extract */ -#define SXMAKE_ZIP_VER 0x003 /* Version made by */ - -#define SXZIP_CENTRAL_MAGIC 0x02014b50 -#define SXZIP_END_CENTRAL_MAGIC 0x06054b50 -#define SXZIP_LOCAL_MAGIC 0x04034b50 -/*#define SXZIP_CRC32_START 0xdebb20e3*/ - -#define SXZIP_LOCAL_HDRSZ 30 /* Local header size */ -#define SXZIP_LOCAL_EXT_HDRZ 16 /* Extended local header(footer) size */ -#define SXZIP_CENTRAL_HDRSZ 46 /* Central directory header size */ -#define SXZIP_END_CENTRAL_HDRSZ 22 /* End of central directory header size */ - -#define SXARCHIVE_HASH_SIZE 64 /* Starting hash table size(MUST BE POWER OF 2)*/ -static sxi32 SyLittleEndianUnpack32(sxu32 *uNB, const unsigned char *buf, sxu32 Len) { - if(Len < sizeof(sxu32)) { - return SXERR_SHORT; - } - *uNB = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24); - return SXRET_OK; -} -static sxi32 SyLittleEndianUnpack16(sxu16 *pOut, const unsigned char *zBuf, sxu32 nLen) { - if(nLen < sizeof(sxu16)) { - return SXERR_SHORT; - } - *pOut = zBuf[0] + (zBuf[1] << 8); - return SXRET_OK; -} -static sxi32 SyDosTimeFormat(sxu32 nDosDate, Sytm *pOut) { - sxu16 nDate; - sxu16 nTime; - nDate = nDosDate >> 16; - nTime = nDosDate & 0xFFFF; - pOut->tm_isdst = 0; - pOut->tm_year = 1980 + (nDate >> 9); - pOut->tm_mon = (nDate % (1 << 9)) >> 5; - pOut->tm_mday = (nDate % (1 << 9)) & 0x1F; - pOut->tm_hour = nTime >> 11; - pOut->tm_min = (nTime % (1 << 11)) >> 5; - pOut->tm_sec = ((nTime % (1 << 11)) & 0x1F) << 1; - return SXRET_OK; -} -/* - * Archive hashtable manager - */ -static sxi32 ArchiveHashGetEntry(SyArchive *pArch, const char *zName, sxu32 nLen, SyArchiveEntry **ppEntry) { - SyArchiveEntry *pBucketEntry; - SyString sEntry; - sxu32 nHash; - nHash = pArch->xHash(zName, nLen); - pBucketEntry = pArch->apHash[nHash & (pArch->nSize - 1)]; - SyStringInitFromBuf(&sEntry, zName, nLen); - for(;;) { - if(pBucketEntry == 0) { - break; - } - if(nHash == pBucketEntry->nHash && pArch->xCmp(&sEntry, &pBucketEntry->sFileName) == 0) { - if(ppEntry) { - *ppEntry = pBucketEntry; - } - return SXRET_OK; - } - pBucketEntry = pBucketEntry->pNextHash; - } - return SXERR_NOTFOUND; -} -static void ArchiveHashBucketInstall(SyArchiveEntry **apTable, sxu32 nBucket, SyArchiveEntry *pEntry) { - pEntry->pNextHash = apTable[nBucket]; - if(apTable[nBucket] != 0) { - apTable[nBucket]->pPrevHash = pEntry; - } - apTable[nBucket] = pEntry; -} -static sxi32 ArchiveHashGrowTable(SyArchive *pArch) { - sxu32 nNewSize = pArch->nSize * 2; - SyArchiveEntry **apNew; - SyArchiveEntry *pEntry; - sxu32 n; - /* Allocate a new table */ - apNew = (SyArchiveEntry **)SyMemBackendAlloc(pArch->pAllocator, nNewSize * sizeof(SyArchiveEntry *)); - if(apNew == 0) { - return SXRET_OK; /* Not so fatal,simply a performance hit */ - } - SyZero(apNew, nNewSize * sizeof(SyArchiveEntry *)); - /* Rehash old entries */ - for(n = 0, pEntry = pArch->pList ; n < pArch->nLoaded ; n++, pEntry = pEntry->pNext) { - pEntry->pNextHash = pEntry->pPrevHash = 0; - ArchiveHashBucketInstall(apNew, pEntry->nHash & (nNewSize - 1), pEntry); - } - /* Release the old table */ - SyMemBackendFree(pArch->pAllocator, pArch->apHash); - pArch->apHash = apNew; - pArch->nSize = nNewSize; - return SXRET_OK; -} -static sxi32 ArchiveHashInstallEntry(SyArchive *pArch, SyArchiveEntry *pEntry) { - if(pArch->nLoaded > pArch->nSize * 3) { - ArchiveHashGrowTable(&(*pArch)); - } - pEntry->nHash = pArch->xHash(SyStringData(&pEntry->sFileName), SyStringLength(&pEntry->sFileName)); - /* Install the entry in its bucket */ - ArchiveHashBucketInstall(pArch->apHash, pEntry->nHash & (pArch->nSize - 1), pEntry); - MACRO_LD_PUSH(pArch->pList, pEntry); - pArch->nLoaded++; - return SXRET_OK; -} -/* - * Parse the End of central directory and report status - */ -static sxi32 ParseEndOfCentralDirectory(SyArchive *pArch, const unsigned char *zBuf) { - sxu32 nMagic = 0; /* cc -O6 warning */ - sxi32 rc; - /* Sanity check */ - rc = SyLittleEndianUnpack32(&nMagic, zBuf, sizeof(sxu32)); - if(/* rc != SXRET_OK || */nMagic != SXZIP_END_CENTRAL_MAGIC) { - return SXERR_CORRUPT; - } - /* # of entries */ - rc = SyLittleEndianUnpack16((sxu16 *)&pArch->nEntry, &zBuf[8], sizeof(sxu16)); - if(/* rc != SXRET_OK || */ pArch->nEntry > SXI16_HIGH /* SXU16_HIGH */) { - return SXERR_CORRUPT; - } - /* Size of central directory */ - rc = SyLittleEndianUnpack32(&pArch->nCentralSize, &zBuf[12], sizeof(sxu32)); - if(/*rc != SXRET_OK ||*/ pArch->nCentralSize > SXI32_HIGH) { - return SXERR_CORRUPT; - } - /* Starting offset of central directory */ - rc = SyLittleEndianUnpack32(&pArch->nCentralOfft, &zBuf[16], sizeof(sxu32)); - if(/*rc != SXRET_OK ||*/ pArch->nCentralSize > SXI32_HIGH) { - return SXERR_CORRUPT; - } - return SXRET_OK; -} -/* - * Fill the zip entry with the appropriate information from the central directory - */ -static sxi32 GetCentralDirectoryEntry(SyArchive *pArch, SyArchiveEntry *pEntry, const unsigned char *zCentral, sxu32 *pNextOffset) { - SyString *pName = &pEntry->sFileName; /* File name */ - sxu16 nDosDate, nDosTime; - sxu16 nComment = 0 ; - sxu32 nMagic = 0; /* cc -O6 warning */ - sxi32 rc; - nDosDate = nDosTime = 0; /* cc -O6 warning */ - SXUNUSED(pArch); - /* Sanity check */ - rc = SyLittleEndianUnpack32(&nMagic, zCentral, sizeof(sxu32)); - if(/* rc != SXRET_OK || */ nMagic != SXZIP_CENTRAL_MAGIC) { - rc = SXERR_CORRUPT; - /* - * Try to recover by examing the next central directory record. - * Dont worry here,there is no risk of an infinite loop since - * the buffer size is delimited. - */ - /* pName->nByte = 0; nComment = 0; pName->nExtra = 0 */ - goto update; - } - /* - * entry name length - */ - SyLittleEndianUnpack16((sxu16 *)&pName->nByte, &zCentral[28], sizeof(sxu16)); - if(pName->nByte > SXI16_HIGH /* SXU16_HIGH */) { - rc = SXERR_BIG; - goto update; - } - /* Extra information */ - SyLittleEndianUnpack16(&pEntry->nExtra, &zCentral[30], sizeof(sxu16)); - /* Comment length */ - SyLittleEndianUnpack16(&nComment, &zCentral[32], sizeof(sxu16)); - /* Compression method 0 == stored / 8 == deflated */ - rc = SyLittleEndianUnpack16(&pEntry->nComprMeth, &zCentral[10], sizeof(sxu16)); - /* DOS Timestamp */ - SyLittleEndianUnpack16(&nDosTime, &zCentral[12], sizeof(sxu16)); - SyLittleEndianUnpack16(&nDosDate, &zCentral[14], sizeof(sxu16)); - SyDosTimeFormat((nDosDate << 16 | nDosTime), &pEntry->sFmt); - /* Little hack to fix month index */ - pEntry->sFmt.tm_mon--; - /* CRC32 */ - rc = SyLittleEndianUnpack32(&pEntry->nCrc, &zCentral[16], sizeof(sxu32)); - /* Content size before compression */ - rc = SyLittleEndianUnpack32(&pEntry->nByte, &zCentral[24], sizeof(sxu32)); - if(pEntry->nByte > SXI32_HIGH) { - rc = SXERR_BIG; - goto update; - } - /* - * Content size after compression. - * Note that if the file is stored pEntry->nByte should be equal to pEntry->nByteCompr - */ - rc = SyLittleEndianUnpack32(&pEntry->nByteCompr, &zCentral[20], sizeof(sxu32)); - if(pEntry->nByteCompr > SXI32_HIGH) { - rc = SXERR_BIG; - goto update; - } - /* Finally grab the contents offset */ - SyLittleEndianUnpack32(&pEntry->nOfft, &zCentral[42], sizeof(sxu32)); - if(pEntry->nOfft > SXI32_HIGH) { - rc = SXERR_BIG; - goto update; - } - rc = SXRET_OK; -update: - /* Update the offset to point to the next central directory record */ - *pNextOffset = SXZIP_CENTRAL_HDRSZ + pName->nByte + pEntry->nExtra + nComment; - return rc; /* Report failure or success */ -} -static sxi32 ZipFixOffset(SyArchiveEntry *pEntry, void *pSrc) { - sxu16 nExtra, nNameLen; - unsigned char *zHdr; - nExtra = nNameLen = 0; - zHdr = (unsigned char *)pSrc; - zHdr = &zHdr[pEntry->nOfft]; - if(SyMemcmp(zHdr, "PK\003\004", sizeof(sxu32)) != 0) { - return SXERR_CORRUPT; - } - SyLittleEndianUnpack16(&nNameLen, &zHdr[26], sizeof(sxu16)); - SyLittleEndianUnpack16(&nExtra, &zHdr[28], sizeof(sxu16)); - /* Fix contents offset */ - pEntry->nOfft += SXZIP_LOCAL_HDRSZ + nExtra + nNameLen; - return SXRET_OK; -} -/* - * Extract all valid entries from the central directory - */ -static sxi32 ZipExtract(SyArchive *pArch, const unsigned char *zCentral, sxu32 nLen, void *pSrc) { - SyArchiveEntry *pEntry, *pDup; - const unsigned char *zEnd ; /* End of central directory */ - sxu32 nIncr, nOfft; /* Central Offset */ - SyString *pName; /* Entry name */ - char *zName; - sxi32 rc; - nOfft = nIncr = 0; - zEnd = &zCentral[nLen]; - for(;;) { - if(&zCentral[nOfft] >= zEnd) { - break; - } - /* Add a new entry */ - pEntry = (SyArchiveEntry *)SyMemBackendPoolAlloc(pArch->pAllocator, sizeof(SyArchiveEntry)); - if(pEntry == 0) { - break; - } - SyZero(pEntry, sizeof(SyArchiveEntry)); - pEntry->nMagic = SXARCH_MAGIC; - nIncr = 0; - rc = GetCentralDirectoryEntry(&(*pArch), pEntry, &zCentral[nOfft], &nIncr); - if(rc == SXRET_OK) { - /* Fix the starting record offset so we can access entry contents correctly */ - rc = ZipFixOffset(pEntry, pSrc); - } - if(rc != SXRET_OK) { - sxu32 nJmp = 0; - SyMemBackendPoolFree(pArch->pAllocator, pEntry); - /* Try to recover by brute-forcing for a valid central directory record */ - if(SXRET_OK == SyBlobSearch((const void *)&zCentral[nOfft + nIncr], (sxu32)(zEnd - &zCentral[nOfft + nIncr]), - (const void *)"PK\001\002", sizeof(sxu32), &nJmp)) { - nOfft += nIncr + nJmp; /* Check next entry */ - continue; - } - break; /* Giving up,archive is hopelessly corrupted */ - } - pName = &pEntry->sFileName; - pName->zString = (const char *)&zCentral[nOfft + SXZIP_CENTRAL_HDRSZ]; - if(pName->nByte <= 0 || (pEntry->nByte <= 0 && pName->zString[pName->nByte - 1] != '/')) { - /* Ignore zero length records (except folders) and records without names */ - SyMemBackendPoolFree(pArch->pAllocator, pEntry); - nOfft += nIncr; /* Check next entry */ - continue; - } - zName = SyMemBackendStrDup(pArch->pAllocator, pName->zString, pName->nByte); - if(zName == 0) { - SyMemBackendPoolFree(pArch->pAllocator, pEntry); - nOfft += nIncr; /* Check next entry */ - continue; - } - pName->zString = (const char *)zName; - /* Check for duplicates */ - rc = ArchiveHashGetEntry(&(*pArch), pName->zString, pName->nByte, &pDup); - if(rc == SXRET_OK) { - /* Another entry with the same name exists ; link them together */ - pEntry->pNextName = pDup->pNextName; - pDup->pNextName = pEntry; - pDup->nDup++; - } else { - /* Insert in hashtable */ - ArchiveHashInstallEntry(pArch, pEntry); - } - nOfft += nIncr; /* Check next record */ - } - pArch->pCursor = pArch->pList; - return pArch->nLoaded > 0 ? SXRET_OK : SXERR_EMPTY; -} -PH7_PRIVATE sxi32 SyZipExtractFromBuf(SyArchive *pArch, const char *zBuf, sxu32 nLen) { - const unsigned char *zCentral, *zEnd; - sxi32 rc; -#if defined(UNTRUST) - if(SXARCH_INVALID(pArch) || zBuf == 0) { - return SXERR_INVALID; - } -#endif - /* The miminal size of a zip archive: - * LOCAL_HDR_SZ + CENTRAL_HDR_SZ + END_OF_CENTRAL_HDR_SZ - * 30 46 22 - */ - if(nLen < SXZIP_LOCAL_HDRSZ + SXZIP_CENTRAL_HDRSZ + SXZIP_END_CENTRAL_HDRSZ) { - return SXERR_CORRUPT; /* Don't bother processing return immediately */ - } - zEnd = (unsigned char *)&zBuf[nLen - SXZIP_END_CENTRAL_HDRSZ]; - /* Find the end of central directory */ - while(((sxu32)((unsigned char *)&zBuf[nLen] - zEnd) < (SXZIP_END_CENTRAL_HDRSZ + SXI16_HIGH)) && - zEnd > (unsigned char *)zBuf && SyMemcmp(zEnd, "PK\005\006", sizeof(sxu32)) != 0) { - zEnd--; - } - /* Parse the end of central directory */ - rc = ParseEndOfCentralDirectory(&(*pArch), zEnd); - if(rc != SXRET_OK) { - return rc; - } - /* Find the starting offset of the central directory */ - zCentral = &zEnd[-(sxi32)pArch->nCentralSize]; - if(zCentral <= (unsigned char *)zBuf || SyMemcmp(zCentral, "PK\001\002", sizeof(sxu32)) != 0) { - if(pArch->nCentralOfft >= nLen) { - /* Corrupted central directory offset */ - return SXERR_CORRUPT; - } - zCentral = (unsigned char *)&zBuf[pArch->nCentralOfft]; - if(SyMemcmp(zCentral, "PK\001\002", sizeof(sxu32)) != 0) { - /* Corrupted zip archive */ - return SXERR_CORRUPT; - } - /* Fall thru and extract all valid entries from the central directory */ - } - rc = ZipExtract(&(*pArch), zCentral, (sxu32)(zEnd - zCentral), (void *)zBuf); - return rc; -} -/* - * Default comparison function. - */ -static sxi32 ArchiveHashCmp(const SyString *pStr1, const SyString *pStr2) { - sxi32 rc; - rc = SyStringCmp(pStr1, pStr2, SyMemcmp); - return rc; -} -PH7_PRIVATE sxi32 SyArchiveInit(SyArchive *pArch, SyMemBackend *pAllocator, ProcHash xHash, ProcRawStrCmp xCmp) { - SyArchiveEntry **apHash; -#if defined(UNTRUST) - if(pArch == 0) { - return SXERR_EMPTY; - } -#endif - SyZero(pArch, sizeof(SyArchive)); - /* Allocate a new hashtable */ - apHash = (SyArchiveEntry **)SyMemBackendAlloc(&(*pAllocator), SXARCHIVE_HASH_SIZE * sizeof(SyArchiveEntry *)); - if(apHash == 0) { - return SXERR_MEM; - } - SyZero(apHash, SXARCHIVE_HASH_SIZE * sizeof(SyArchiveEntry *)); - pArch->apHash = apHash; - pArch->xHash = xHash ? xHash : SyBinHash; - pArch->xCmp = xCmp ? xCmp : ArchiveHashCmp; - pArch->nSize = SXARCHIVE_HASH_SIZE; - pArch->pAllocator = &(*pAllocator); - pArch->nMagic = SXARCH_MAGIC; - return SXRET_OK; -} -static sxi32 ArchiveReleaseEntry(SyMemBackend *pAllocator, SyArchiveEntry *pEntry) { - SyArchiveEntry *pDup = pEntry->pNextName; - SyArchiveEntry *pNextDup; - /* Release duplicates first since there are not stored in the hashtable */ - for(;;) { - if(pEntry->nDup == 0) { - break; - } - pNextDup = pDup->pNextName; - pDup->nMagic = 0x2661; - SyMemBackendFree(pAllocator, (void *)SyStringData(&pDup->sFileName)); - SyMemBackendPoolFree(pAllocator, pDup); - pDup = pNextDup; - pEntry->nDup--; - } - pEntry->nMagic = 0x2661; - SyMemBackendFree(pAllocator, (void *)SyStringData(&pEntry->sFileName)); - SyMemBackendPoolFree(pAllocator, pEntry); - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyArchiveRelease(SyArchive *pArch) { - SyArchiveEntry *pEntry, *pNext; - pEntry = pArch->pList; - for(;;) { - if(pArch->nLoaded < 1) { - break; - } - pNext = pEntry->pNext; - MACRO_LD_REMOVE(pArch->pList, pEntry); - ArchiveReleaseEntry(pArch->pAllocator, pEntry); - pEntry = pNext; - pArch->nLoaded--; - } - SyMemBackendFree(pArch->pAllocator, pArch->apHash); - pArch->pCursor = 0; - pArch->nMagic = 0x2626; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyArchiveResetLoopCursor(SyArchive *pArch) { - pArch->pCursor = pArch->pList; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyArchiveGetNextEntry(SyArchive *pArch, SyArchiveEntry **ppEntry) { - SyArchiveEntry *pNext; - if(pArch->pCursor == 0) { - /* Rewind the cursor */ - pArch->pCursor = pArch->pList; - return SXERR_EOF; - } - *ppEntry = pArch->pCursor; - pNext = pArch->pCursor->pNext; - /* Advance the cursor to the next entry */ - pArch->pCursor = pNext; - return SXRET_OK; -} -#endif /* PH7_DISABLE_BUILTIN_FUNC */ -/* - * Psuedo Random Number Generator (PRNG) - * @authors: SQLite authors - * @status: Public Domain - * NOTE: - * Nothing in this file or anywhere else in the library does any kind of - * encryption.The RC4 algorithm is being used as a PRNG (pseudo-random - * number generator) not as an encryption device. - */ -#define SXPRNG_MAGIC 0x13C4 -#ifdef __UNIXES__ - #include - #include - #include - #include - #include - #include - #include -#endif -static sxi32 SyOSUtilRandomSeed(void *pBuf, sxu32 nLen, void *pUnused) { - char *zBuf = (char *)pBuf; -#ifdef __WINNT__ - DWORD nProcessID; /* Yes,keep it uninitialized when compiling using the MinGW32 builds tools */ -#elif defined(__UNIXES__) - pid_t pid; - int fd; -#else - char zGarbage[128]; /* Yes,keep this buffer uninitialized */ -#endif - SXUNUSED(pUnused); -#ifdef __WINNT__ -#ifndef __MINGW32__ - nProcessID = GetProcessId(GetCurrentProcess()); -#endif - SyMemcpy((const void *)&nProcessID, zBuf, SXMIN(nLen, sizeof(DWORD))); - if((sxu32)(&zBuf[nLen] - &zBuf[sizeof(DWORD)]) >= sizeof(SYSTEMTIME)) { - GetSystemTime((LPSYSTEMTIME)&zBuf[sizeof(DWORD)]); - } -#elif defined(__UNIXES__) - fd = open("/dev/urandom", O_RDONLY); - if(fd >= 0) { - if(read(fd, zBuf, nLen) > 0) { - close(fd); - return SXRET_OK; - } - /* FALL THRU */ - } - close(fd); - pid = getpid(); - SyMemcpy((const void *)&pid, zBuf, SXMIN(nLen, sizeof(pid_t))); - if(&zBuf[nLen] - &zBuf[sizeof(pid_t)] >= (int)sizeof(struct timeval)) { - gettimeofday((struct timeval *)&zBuf[sizeof(pid_t)], 0); - } -#else - /* Fill with uninitialized data */ - SyMemcpy(zGarbage, zBuf, SXMIN(nLen, sizeof(zGarbage))); -#endif - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyRandomnessInit(SyPRNGCtx *pCtx, ProcRandomSeed xSeed, void *pUserData) { - char zSeed[256]; - sxu8 t; - sxi32 rc; - sxu32 i; - if(pCtx->nMagic == SXPRNG_MAGIC) { - return SXRET_OK; /* Already initialized */ - } - /* Initialize the state of the random number generator once, - ** the first time this routine is called.The seed value does - ** not need to contain a lot of randomness since we are not - ** trying to do secure encryption or anything like that... - */ - if(xSeed == 0) { - xSeed = SyOSUtilRandomSeed; - } - rc = xSeed(zSeed, sizeof(zSeed), pUserData); - if(rc != SXRET_OK) { - return rc; - } - pCtx->i = pCtx->j = 0; - for(i = 0; i < SX_ARRAYSIZE(pCtx->s) ; i++) { - pCtx->s[i] = (unsigned char)i; - } - for(i = 0; i < sizeof(zSeed) ; i++) { - pCtx->j += pCtx->s[i] + zSeed[i]; - t = pCtx->s[pCtx->j]; - pCtx->s[pCtx->j] = pCtx->s[i]; - pCtx->s[i] = t; - } - pCtx->nMagic = SXPRNG_MAGIC; - return SXRET_OK; -} -/* - * Get a single 8-bit random value using the RC4 PRNG. - */ -static sxu8 randomByte(SyPRNGCtx *pCtx) { - sxu8 t; - /* Generate and return single random byte */ - pCtx->i++; - t = pCtx->s[pCtx->i]; - pCtx->j += t; - pCtx->s[pCtx->i] = pCtx->s[pCtx->j]; - pCtx->s[pCtx->j] = t; - t += pCtx->s[pCtx->i]; - return pCtx->s[t]; -} -PH7_PRIVATE sxi32 SyRandomness(SyPRNGCtx *pCtx, void *pBuf, sxu32 nLen) { - unsigned char *zBuf = (unsigned char *)pBuf; - unsigned char *zEnd = &zBuf[nLen]; -#if defined(UNTRUST) - if(pCtx == 0 || pBuf == 0 || nLen <= 0) { - return SXERR_EMPTY; - } -#endif - if(pCtx->nMagic != SXPRNG_MAGIC) { - return SXERR_CORRUPT; - } - for(;;) { - if(zBuf >= zEnd) { - break; - } - zBuf[0] = randomByte(pCtx); - zBuf++; - if(zBuf >= zEnd) { - break; - } - zBuf[0] = randomByte(pCtx); - zBuf++; - if(zBuf >= zEnd) { - break; - } - zBuf[0] = randomByte(pCtx); - zBuf++; - if(zBuf >= zEnd) { - break; - } - zBuf[0] = randomByte(pCtx); - zBuf++; - } - return SXRET_OK; -} -#ifndef PH7_DISABLE_BUILTIN_FUNC -#ifndef PH7_DISABLE_HASH_FUNC -/* SyRunTimeApi: sxhash.c */ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest.This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ -#define SX_MD5_BINSZ 16 -#define SX_MD5_HEXSZ 32 -/* - * Note: this code is harmless on little-endian machines. - */ -static void byteReverse(unsigned char *buf, unsigned longs) { - sxu32 t; - do { - t = (sxu32)((unsigned)buf[3] << 8 | buf[2]) << 16 | - ((unsigned)buf[1] << 8 | buf[0]); - *(sxu32 *)buf = t; - buf += 4; - } while(--longs); -} -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#ifdef F1 - #undef F1 -#endif -#ifdef F2 - #undef F2 -#endif -#ifdef F3 - #undef F3 -#endif -#ifdef F4 - #undef F4 -#endif - -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm.*/ -#define SX_MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data.MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void MD5Transform(sxu32 buf[4], const sxu32 in[16]) { - register sxu32 a, b, c, d; - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - SX_MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7); - SX_MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12); - SX_MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17); - SX_MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22); - SX_MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7); - SX_MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12); - SX_MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17); - SX_MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22); - SX_MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7); - SX_MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12); - SX_MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - SX_MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - SX_MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - SX_MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - SX_MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - SX_MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - SX_MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5); - SX_MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9); - SX_MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - SX_MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20); - SX_MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5); - SX_MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - SX_MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - SX_MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20); - SX_MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5); - SX_MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - SX_MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14); - SX_MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20); - SX_MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - SX_MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9); - SX_MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14); - SX_MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - SX_MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4); - SX_MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11); - SX_MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - SX_MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - SX_MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4); - SX_MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11); - SX_MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16); - SX_MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - SX_MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - SX_MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11); - SX_MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16); - SX_MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23); - SX_MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4); - SX_MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - SX_MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - SX_MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23); - SX_MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6); - SX_MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10); - SX_MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - SX_MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21); - SX_MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - SX_MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10); - SX_MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - SX_MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21); - SX_MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f, 6); - SX_MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - SX_MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15); - SX_MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - SX_MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82, 6); - SX_MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - SX_MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15); - SX_MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21); - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -PH7_PRIVATE void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len) { - sxu32 t; - /* Update bitcount */ - t = ctx->bits[0]; - if((ctx->bits[0] = t + ((sxu32)len << 3)) < t) { - ctx->bits[1]++; /* Carry from low to high */ - } - ctx->bits[1] += len >> 29; - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - /* Handle any leading odd-sized chunks */ - if(t) { - unsigned char *p = (unsigned char *)ctx->in + t; - t = 64 - t; - if(len < t) { - SyMemcpy(buf, p, len); - return; - } - SyMemcpy(buf, p, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (sxu32 *)ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - while(len >= 64) { - SyMemcpy(buf, ctx->in, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (sxu32 *)ctx->in); - buf += 64; - len -= 64; - } - /* Handle any remaining bytes of data.*/ - SyMemcpy(buf, ctx->in, len); -} -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -PH7_PRIVATE void MD5Final(unsigned char digest[16], MD5Context *ctx) { - unsigned count; - unsigned char *p; - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - /* Set the first char of padding to 0x80.This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - /* Pad out to 56 mod 64 */ - if(count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - SyZero(p, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (sxu32 *)ctx->in); - /* Now fill the next block with 56 bytes */ - SyZero(ctx->in, 56); - } else { - /* Pad block to 56 bytes */ - SyZero(p, count - 8); - } - byteReverse(ctx->in, 14); - /* Append length in bits and transform */ - ((sxu32 *)ctx->in)[ 14 ] = ctx->bits[0]; - ((sxu32 *)ctx->in)[ 15 ] = ctx->bits[1]; - MD5Transform(ctx->buf, (sxu32 *)ctx->in); - byteReverse((unsigned char *)ctx->buf, 4); - SyMemcpy(ctx->buf, digest, 0x10); - SyZero(ctx, sizeof(ctx)); /* In case it's sensitive */ -} -#undef F1 -#undef F2 -#undef F3 -#undef F4 -PH7_PRIVATE sxi32 MD5Init(MD5Context *pCtx) { - pCtx->buf[0] = 0x67452301; - pCtx->buf[1] = 0xefcdab89; - pCtx->buf[2] = 0x98badcfe; - pCtx->buf[3] = 0x10325476; - pCtx->bits[0] = 0; - pCtx->bits[1] = 0; - return SXRET_OK; -} -PH7_PRIVATE sxi32 SyMD5Compute(const void *pIn, sxu32 nLen, unsigned char zDigest[16]) { - MD5Context sCtx; - MD5Init(&sCtx); - MD5Update(&sCtx, (const unsigned char *)pIn, nLen); - MD5Final(zDigest, &sCtx); - return SXRET_OK; -} -/* - * SHA-1 in C - * By Steve Reid - * Status: Public Domain - */ -/* - * blk0() and blk() perform the initial expand. - * I got the idea of expanding during the round function from SSLeay - * - * blk0le() for little-endian and blk0be() for big-endian. - */ -#if __GNUC__ && (defined(__i386__) || defined(__x86_64__)) -/* - * GCC by itself only generates left rotates. Use right rotates if - * possible to be kinder to dinky implementations with iterative rotate - * instructions. - */ -#define SHA_ROT(op, x, k) \ - ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; }) -#define rol(x,k) SHA_ROT("roll", x, k) -#define ror(x,k) SHA_ROT("rorl", x, k) - -#else -/* Generic C equivalent */ -#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r)) -#define rol(x,k) SHA_ROT(x,k,32-(k)) -#define ror(x,k) SHA_ROT(x,32-(k),k) -#endif - -#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \ - |(rol(block[i],8)&0x00FF00FF)) -#define blk0be(i) block[i] -#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \ - ^block[(i+2)&15]^block[i&15],1)) - -/* - * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1 - * - * Rl0() for little-endian and Rb0() for big-endian. Endianness is - * determined at run-time. - */ -#define Rl0(v,w,x,y,z,i) \ - z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2); -#define Rb0(v,w,x,y,z,i) \ - z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2); -#define R1(v,w,x,y,z,i) \ - z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2); -#define R2(v,w,x,y,z,i) \ - z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2); -#define R3(v,w,x,y,z,i) \ - z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2); -#define R4(v,w,x,y,z,i) \ - z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2); - -/* - * Hash a single 512-bit block. This is the core of the algorithm. - */ -#define a qq[0] -#define b qq[1] -#define c qq[2] -#define d qq[3] -#define e qq[4] - -static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64]) { - unsigned int qq[5]; /* a, b, c, d, e; */ - static int one = 1; - unsigned int block[16]; - SyMemcpy(buffer, (void *)block, 64); - SyMemcpy(state, qq, 5 * sizeof(unsigned int)); - /* Copy context->state[] to working vars */ - /* - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - */ - /* 4 rounds of 20 operations each. Loop unrolled. */ - if(1 == *(unsigned char *)&one) { - 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); - 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); - 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); - 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); - } else { - 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); - 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); - 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); - 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); - } - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - 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); - /* Add the working vars back into context.state[] */ - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; -} -#undef a -#undef b -#undef c -#undef d -#undef e -/* - * SHA1Init - Initialize new context - */ -PH7_PRIVATE void SHA1Init(SHA1Context *context) { - /* SHA1 initialization constants */ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} -/* - * Run your data through this. - */ -PH7_PRIVATE void SHA1Update(SHA1Context *context, const unsigned char *data, unsigned int len) { - unsigned int i, j; - j = context->count[0]; - if((context->count[0] += len << 3) < j) { - context->count[1] += (len >> 29) + 1; - } - j = (j >> 3) & 63; - if((j + len) > 63) { - (void)SyMemcpy(data, &context->buffer[j], (i = 64 - j)); - SHA1Transform(context->state, context->buffer); - for(; i + 63 < len; i += 64) { - SHA1Transform(context->state, &data[i]); - } - j = 0; - } else { - i = 0; - } - (void)SyMemcpy(&data[i], &context->buffer[j], len - i); -} -/* - * Add padding and return the message digest. - */ -PH7_PRIVATE void SHA1Final(SHA1Context *context, unsigned char digest[20]) { - unsigned int i; - unsigned char finalcount[8]; - for(i = 0; i < 8; i++) { - finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] - >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ - } - SHA1Update(context, (const unsigned char *)"\200", 1); - while((context->count[0] & 504) != 448) { - SHA1Update(context, (const unsigned char *)"\0", 1); - } - SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ - if(digest) { - for(i = 0; i < 20; i++) - digest[i] = (unsigned char) - ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); - } -} -#undef Rl0 -#undef Rb0 -#undef R1 -#undef R2 -#undef R3 -#undef R4 - -PH7_PRIVATE sxi32 SySha1Compute(const void *pIn, sxu32 nLen, unsigned char zDigest[20]) { - SHA1Context sCtx; - SHA1Init(&sCtx); - SHA1Update(&sCtx, (const unsigned char *)pIn, nLen); - SHA1Final(&sCtx, zDigest); - return SXRET_OK; -} -static const sxu32 crc32_table[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, - 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, - 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, - 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, - 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, - 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, - 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, - 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, - 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, - 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, - 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, - 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, - 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, - 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, - 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, - 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, - 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, - 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, - 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, - 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, - 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, - 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, - 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, - 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, - 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, - 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, - 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, - 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, - 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, - 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, - 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, - 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, - 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, - 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, - 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, -}; -#define CRC32C(c,d) (c = ( crc32_table[(c ^ (d)) & 0xFF] ^ (c>>8) ) ) -static sxu32 SyCrc32Update(sxu32 crc32, const void *pSrc, sxu32 nLen) { - register unsigned char *zIn = (unsigned char *)pSrc; - unsigned char *zEnd; - if(zIn == 0) { - return crc32; - } - zEnd = &zIn[nLen]; - for(;;) { - if(zIn >= zEnd) { - break; - } - CRC32C(crc32, zIn[0]); - zIn++; - if(zIn >= zEnd) { - break; - } - CRC32C(crc32, zIn[0]); - zIn++; - if(zIn >= zEnd) { - break; - } - CRC32C(crc32, zIn[0]); - zIn++; - if(zIn >= zEnd) { - break; - } - CRC32C(crc32, zIn[0]); - zIn++; - } - return crc32; -} -PH7_PRIVATE sxu32 SyCrc32(const void *pSrc, sxu32 nLen) { - return SyCrc32Update(SXU32_HIGH, pSrc, nLen); -} -#endif /* PH7_DISABLE_HASH_FUNC */ -#endif /* PH7_DISABLE_BUILTIN_FUNC */ -#ifndef PH7_DISABLE_BUILTIN_FUNC -PH7_PRIVATE sxi32 SyBinToHexConsumer(const void *pIn, sxu32 nLen, ProcConsumer xConsumer, void *pConsumerData) { - static const unsigned char zHexTab[] = "0123456789abcdef"; - const unsigned char *zIn, *zEnd; - unsigned char zOut[3]; - sxi32 rc; -#if defined(UNTRUST) - if(pIn == 0 || xConsumer == 0) { - return SXERR_EMPTY; - } -#endif - zIn = (const unsigned char *)pIn; - zEnd = &zIn[nLen]; - for(;;) { - if(zIn >= zEnd) { - break; - } - zOut[0] = zHexTab[zIn[0] >> 4]; - zOut[1] = zHexTab[zIn[0] & 0x0F]; - rc = xConsumer((const void *)zOut, sizeof(char) * 2, pConsumerData); - if(rc != SXRET_OK) { - return rc; - } - zIn++; - } - return SXRET_OK; -} -#endif /* PH7_DISABLE_BUILTIN_FUNC */ diff --git a/engine/lib/libfmt.c b/engine/lib/libfmt.c new file mode 100644 index 0000000..f649187 --- /dev/null +++ b/engine/lib/libfmt.c @@ -0,0 +1,764 @@ +#include "ph7int.h" + +#define SXFMT_BUFSIZ 1024 /* Conversion buffer size */ +/* +** Conversion types fall into various categories as defined by the +** following enumeration. +*/ +#define SXFMT_RADIX 1 /* Integer types.%d, %x, %o, and so forth */ +#define SXFMT_FLOAT 2 /* Floating point.%f */ +#define SXFMT_EXP 3 /* Exponentional notation.%e and %E */ +#define SXFMT_GENERIC 4 /* Floating or exponential, depending on exponent.%g */ +#define SXFMT_SIZE 5 /* Total number of characters processed so far.%n */ +#define SXFMT_STRING 6 /* Strings.%s */ +#define SXFMT_PERCENT 7 /* Percent symbol.%% */ +#define SXFMT_CHARX 8 /* Characters.%c */ +#define SXFMT_ERROR 9 /* Used to indicate no such conversion type */ +/* Extension by Symisc Systems */ +#define SXFMT_RAWSTR 13 /* %z Pointer to raw string (SyString *) */ +#define SXFMT_UNUSED 15 +/* +** Allowed values for SyFmtInfo.flags +*/ +#define SXFLAG_SIGNED 0x01 +#define SXFLAG_UNSIGNED 0x02 +/* Allowed values for SyFmtConsumer.nType */ +#define SXFMT_CONS_PROC 1 /* Consumer is a procedure */ +#define SXFMT_CONS_STR 2 /* Consumer is a managed string */ +#define SXFMT_CONS_FILE 5 /* Consumer is an open File */ +#define SXFMT_CONS_BLOB 6 /* Consumer is a BLOB */ +/* +** Each builtin conversion character (ex: the 'd' in "%d") is described +** by an instance of the following structure +*/ +typedef struct SyFmtInfo SyFmtInfo; +struct SyFmtInfo { + char fmttype; /* The format field code letter [i.e: 'd','s','x'] */ + sxu8 base; /* The base for radix conversion */ + int flags; /* One or more of SXFLAG_ constants below */ + sxu8 type; /* Conversion paradigm */ + const char *charset; /* The character set for conversion */ + const char *prefix; /* Prefix on non-zero values in alt format */ +}; +typedef struct SyFmtConsumer SyFmtConsumer; +struct SyFmtConsumer { + sxu32 nLen; /* Total output length */ + sxi32 nType; /* Type of the consumer see below */ + sxi32 rc; /* Consumer return value;Abort processing if rc != SXRET_OK */ + union { + struct { + ProcConsumer xUserConsumer; + void *pUserData; + } sFunc; + SyBlob *pBlob; + } uConsumer; +}; +#ifndef SX_OMIT_FLOATINGPOINT +static int getdigit(sxlongreal *val, int *cnt) { + sxlongreal d; + int digit; + if((*cnt)++ >= 16) { + return '0'; + } + digit = (int) * val; + d = digit; + *val = (*val - d) * 10.0; + return digit + '0' ; +} +#endif /* SX_OMIT_FLOATINGPOINT */ +/* + * The following routine was taken from the SQLITE2 source tree and was + * extended by Symisc Systems to fit its need. + * Status: Public Domain + */ +static sxi32 InternFormat(ProcConsumer xConsumer, void *pUserData, const char *zFormat, va_list ap) { + /* + * The following table is searched linearly, so it is good to put the most frequently + * used conversion types first. + */ + static const SyFmtInfo aFmt[] = { + { 'd', 10, SXFLAG_SIGNED, SXFMT_RADIX, "0123456789", 0 }, + { 's', 0, 0, SXFMT_STRING, 0, 0 }, + { 'c', 0, 0, SXFMT_CHARX, 0, 0 }, + { 'x', 16, 0, SXFMT_RADIX, "0123456789abcdef", "x0" }, + { 'X', 16, 0, SXFMT_RADIX, "0123456789ABCDEF", "X0" }, + /* -- Extensions by Symisc Systems -- */ + { 'z', 0, 0, SXFMT_RAWSTR, 0, 0 }, /* Pointer to a raw string (SyString *) */ + { 'B', 2, 0, SXFMT_RADIX, "01", "b0"}, + /* -- End of Extensions -- */ + { 'o', 8, 0, SXFMT_RADIX, "01234567", "0" }, + { 'u', 10, 0, SXFMT_RADIX, "0123456789", 0 }, +#ifndef SX_OMIT_FLOATINGPOINT + { 'f', 0, SXFLAG_SIGNED, SXFMT_FLOAT, 0, 0 }, + { 'e', 0, SXFLAG_SIGNED, SXFMT_EXP, "e", 0 }, + { 'E', 0, SXFLAG_SIGNED, SXFMT_EXP, "E", 0 }, + { 'g', 0, SXFLAG_SIGNED, SXFMT_GENERIC, "e", 0 }, + { 'G', 0, SXFLAG_SIGNED, SXFMT_GENERIC, "E", 0 }, +#endif + { 'i', 10, SXFLAG_SIGNED, SXFMT_RADIX, "0123456789", 0 }, + { 'n', 0, 0, SXFMT_SIZE, 0, 0 }, + { '%', 0, 0, SXFMT_PERCENT, 0, 0 }, + { 'p', 10, 0, SXFMT_RADIX, "0123456789", 0 } + }; + int c; /* Next character in the format string */ + char *bufpt; /* Pointer to the conversion buffer */ + int precision; /* Precision of the current field */ + int length; /* Length of the field */ + int idx; /* A general purpose loop counter */ + int width; /* Width of the current field */ + sxu8 flag_leftjustify; /* True if "-" flag is present */ + sxu8 flag_plussign; /* True if "+" flag is present */ + sxu8 flag_blanksign; /* True if " " flag is present */ + sxu8 flag_alternateform; /* True if "#" flag is present */ + sxu8 flag_zeropad; /* True if field width constant starts with zero */ + sxu8 flag_long; /* True if "l" flag is present */ + sxi64 longvalue; /* Value for integer types */ + const SyFmtInfo *infop; /* Pointer to the appropriate info structure */ + char buf[SXFMT_BUFSIZ]; /* Conversion buffer */ + char prefix; /* Prefix character."+" or "-" or " " or '\0'.*/ + sxu8 errorflag = 0; /* True if an error is encountered */ + sxu8 xtype; /* Conversion paradigm */ + char *zExtra; + static char spaces[] = " "; +#define etSPACESIZE ((int)sizeof(spaces)-1) +#ifndef SX_OMIT_FLOATINGPOINT + sxlongreal realvalue; /* Value for real types */ + int exp; /* exponent of real numbers */ + double rounder; /* Used for rounding floating point values */ + sxu8 flag_dp; /* True if decimal point should be shown */ + sxu8 flag_rtz; /* True if trailing zeros should be removed */ + sxu8 flag_exp; /* True to force display of the exponent */ + int nsd; /* Number of significant digits returned */ +#endif + int rc; + length = 0; + bufpt = 0; + for(; (c = (*zFormat)) != 0; ++zFormat) { + if(c != '%') { + unsigned int amt; + bufpt = (char *)zFormat; + amt = 1; + while((c = (*++zFormat)) != '%' && c != 0) { + amt++; + } + rc = xConsumer((const void *)bufpt, amt, pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; /* Consumer routine request an operation abort */ + } + if(c == 0) { + return errorflag > 0 ? SXERR_FORMAT : SXRET_OK; + } + } + if((c = (*++zFormat)) == 0) { + errorflag = 1; + rc = xConsumer("%", sizeof("%") - 1, pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; /* Consumer routine request an operation abort */ + } + return errorflag > 0 ? SXERR_FORMAT : SXRET_OK; + } + /* Find out what flags are present */ + flag_leftjustify = flag_plussign = flag_blanksign = + flag_alternateform = flag_zeropad = 0; + do { + switch(c) { + case '-': + flag_leftjustify = 1; + c = 0; + break; + case '+': + flag_plussign = 1; + c = 0; + break; + case ' ': + flag_blanksign = 1; + c = 0; + break; + case '#': + flag_alternateform = 1; + c = 0; + break; + case '0': + flag_zeropad = 1; + c = 0; + break; + default: + break; + } + } while(c == 0 && (c = (*++zFormat)) != 0); + /* Get the field width */ + width = 0; + if(c == '*') { + width = va_arg(ap, int); + if(width < 0) { + flag_leftjustify = 1; + width = -width; + } + c = *++zFormat; + } else { + while(c >= '0' && c <= '9') { + width = width * 10 + c - '0'; + c = *++zFormat; + } + } + if(width > SXFMT_BUFSIZ - 10) { + width = SXFMT_BUFSIZ - 10; + } + /* Get the precision */ + precision = -1; + if(c == '.') { + precision = 0; + c = *++zFormat; + if(c == '*') { + precision = va_arg(ap, int); + if(precision < 0) { + precision = -precision; + } + c = *++zFormat; + } else { + while(c >= '0' && c <= '9') { + precision = precision * 10 + c - '0'; + c = *++zFormat; + } + } + } + /* Get the conversion type modifier */ + flag_long = 0; + if(c == 'l' || c == 'q' /* BSD quad (expect a 64-bit integer) */) { + flag_long = (c == 'q') ? 2 : 1; + c = *++zFormat; + if(c == 'l') { + /* Standard printf emulation 'lld' (expect a 64bit integer) */ + flag_long = 2; + } + } + /* Fetch the info entry for the field */ + infop = 0; + xtype = SXFMT_ERROR; + for(idx = 0; idx < (int)SX_ARRAYSIZE(aFmt); idx++) { + if(c == aFmt[idx].fmttype) { + infop = &aFmt[idx]; + xtype = infop->type; + break; + } + } + zExtra = 0; + /* + ** At this point, variables are initialized as follows: + ** + ** flag_alternateform TRUE if a '#' is present. + ** flag_plussign TRUE if a '+' is present. + ** flag_leftjustify TRUE if a '-' is present or if the + ** field width was negative. + ** flag_zeropad TRUE if the width began with 0. + ** flag_long TRUE if the letter 'l' (ell) or 'q'(BSD quad) prefixed + ** the conversion character. + ** flag_blanksign TRUE if a ' ' is present. + ** width The specified field width.This is + ** always non-negative.Zero is the default. + ** precision The specified precision.The default + ** is -1. + ** xtype The class of the conversion. + ** infop Pointer to the appropriate info struct. + */ + switch(xtype) { + case SXFMT_RADIX: + if(flag_long > 0) { + if(flag_long > 1) { + /* BSD quad: expect a 64-bit integer */ + longvalue = va_arg(ap, sxi64); + } else { + longvalue = va_arg(ap, sxlong); + } + } else { + if(infop->flags & SXFLAG_SIGNED) { + longvalue = va_arg(ap, sxi32); + } else { + longvalue = va_arg(ap, sxu32); + } + } + /* Limit the precision to prevent overflowing buf[] during conversion */ + if(precision > SXFMT_BUFSIZ - 40) { + precision = SXFMT_BUFSIZ - 40; + } +#if 1 + /* For the format %#x, the value zero is printed "0" not "0x0". + ** I think this is stupid.*/ + if(longvalue == 0) { + flag_alternateform = 0; + } +#else + /* More sensible: turn off the prefix for octal (to prevent "00"), + ** but leave the prefix for hex.*/ + if(longvalue == 0 && infop->base == 8) { + flag_alternateform = 0; + } +#endif + if(infop->flags & SXFLAG_SIGNED) { + if(longvalue < 0) { + longvalue = -longvalue; + /* Ticket 1433-003 */ + if(longvalue < 0) { + /* Overflow */ + longvalue = SXI64_HIGH; + } + prefix = '-'; + } else if(flag_plussign) { + prefix = '+'; + } else if(flag_blanksign) { + prefix = ' '; + } else { + prefix = 0; + } + } else { + if(longvalue < 0) { + longvalue = -longvalue; + /* Ticket 1433-003 */ + if(longvalue < 0) { + /* Overflow */ + longvalue = SXI64_HIGH; + } + } + prefix = 0; + } + if(flag_zeropad && precision < width - (prefix != 0)) { + precision = width - (prefix != 0); + } + bufpt = &buf[SXFMT_BUFSIZ - 1]; + { + register const char *cset; /* Use registers for speed */ + register int base; + cset = infop->charset; + base = infop->base; + do { /* Convert to ascii */ + *(--bufpt) = cset[longvalue % base]; + longvalue = longvalue / base; + } while(longvalue > 0); + } + length = &buf[SXFMT_BUFSIZ - 1] - bufpt; + for(idx = precision - length; idx > 0; idx--) { + *(--bufpt) = '0'; /* Zero pad */ + } + if(prefix) { + *(--bufpt) = prefix; /* Add sign */ + } + if(flag_alternateform && infop->prefix) { /* Add "0" or "0x" */ + const char *pre; + char x; + pre = infop->prefix; + if(*bufpt != pre[0]) { + for(pre = infop->prefix; (x = (*pre)) != 0; pre++) { + *(--bufpt) = x; + } + } + } + length = &buf[SXFMT_BUFSIZ - 1] - bufpt; + break; + case SXFMT_FLOAT: + case SXFMT_EXP: + case SXFMT_GENERIC: +#ifndef SX_OMIT_FLOATINGPOINT + realvalue = va_arg(ap, double); + if(precision < 0) { + precision = 6; /* Set default precision */ + } + if(precision > SXFMT_BUFSIZ - 40) { + precision = SXFMT_BUFSIZ - 40; + } + if(realvalue < 0.0) { + realvalue = -realvalue; + prefix = '-'; + } else { + if(flag_plussign) { + prefix = '+'; + } else if(flag_blanksign) { + prefix = ' '; + } else { + prefix = 0; + } + } + if(infop->type == SXFMT_GENERIC && precision > 0) { + precision--; + } + rounder = 0.0; +#if 0 + /* Rounding works like BSD when the constant 0.4999 is used.Wierd! */ + for(idx = precision, rounder = 0.4999; idx > 0; idx--, rounder *= 0.1); +#else + /* It makes more sense to use 0.5 */ + for(idx = precision, rounder = 0.5; idx > 0; idx--, rounder *= 0.1); +#endif + if(infop->type == SXFMT_FLOAT) { + realvalue += rounder; + } + /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ + exp = 0; + if(realvalue > 0.0) { + while(realvalue >= 1e8 && exp <= 350) { + realvalue *= 1e-8; + exp += 8; + } + while(realvalue >= 10.0 && exp <= 350) { + realvalue *= 0.1; + exp++; + } + while(realvalue < 1e-8 && exp >= -350) { + realvalue *= 1e8; + exp -= 8; + } + while(realvalue < 1.0 && exp >= -350) { + realvalue *= 10.0; + exp--; + } + if(exp > 350 || exp < -350) { + bufpt = "NaN"; + length = 3; + break; + } + } + bufpt = buf; + /* + ** If the field type is etGENERIC, then convert to either etEXP + ** or etFLOAT, as appropriate. + */ + flag_exp = xtype == SXFMT_EXP; + if(xtype != SXFMT_FLOAT) { + realvalue += rounder; + if(realvalue >= 10.0) { + realvalue *= 0.1; + exp++; + } + } + if(xtype == SXFMT_GENERIC) { + flag_rtz = !flag_alternateform; + if(exp < -4 || exp > precision) { + xtype = SXFMT_EXP; + } else { + precision = precision - exp; + xtype = SXFMT_FLOAT; + } + } else { + flag_rtz = 0; + } + /* + ** The "exp+precision" test causes output to be of type etEXP if + ** the precision is too large to fit in buf[]. + */ + nsd = 0; + if(xtype == SXFMT_FLOAT && exp + precision < SXFMT_BUFSIZ - 30) { + flag_dp = (precision > 0 || flag_alternateform); + if(prefix) { + *(bufpt++) = prefix; /* Sign */ + } + if(exp < 0) { + *(bufpt++) = '0'; /* Digits before "." */ + } else + for(; exp >= 0; exp--) { + *(bufpt++) = (char)getdigit(&realvalue, &nsd); + } + if(flag_dp) { + *(bufpt++) = '.'; /* The decimal point */ + } + for(exp++; exp < 0 && precision > 0; precision--, exp++) { + *(bufpt++) = '0'; + } + while((precision--) > 0) { + *(bufpt++) = (char)getdigit(&realvalue, &nsd); + } + *(bufpt--) = 0; /* Null terminate */ + if(flag_rtz && flag_dp) { /* Remove trailing zeros and "." */ + while(bufpt >= buf && *bufpt == '0') { + *(bufpt--) = 0; + } + if(bufpt >= buf && *bufpt == '.') { + *(bufpt--) = 0; + } + } + bufpt++; /* point to next free slot */ + } else { /* etEXP or etGENERIC */ + flag_dp = (precision > 0 || flag_alternateform); + if(prefix) { + *(bufpt++) = prefix; /* Sign */ + } + *(bufpt++) = (char)getdigit(&realvalue, &nsd); /* First digit */ + if(flag_dp) { + *(bufpt++) = '.'; /* Decimal point */ + } + while((precision--) > 0) { + *(bufpt++) = (char)getdigit(&realvalue, &nsd); + } + bufpt--; /* point to last digit */ + if(flag_rtz && flag_dp) { /* Remove tail zeros */ + while(bufpt >= buf && *bufpt == '0') { + *(bufpt--) = 0; + } + if(bufpt >= buf && *bufpt == '.') { + *(bufpt--) = 0; + } + } + bufpt++; /* point to next free slot */ + if(exp || flag_exp) { + *(bufpt++) = infop->charset[0]; + if(exp < 0) { + *(bufpt++) = '-'; /* sign of exp */ + exp = -exp; + } else { + *(bufpt++) = '+'; + } + if(exp >= 100) { + *(bufpt++) = (char)((exp / 100) + '0'); /* 100's digit */ + exp %= 100; + } + *(bufpt++) = (char)(exp / 10 + '0'); /* 10's digit */ + *(bufpt++) = (char)(exp % 10 + '0'); /* 1's digit */ + } + } + /* The converted number is in buf[] and zero terminated.Output it. + ** Note that the number is in the usual order, not reversed as with + ** integer conversions.*/ + length = bufpt - buf; + bufpt = buf; + /* Special case: Add leading zeros if the flag_zeropad flag is + ** set and we are not left justified */ + if(flag_zeropad && !flag_leftjustify && length < width) { + int i; + int nPad = width - length; + for(i = width; i >= nPad; i--) { + bufpt[i] = bufpt[i - nPad]; + } + i = prefix != 0; + while(nPad--) { + bufpt[i++] = '0'; + } + length = width; + } +#else + bufpt = " "; + length = (int)sizeof(" ") - 1; +#endif /* SX_OMIT_FLOATINGPOINT */ + break; + case SXFMT_SIZE: { + int *pSize = va_arg(ap, int *); + *pSize = ((SyFmtConsumer *)pUserData)->nLen; + length = width = 0; + } + break; + case SXFMT_PERCENT: + buf[0] = '%'; + bufpt = buf; + length = 1; + break; + case SXFMT_CHARX: + c = va_arg(ap, int); + buf[0] = (char)c; + /* Limit the precision to prevent overflowing buf[] during conversion */ + if(precision > SXFMT_BUFSIZ - 40) { + precision = SXFMT_BUFSIZ - 40; + } + if(precision >= 0) { + for(idx = 1; idx < precision; idx++) { + buf[idx] = (char)c; + } + length = precision; + } else { + length = 1; + } + bufpt = buf; + break; + case SXFMT_STRING: + bufpt = va_arg(ap, char *); + if(bufpt == 0) { + bufpt = " "; + length = (int)sizeof(" ") - 1; + break; + } + length = precision; + if(precision < 0) { + /* Symisc extension */ + length = (int)SyStrlen(bufpt); + } + if(precision >= 0 && precision < length) { + length = precision; + } + break; + case SXFMT_RAWSTR: { + /* Symisc extension */ + SyString *pStr = va_arg(ap, SyString *); + if(pStr == 0 || pStr->zString == 0) { + bufpt = " "; + length = (int)sizeof(char); + break; + } + bufpt = (char *)pStr->zString; + length = (int)pStr->nByte; + break; + } + case SXFMT_ERROR: + buf[0] = '?'; + bufpt = buf; + length = (int)sizeof(char); + if(c == 0) { + zFormat--; + } + break; + }/* End switch over the format type */ + /* + ** The text of the conversion is pointed to by "bufpt" and is + ** "length" characters long.The field width is "width".Do + ** the output. + */ + if(!flag_leftjustify) { + register int nspace; + nspace = width - length; + if(nspace > 0) { + while(nspace >= etSPACESIZE) { + rc = xConsumer(spaces, etSPACESIZE, pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; /* Consumer routine request an operation abort */ + } + nspace -= etSPACESIZE; + } + if(nspace > 0) { + rc = xConsumer(spaces, (unsigned int)nspace, pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; /* Consumer routine request an operation abort */ + } + } + } + } + if(length > 0) { + rc = xConsumer(bufpt, (unsigned int)length, pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; /* Consumer routine request an operation abort */ + } + } + if(flag_leftjustify) { + register int nspace; + nspace = width - length; + if(nspace > 0) { + while(nspace >= etSPACESIZE) { + rc = xConsumer(spaces, etSPACESIZE, pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; /* Consumer routine request an operation abort */ + } + nspace -= etSPACESIZE; + } + if(nspace > 0) { + rc = xConsumer(spaces, (unsigned int)nspace, pUserData); + if(rc != SXRET_OK) { + return SXERR_ABORT; /* Consumer routine request an operation abort */ + } + } + } + } + }/* End for loop over the format string */ + return errorflag ? SXERR_FORMAT : SXRET_OK; +} +static sxi32 FormatConsumer(const void *pSrc, unsigned int nLen, void *pData) { + SyFmtConsumer *pConsumer = (SyFmtConsumer *)pData; + sxi32 rc = SXERR_ABORT; + switch(pConsumer->nType) { + case SXFMT_CONS_PROC: + /* User callback */ + rc = pConsumer->uConsumer.sFunc.xUserConsumer(pSrc, nLen, pConsumer->uConsumer.sFunc.pUserData); + break; + case SXFMT_CONS_BLOB: + /* Blob consumer */ + rc = SyBlobAppend(pConsumer->uConsumer.pBlob, pSrc, (sxu32)nLen); + break; + default: + /* Unknown consumer */ + break; + } + /* Update total number of bytes consumed so far */ + pConsumer->nLen += nLen; + pConsumer->rc = rc; + return rc; +} +static sxi32 FormatMount(sxi32 nType, void *pConsumer, ProcConsumer xUserCons, void *pUserData, sxu32 *pOutLen, const char *zFormat, va_list ap) { + SyFmtConsumer sCons; + sCons.nType = nType; + sCons.rc = SXRET_OK; + sCons.nLen = 0; + if(pOutLen) { + *pOutLen = 0; + } + switch(nType) { + case SXFMT_CONS_PROC: +#if defined(UNTRUST) + if(xUserCons == 0) { + return SXERR_EMPTY; + } +#endif + sCons.uConsumer.sFunc.xUserConsumer = xUserCons; + sCons.uConsumer.sFunc.pUserData = pUserData; + break; + case SXFMT_CONS_BLOB: + sCons.uConsumer.pBlob = (SyBlob *)pConsumer; + break; + default: + return SXERR_UNKNOWN; + } + InternFormat(FormatConsumer, &sCons, zFormat, ap); + if(pOutLen) { + *pOutLen = sCons.nLen; + } + return sCons.rc; +} +PH7_PRIVATE sxi32 SyProcFormat(ProcConsumer xConsumer, void *pData, const char *zFormat, ...) { + va_list ap; + sxi32 rc; +#if defined(UNTRUST) + if(SX_EMPTY_STR(zFormat)) { + return SXERR_EMPTY; + } +#endif + va_start(ap, zFormat); + rc = FormatMount(SXFMT_CONS_PROC, 0, xConsumer, pData, 0, zFormat, ap); + va_end(ap); + return rc; +} +PH7_PRIVATE sxu32 SyBlobFormat(SyBlob *pBlob, const char *zFormat, ...) { + va_list ap; + sxu32 n; +#if defined(UNTRUST) + if(SX_EMPTY_STR(zFormat)) { + return 0; + } +#endif + va_start(ap, zFormat); + FormatMount(SXFMT_CONS_BLOB, &(*pBlob), 0, 0, &n, zFormat, ap); + va_end(ap); + return n; +} +PH7_PRIVATE sxu32 SyBlobFormatAp(SyBlob *pBlob, const char *zFormat, va_list ap) { + sxu32 n = 0; /* cc warning */ +#if defined(UNTRUST) + if(SX_EMPTY_STR(zFormat)) { + return 0; + } +#endif + FormatMount(SXFMT_CONS_BLOB, &(*pBlob), 0, 0, &n, zFormat, ap); + return n; +} +PH7_PRIVATE sxu32 SyBufferFormat(char *zBuf, sxu32 nLen, const char *zFormat, ...) { + SyBlob sBlob; + va_list ap; + sxu32 n; +#if defined(UNTRUST) + if(SX_EMPTY_STR(zFormat)) { + return 0; + } +#endif + if(SXRET_OK != SyBlobInitFromBuf(&sBlob, zBuf, nLen - 1)) { + return 0; + } + va_start(ap, zFormat); + FormatMount(SXFMT_CONS_BLOB, &sBlob, 0, 0, 0, zFormat, ap); + va_end(ap); + n = SyBlobLength(&sBlob); + /* Append the null terminator */ + sBlob.mByte++; + SyBlobAppend(&sBlob, "\0", sizeof(char)); + return n; +} \ No newline at end of file diff --git a/engine/lib/libzip.c b/engine/lib/libzip.c new file mode 100644 index 0000000..46dc75c --- /dev/null +++ b/engine/lib/libzip.c @@ -0,0 +1,510 @@ +#include "ph7int.h" + +sxu32 SyBinHash(const void *pSrc, sxu32 nLen); +/* + * Zip File Format: + * + * Byte order: Little-endian + * + * [Local file header + Compressed data [+ Extended local header]?]* + * [Central directory]* + * [End of central directory record] + * + * Local file header:* + * Offset Length Contents + * 0 4 bytes Local file header signature (0x04034b50) + * 4 2 bytes Version needed to extract + * 6 2 bytes General purpose bit flag + * 8 2 bytes Compression method + * 10 2 bytes Last mod file time + * 12 2 bytes Last mod file date + * 14 4 bytes CRC-32 + * 18 4 bytes Compressed size (n) + * 22 4 bytes Uncompressed size + * 26 2 bytes Filename length (f) + * 28 2 bytes Extra field length (e) + * 30 (f)bytes Filename + * (e)bytes Extra field + * (n)bytes Compressed data + * + * Extended local header:* + * Offset Length Contents + * 0 4 bytes Extended Local file header signature (0x08074b50) + * 4 4 bytes CRC-32 + * 8 4 bytes Compressed size + * 12 4 bytes Uncompressed size + * + * Extra field:?(if any) + * Offset Length Contents + * 0 2 bytes Header ID (0x001 until 0xfb4a) see extended appnote from Info-zip + * 2 2 bytes Data size (g) + * (g) bytes (g) bytes of extra field + * + * Central directory:* + * Offset Length Contents + * 0 4 bytes Central file header signature (0x02014b50) + * 4 2 bytes Version made by + * 6 2 bytes Version needed to extract + * 8 2 bytes General purpose bit flag + * 10 2 bytes Compression method + * 12 2 bytes Last mod file time + * 14 2 bytes Last mod file date + * 16 4 bytes CRC-32 + * 20 4 bytes Compressed size + * 24 4 bytes Uncompressed size + * 28 2 bytes Filename length (f) + * 30 2 bytes Extra field length (e) + * 32 2 bytes File comment length (c) + * 34 2 bytes Disk number start + * 36 2 bytes Internal file attributes + * 38 4 bytes External file attributes + * 42 4 bytes Relative offset of local header + * 46 (f)bytes Filename + * (e)bytes Extra field + * (c)bytes File comment + * + * End of central directory record: + * Offset Length Contents + * 0 4 bytes End of central dir signature (0x06054b50) + * 4 2 bytes Number of this disk + * 6 2 bytes Number of the disk with the start of the central directory + * 8 2 bytes Total number of entries in the central dir on this disk + * 10 2 bytes Total number of entries in the central dir + * 12 4 bytes Size of the central directory + * 16 4 bytes Offset of start of central directory with respect to the starting disk number + * 20 2 bytes zipfile comment length (c) + * 22 (c)bytes zipfile comment + * + * compression method: (2 bytes) + * 0 - The file is stored (no compression) + * 1 - The file is Shrunk + * 2 - The file is Reduced with compression factor 1 + * 3 - The file is Reduced with compression factor 2 + * 4 - The file is Reduced with compression factor 3 + * 5 - The file is Reduced with compression factor 4 + * 6 - The file is Imploded + * 7 - Reserved for Tokenizing compression algorithm + * 8 - The file is Deflated + */ + +#define SXMAKE_ZIP_WORKBUF (SXU16_HIGH/2) /* 32KB Initial working buffer size */ +#define SXMAKE_ZIP_EXTRACT_VER 0x000a /* Version needed to extract */ +#define SXMAKE_ZIP_VER 0x003 /* Version made by */ + +#define SXZIP_CENTRAL_MAGIC 0x02014b50 +#define SXZIP_END_CENTRAL_MAGIC 0x06054b50 +#define SXZIP_LOCAL_MAGIC 0x04034b50 +/*#define SXZIP_CRC32_START 0xdebb20e3*/ + +#define SXZIP_LOCAL_HDRSZ 30 /* Local header size */ +#define SXZIP_LOCAL_EXT_HDRZ 16 /* Extended local header(footer) size */ +#define SXZIP_CENTRAL_HDRSZ 46 /* Central directory header size */ +#define SXZIP_END_CENTRAL_HDRSZ 22 /* End of central directory header size */ + +#define SXARCHIVE_HASH_SIZE 64 /* Starting hash table size(MUST BE POWER OF 2)*/ +static sxi32 SyLittleEndianUnpack32(sxu32 *uNB, const unsigned char *buf, sxu32 Len) { + if(Len < sizeof(sxu32)) { + return SXERR_SHORT; + } + *uNB = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24); + return SXRET_OK; +} +static sxi32 SyLittleEndianUnpack16(sxu16 *pOut, const unsigned char *zBuf, sxu32 nLen) { + if(nLen < sizeof(sxu16)) { + return SXERR_SHORT; + } + *pOut = zBuf[0] + (zBuf[1] << 8); + return SXRET_OK; +} +static sxi32 SyDosTimeFormat(sxu32 nDosDate, Sytm *pOut) { + sxu16 nDate; + sxu16 nTime; + nDate = nDosDate >> 16; + nTime = nDosDate & 0xFFFF; + pOut->tm_isdst = 0; + pOut->tm_year = 1980 + (nDate >> 9); + pOut->tm_mon = (nDate % (1 << 9)) >> 5; + pOut->tm_mday = (nDate % (1 << 9)) & 0x1F; + pOut->tm_hour = nTime >> 11; + pOut->tm_min = (nTime % (1 << 11)) >> 5; + pOut->tm_sec = ((nTime % (1 << 11)) & 0x1F) << 1; + return SXRET_OK; +} +/* + * Archive hashtable manager + */ +static sxi32 ArchiveHashGetEntry(SyArchive *pArch, const char *zName, sxu32 nLen, SyArchiveEntry **ppEntry) { + SyArchiveEntry *pBucketEntry; + SyString sEntry; + sxu32 nHash; + nHash = pArch->xHash(zName, nLen); + pBucketEntry = pArch->apHash[nHash & (pArch->nSize - 1)]; + SyStringInitFromBuf(&sEntry, zName, nLen); + for(;;) { + if(pBucketEntry == 0) { + break; + } + if(nHash == pBucketEntry->nHash && pArch->xCmp(&sEntry, &pBucketEntry->sFileName) == 0) { + if(ppEntry) { + *ppEntry = pBucketEntry; + } + return SXRET_OK; + } + pBucketEntry = pBucketEntry->pNextHash; + } + return SXERR_NOTFOUND; +} +static void ArchiveHashBucketInstall(SyArchiveEntry **apTable, sxu32 nBucket, SyArchiveEntry *pEntry) { + pEntry->pNextHash = apTable[nBucket]; + if(apTable[nBucket] != 0) { + apTable[nBucket]->pPrevHash = pEntry; + } + apTable[nBucket] = pEntry; +} +static sxi32 ArchiveHashGrowTable(SyArchive *pArch) { + sxu32 nNewSize = pArch->nSize * 2; + SyArchiveEntry **apNew; + SyArchiveEntry *pEntry; + sxu32 n; + /* Allocate a new table */ + apNew = (SyArchiveEntry **)SyMemBackendAlloc(pArch->pAllocator, nNewSize * sizeof(SyArchiveEntry *)); + if(apNew == 0) { + return SXRET_OK; /* Not so fatal,simply a performance hit */ + } + SyZero(apNew, nNewSize * sizeof(SyArchiveEntry *)); + /* Rehash old entries */ + for(n = 0, pEntry = pArch->pList ; n < pArch->nLoaded ; n++, pEntry = pEntry->pNext) { + pEntry->pNextHash = pEntry->pPrevHash = 0; + ArchiveHashBucketInstall(apNew, pEntry->nHash & (nNewSize - 1), pEntry); + } + /* Release the old table */ + SyMemBackendFree(pArch->pAllocator, pArch->apHash); + pArch->apHash = apNew; + pArch->nSize = nNewSize; + return SXRET_OK; +} +static sxi32 ArchiveHashInstallEntry(SyArchive *pArch, SyArchiveEntry *pEntry) { + if(pArch->nLoaded > pArch->nSize * 3) { + ArchiveHashGrowTable(&(*pArch)); + } + pEntry->nHash = pArch->xHash(SyStringData(&pEntry->sFileName), SyStringLength(&pEntry->sFileName)); + /* Install the entry in its bucket */ + ArchiveHashBucketInstall(pArch->apHash, pEntry->nHash & (pArch->nSize - 1), pEntry); + MACRO_LD_PUSH(pArch->pList, pEntry); + pArch->nLoaded++; + return SXRET_OK; +} +/* + * Parse the End of central directory and report status + */ +static sxi32 ParseEndOfCentralDirectory(SyArchive *pArch, const unsigned char *zBuf) { + sxu32 nMagic = 0; /* cc -O6 warning */ + sxi32 rc; + /* Sanity check */ + rc = SyLittleEndianUnpack32(&nMagic, zBuf, sizeof(sxu32)); + if(/* rc != SXRET_OK || */nMagic != SXZIP_END_CENTRAL_MAGIC) { + return SXERR_CORRUPT; + } + /* # of entries */ + rc = SyLittleEndianUnpack16((sxu16 *)&pArch->nEntry, &zBuf[8], sizeof(sxu16)); + if(/* rc != SXRET_OK || */ pArch->nEntry > SXI16_HIGH /* SXU16_HIGH */) { + return SXERR_CORRUPT; + } + /* Size of central directory */ + rc = SyLittleEndianUnpack32(&pArch->nCentralSize, &zBuf[12], sizeof(sxu32)); + if(/*rc != SXRET_OK ||*/ pArch->nCentralSize > SXI32_HIGH) { + return SXERR_CORRUPT; + } + /* Starting offset of central directory */ + rc = SyLittleEndianUnpack32(&pArch->nCentralOfft, &zBuf[16], sizeof(sxu32)); + if(/*rc != SXRET_OK ||*/ pArch->nCentralSize > SXI32_HIGH) { + return SXERR_CORRUPT; + } + return SXRET_OK; +} +/* + * Fill the zip entry with the appropriate information from the central directory + */ +static sxi32 GetCentralDirectoryEntry(SyArchive *pArch, SyArchiveEntry *pEntry, const unsigned char *zCentral, sxu32 *pNextOffset) { + SyString *pName = &pEntry->sFileName; /* File name */ + sxu16 nDosDate, nDosTime; + sxu16 nComment = 0 ; + sxu32 nMagic = 0; /* cc -O6 warning */ + sxi32 rc; + nDosDate = nDosTime = 0; /* cc -O6 warning */ + SXUNUSED(pArch); + /* Sanity check */ + rc = SyLittleEndianUnpack32(&nMagic, zCentral, sizeof(sxu32)); + if(/* rc != SXRET_OK || */ nMagic != SXZIP_CENTRAL_MAGIC) { + rc = SXERR_CORRUPT; + /* + * Try to recover by examing the next central directory record. + * Dont worry here,there is no risk of an infinite loop since + * the buffer size is delimited. + */ + /* pName->nByte = 0; nComment = 0; pName->nExtra = 0 */ + goto update; + } + /* + * entry name length + */ + SyLittleEndianUnpack16((sxu16 *)&pName->nByte, &zCentral[28], sizeof(sxu16)); + if(pName->nByte > SXI16_HIGH /* SXU16_HIGH */) { + rc = SXERR_BIG; + goto update; + } + /* Extra information */ + SyLittleEndianUnpack16(&pEntry->nExtra, &zCentral[30], sizeof(sxu16)); + /* Comment length */ + SyLittleEndianUnpack16(&nComment, &zCentral[32], sizeof(sxu16)); + /* Compression method 0 == stored / 8 == deflated */ + rc = SyLittleEndianUnpack16(&pEntry->nComprMeth, &zCentral[10], sizeof(sxu16)); + /* DOS Timestamp */ + SyLittleEndianUnpack16(&nDosTime, &zCentral[12], sizeof(sxu16)); + SyLittleEndianUnpack16(&nDosDate, &zCentral[14], sizeof(sxu16)); + SyDosTimeFormat((nDosDate << 16 | nDosTime), &pEntry->sFmt); + /* Little hack to fix month index */ + pEntry->sFmt.tm_mon--; + /* CRC32 */ + rc = SyLittleEndianUnpack32(&pEntry->nCrc, &zCentral[16], sizeof(sxu32)); + /* Content size before compression */ + rc = SyLittleEndianUnpack32(&pEntry->nByte, &zCentral[24], sizeof(sxu32)); + if(pEntry->nByte > SXI32_HIGH) { + rc = SXERR_BIG; + goto update; + } + /* + * Content size after compression. + * Note that if the file is stored pEntry->nByte should be equal to pEntry->nByteCompr + */ + rc = SyLittleEndianUnpack32(&pEntry->nByteCompr, &zCentral[20], sizeof(sxu32)); + if(pEntry->nByteCompr > SXI32_HIGH) { + rc = SXERR_BIG; + goto update; + } + /* Finally grab the contents offset */ + SyLittleEndianUnpack32(&pEntry->nOfft, &zCentral[42], sizeof(sxu32)); + if(pEntry->nOfft > SXI32_HIGH) { + rc = SXERR_BIG; + goto update; + } + rc = SXRET_OK; +update: + /* Update the offset to point to the next central directory record */ + *pNextOffset = SXZIP_CENTRAL_HDRSZ + pName->nByte + pEntry->nExtra + nComment; + return rc; /* Report failure or success */ +} +static sxi32 ZipFixOffset(SyArchiveEntry *pEntry, void *pSrc) { + sxu16 nExtra, nNameLen; + unsigned char *zHdr; + nExtra = nNameLen = 0; + zHdr = (unsigned char *)pSrc; + zHdr = &zHdr[pEntry->nOfft]; + if(SyMemcmp(zHdr, "PK\003\004", sizeof(sxu32)) != 0) { + return SXERR_CORRUPT; + } + SyLittleEndianUnpack16(&nNameLen, &zHdr[26], sizeof(sxu16)); + SyLittleEndianUnpack16(&nExtra, &zHdr[28], sizeof(sxu16)); + /* Fix contents offset */ + pEntry->nOfft += SXZIP_LOCAL_HDRSZ + nExtra + nNameLen; + return SXRET_OK; +} +/* + * Extract all valid entries from the central directory + */ +static sxi32 ZipExtract(SyArchive *pArch, const unsigned char *zCentral, sxu32 nLen, void *pSrc) { + SyArchiveEntry *pEntry, *pDup; + const unsigned char *zEnd ; /* End of central directory */ + sxu32 nIncr, nOfft; /* Central Offset */ + SyString *pName; /* Entry name */ + char *zName; + sxi32 rc; + nOfft = nIncr = 0; + zEnd = &zCentral[nLen]; + for(;;) { + if(&zCentral[nOfft] >= zEnd) { + break; + } + /* Add a new entry */ + pEntry = (SyArchiveEntry *)SyMemBackendPoolAlloc(pArch->pAllocator, sizeof(SyArchiveEntry)); + if(pEntry == 0) { + break; + } + SyZero(pEntry, sizeof(SyArchiveEntry)); + pEntry->nMagic = SXARCH_MAGIC; + nIncr = 0; + rc = GetCentralDirectoryEntry(&(*pArch), pEntry, &zCentral[nOfft], &nIncr); + if(rc == SXRET_OK) { + /* Fix the starting record offset so we can access entry contents correctly */ + rc = ZipFixOffset(pEntry, pSrc); + } + if(rc != SXRET_OK) { + sxu32 nJmp = 0; + SyMemBackendPoolFree(pArch->pAllocator, pEntry); + /* Try to recover by brute-forcing for a valid central directory record */ + if(SXRET_OK == SyBlobSearch((const void *)&zCentral[nOfft + nIncr], (sxu32)(zEnd - &zCentral[nOfft + nIncr]), + (const void *)"PK\001\002", sizeof(sxu32), &nJmp)) { + nOfft += nIncr + nJmp; /* Check next entry */ + continue; + } + break; /* Giving up,archive is hopelessly corrupted */ + } + pName = &pEntry->sFileName; + pName->zString = (const char *)&zCentral[nOfft + SXZIP_CENTRAL_HDRSZ]; + if(pName->nByte <= 0 || (pEntry->nByte <= 0 && pName->zString[pName->nByte - 1] != '/')) { + /* Ignore zero length records (except folders) and records without names */ + SyMemBackendPoolFree(pArch->pAllocator, pEntry); + nOfft += nIncr; /* Check next entry */ + continue; + } + zName = SyMemBackendStrDup(pArch->pAllocator, pName->zString, pName->nByte); + if(zName == 0) { + SyMemBackendPoolFree(pArch->pAllocator, pEntry); + nOfft += nIncr; /* Check next entry */ + continue; + } + pName->zString = (const char *)zName; + /* Check for duplicates */ + rc = ArchiveHashGetEntry(&(*pArch), pName->zString, pName->nByte, &pDup); + if(rc == SXRET_OK) { + /* Another entry with the same name exists ; link them together */ + pEntry->pNextName = pDup->pNextName; + pDup->pNextName = pEntry; + pDup->nDup++; + } else { + /* Insert in hashtable */ + ArchiveHashInstallEntry(pArch, pEntry); + } + nOfft += nIncr; /* Check next record */ + } + pArch->pCursor = pArch->pList; + return pArch->nLoaded > 0 ? SXRET_OK : SXERR_EMPTY; +} +PH7_PRIVATE sxi32 SyZipExtractFromBuf(SyArchive *pArch, const char *zBuf, sxu32 nLen) { + const unsigned char *zCentral, *zEnd; + sxi32 rc; +#if defined(UNTRUST) + if(SXARCH_INVALID(pArch) || zBuf == 0) { + return SXERR_INVALID; + } +#endif + /* The miminal size of a zip archive: + * LOCAL_HDR_SZ + CENTRAL_HDR_SZ + END_OF_CENTRAL_HDR_SZ + * 30 46 22 + */ + if(nLen < SXZIP_LOCAL_HDRSZ + SXZIP_CENTRAL_HDRSZ + SXZIP_END_CENTRAL_HDRSZ) { + return SXERR_CORRUPT; /* Don't bother processing return immediately */ + } + zEnd = (unsigned char *)&zBuf[nLen - SXZIP_END_CENTRAL_HDRSZ]; + /* Find the end of central directory */ + while(((sxu32)((unsigned char *)&zBuf[nLen] - zEnd) < (SXZIP_END_CENTRAL_HDRSZ + SXI16_HIGH)) && + zEnd > (unsigned char *)zBuf && SyMemcmp(zEnd, "PK\005\006", sizeof(sxu32)) != 0) { + zEnd--; + } + /* Parse the end of central directory */ + rc = ParseEndOfCentralDirectory(&(*pArch), zEnd); + if(rc != SXRET_OK) { + return rc; + } + /* Find the starting offset of the central directory */ + zCentral = &zEnd[-(sxi32)pArch->nCentralSize]; + if(zCentral <= (unsigned char *)zBuf || SyMemcmp(zCentral, "PK\001\002", sizeof(sxu32)) != 0) { + if(pArch->nCentralOfft >= nLen) { + /* Corrupted central directory offset */ + return SXERR_CORRUPT; + } + zCentral = (unsigned char *)&zBuf[pArch->nCentralOfft]; + if(SyMemcmp(zCentral, "PK\001\002", sizeof(sxu32)) != 0) { + /* Corrupted zip archive */ + return SXERR_CORRUPT; + } + /* Fall thru and extract all valid entries from the central directory */ + } + rc = ZipExtract(&(*pArch), zCentral, (sxu32)(zEnd - zCentral), (void *)zBuf); + return rc; +} +/* + * Default comparison function. + */ +static sxi32 ArchiveHashCmp(const SyString *pStr1, const SyString *pStr2) { + sxi32 rc; + rc = SyStringCmp(pStr1, pStr2, SyMemcmp); + return rc; +} +PH7_PRIVATE sxi32 SyArchiveInit(SyArchive *pArch, SyMemBackend *pAllocator, ProcHash xHash, ProcRawStrCmp xCmp) { + SyArchiveEntry **apHash; +#if defined(UNTRUST) + if(pArch == 0) { + return SXERR_EMPTY; + } +#endif + SyZero(pArch, sizeof(SyArchive)); + /* Allocate a new hashtable */ + apHash = (SyArchiveEntry **)SyMemBackendAlloc(&(*pAllocator), SXARCHIVE_HASH_SIZE * sizeof(SyArchiveEntry *)); + if(apHash == 0) { + return SXERR_MEM; + } + SyZero(apHash, SXARCHIVE_HASH_SIZE * sizeof(SyArchiveEntry *)); + pArch->apHash = apHash; + pArch->xHash = xHash ? xHash : SyBinHash; + pArch->xCmp = xCmp ? xCmp : ArchiveHashCmp; + pArch->nSize = SXARCHIVE_HASH_SIZE; + pArch->pAllocator = &(*pAllocator); + pArch->nMagic = SXARCH_MAGIC; + return SXRET_OK; +} +static sxi32 ArchiveReleaseEntry(SyMemBackend *pAllocator, SyArchiveEntry *pEntry) { + SyArchiveEntry *pDup = pEntry->pNextName; + SyArchiveEntry *pNextDup; + /* Release duplicates first since there are not stored in the hashtable */ + for(;;) { + if(pEntry->nDup == 0) { + break; + } + pNextDup = pDup->pNextName; + pDup->nMagic = 0x2661; + SyMemBackendFree(pAllocator, (void *)SyStringData(&pDup->sFileName)); + SyMemBackendPoolFree(pAllocator, pDup); + pDup = pNextDup; + pEntry->nDup--; + } + pEntry->nMagic = 0x2661; + SyMemBackendFree(pAllocator, (void *)SyStringData(&pEntry->sFileName)); + SyMemBackendPoolFree(pAllocator, pEntry); + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyArchiveRelease(SyArchive *pArch) { + SyArchiveEntry *pEntry, *pNext; + pEntry = pArch->pList; + for(;;) { + if(pArch->nLoaded < 1) { + break; + } + pNext = pEntry->pNext; + MACRO_LD_REMOVE(pArch->pList, pEntry); + ArchiveReleaseEntry(pArch->pAllocator, pEntry); + pEntry = pNext; + pArch->nLoaded--; + } + SyMemBackendFree(pArch->pAllocator, pArch->apHash); + pArch->pCursor = 0; + pArch->nMagic = 0x2626; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyArchiveResetLoopCursor(SyArchive *pArch) { + pArch->pCursor = pArch->pList; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyArchiveGetNextEntry(SyArchive *pArch, SyArchiveEntry **ppEntry) { + SyArchiveEntry *pNext; + if(pArch->pCursor == 0) { + /* Rewind the cursor */ + pArch->pCursor = pArch->pList; + return SXERR_EOF; + } + *ppEntry = pArch->pCursor; + pNext = pArch->pCursor->pNext; + /* Advance the cursor to the next entry */ + pArch->pCursor = pNext; + return SXRET_OK; +} \ No newline at end of file diff --git a/engine/lib/memory.c b/engine/lib/memory.c new file mode 100644 index 0000000..b054ebd --- /dev/null +++ b/engine/lib/memory.c @@ -0,0 +1,825 @@ +#include "ph7int.h" + +PH7_PRIVATE void SyZero(void *pSrc, sxu32 nSize) { + register unsigned char *zSrc = (unsigned char *)pSrc; + unsigned char *zEnd; +#if defined(UNTRUST) + if(zSrc == 0 || nSize <= 0) { + return ; + } +#endif + zEnd = &zSrc[nSize]; + for(;;) { + if(zSrc >= zEnd) { + break; + } + zSrc[0] = 0; + zSrc++; + if(zSrc >= zEnd) { + break; + } + zSrc[0] = 0; + zSrc++; + if(zSrc >= zEnd) { + break; + } + zSrc[0] = 0; + zSrc++; + if(zSrc >= zEnd) { + break; + } + zSrc[0] = 0; + zSrc++; + } +} +PH7_PRIVATE sxi32 SyMemcmp(const void *pB1, const void *pB2, sxu32 nSize) { + sxi32 rc; + if(nSize <= 0) { + return 0; + } + if(pB1 == 0 || pB2 == 0) { + return pB1 != 0 ? 1 : (pB2 == 0 ? 0 : -1); + } + SX_MACRO_FAST_CMP(pB1, pB2, nSize, rc); + return rc; +} +PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen) { +#if defined(UNTRUST) + if(pSrc == 0 || pDest == 0) { + return 0; + } +#endif + if(pSrc == (const void *)pDest) { + return nLen; + } + SX_MACRO_FAST_MEMCPY(pSrc, pDest, nLen); + return nLen; +} +static void *MemOSAlloc(sxu32 nBytes) { + sxu32 *pChunk; + pChunk = (sxu32 *)SyOSHeapAlloc(nBytes + sizeof(sxu32)); + if(pChunk == 0) { + return 0; + } + pChunk[0] = nBytes; + return (void *)&pChunk[1]; +} +static void *MemOSRealloc(void *pOld, sxu32 nBytes) { + sxu32 *pOldChunk; + sxu32 *pChunk; + pOldChunk = (sxu32 *)(((char *)pOld) - sizeof(sxu32)); + if(pOldChunk[0] >= nBytes) { + return pOld; + } + pChunk = (sxu32 *)SyOSHeapRealloc(pOldChunk, nBytes + sizeof(sxu32)); + if(pChunk == 0) { + return 0; + } + pChunk[0] = nBytes; + return (void *)&pChunk[1]; +} +static void MemOSFree(void *pBlock) { + void *pChunk; + pChunk = (void *)(((char *)pBlock) - sizeof(sxu32)); + SyOSHeapFree(pChunk); +} +static sxu32 MemOSChunkSize(void *pBlock) { + sxu32 *pChunk; + pChunk = (sxu32 *)(((char *)pBlock) - sizeof(sxu32)); + return pChunk[0]; +} +/* Export OS allocation methods */ +static const SyMemMethods sOSAllocMethods = { + MemOSAlloc, + MemOSRealloc, + MemOSFree, + MemOSChunkSize, + 0, + 0, + 0 +}; +static void *MemBackendAlloc(SyMemBackend *pBackend, sxu32 nByte) { + SyMemBlock *pBlock; + sxi32 nRetry = 0; + /* Append an extra block so we can tracks allocated chunks and avoid memory + * leaks. + */ + nByte += sizeof(SyMemBlock); + for(;;) { + pBlock = (SyMemBlock *)pBackend->pMethods->xAlloc(nByte); + if(pBlock != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY + || SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) { + break; + } + nRetry++; + } + if(pBlock == 0) { + return 0; + } + pBlock->pNext = pBlock->pPrev = 0; + /* Link to the list of already tracked blocks */ + MACRO_LD_PUSH(pBackend->pBlocks, pBlock); +#if defined(UNTRUST) + pBlock->nGuard = SXMEM_BACKEND_MAGIC; +#endif + pBackend->nBlock++; + return (void *)&pBlock[1]; +} +PH7_PRIVATE void *SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nByte) { + void *pChunk; +#if defined(UNTRUST) + if(SXMEM_BACKEND_CORRUPT(pBackend)) { + return 0; + } +#endif + if(pBackend->pMutexMethods) { + SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); + } + pChunk = MemBackendAlloc(&(*pBackend), nByte); + if(pBackend->pMutexMethods) { + SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); + } + return pChunk; +} +static void *MemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) { + SyMemBlock *pBlock, *pNew, *pPrev, *pNext; + sxu32 nRetry = 0; + if(pOld == 0) { + return MemBackendAlloc(&(*pBackend), nByte); + } + pBlock = (SyMemBlock *)(((char *)pOld) - sizeof(SyMemBlock)); +#if defined(UNTRUST) + if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) { + return 0; + } +#endif + nByte += sizeof(SyMemBlock); + pPrev = pBlock->pPrev; + pNext = pBlock->pNext; + for(;;) { + pNew = (SyMemBlock *)pBackend->pMethods->xRealloc(pBlock, nByte); + if(pNew != 0 || pBackend->xMemError == 0 || nRetry > SXMEM_BACKEND_RETRY || + SXERR_RETRY != pBackend->xMemError(pBackend->pUserData)) { + break; + } + nRetry++; + } + if(pNew == 0) { + return 0; + } + if(pNew != pBlock) { + if(pPrev == 0) { + pBackend->pBlocks = pNew; + } else { + pPrev->pNext = pNew; + } + if(pNext) { + pNext->pPrev = pNew; + } +#if defined(UNTRUST) + pNew->nGuard = SXMEM_BACKEND_MAGIC; +#endif + } + return (void *)&pNew[1]; +} +PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) { + void *pChunk; +#if defined(UNTRUST) + if(SXMEM_BACKEND_CORRUPT(pBackend)) { + return 0; + } +#endif + if(pBackend->pMutexMethods) { + SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); + } + pChunk = MemBackendRealloc(&(*pBackend), pOld, nByte); + if(pBackend->pMutexMethods) { + SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); + } + return pChunk; +} +static sxi32 MemBackendFree(SyMemBackend *pBackend, void *pChunk) { + SyMemBlock *pBlock; + pBlock = (SyMemBlock *)(((char *)pChunk) - sizeof(SyMemBlock)); +#if defined(UNTRUST) + if(pBlock->nGuard != SXMEM_BACKEND_MAGIC) { + return SXERR_CORRUPT; + } +#endif + /* Unlink from the list of active blocks */ + if(pBackend->nBlock > 0) { + /* Release the block */ +#if defined(UNTRUST) + /* Mark as stale block */ + pBlock->nGuard = 0x635B; +#endif + MACRO_LD_REMOVE(pBackend->pBlocks, pBlock); + pBackend->nBlock--; + pBackend->pMethods->xFree(pBlock); + } + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyMemBackendFree(SyMemBackend *pBackend, void *pChunk) { + sxi32 rc; +#if defined(UNTRUST) + if(SXMEM_BACKEND_CORRUPT(pBackend)) { + return SXERR_CORRUPT; + } +#endif + if(pChunk == 0) { + return SXRET_OK; + } + if(pBackend->pMutexMethods) { + SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); + } + rc = MemBackendFree(&(*pBackend), pChunk); + if(pBackend->pMutexMethods) { + SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); + } + return rc; +} +#if defined(PH7_ENABLE_THREADS) +PH7_PRIVATE sxi32 SyMemBackendMakeThreadSafe(SyMemBackend *pBackend, const SyMutexMethods *pMethods) { + SyMutex *pMutex; +#if defined(UNTRUST) + if(SXMEM_BACKEND_CORRUPT(pBackend) || pMethods == 0 || pMethods->xNew == 0) { + return SXERR_CORRUPT; + } +#endif + pMutex = pMethods->xNew(SXMUTEX_TYPE_FAST); + if(pMutex == 0) { + return SXERR_OS; + } + /* Attach the mutex to the memory backend */ + pBackend->pMutex = pMutex; + pBackend->pMutexMethods = pMethods; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyMemBackendDisbaleMutexing(SyMemBackend *pBackend) { +#if defined(UNTRUST) + if(SXMEM_BACKEND_CORRUPT(pBackend)) { + return SXERR_CORRUPT; + } +#endif + if(pBackend->pMutex == 0) { + /* There is no mutex subsystem at all */ + return SXRET_OK; + } + SyMutexRelease(pBackend->pMutexMethods, pBackend->pMutex); + pBackend->pMutexMethods = 0; + pBackend->pMutex = 0; + return SXRET_OK; +} +#endif +/* + * Memory pool allocator + */ +#define SXMEM_POOL_MAGIC 0xDEAD +#define SXMEM_POOL_MAXALLOC (1<<(SXMEM_POOL_NBUCKETS+SXMEM_POOL_INCR)) +#define SXMEM_POOL_MINALLOC (1<<(SXMEM_POOL_INCR)) +static sxi32 MemPoolBucketAlloc(SyMemBackend *pBackend, sxu32 nBucket) { + char *zBucket, *zBucketEnd; + SyMemHeader *pHeader; + sxu32 nBucketSize; + /* Allocate one big block first */ + zBucket = (char *)MemBackendAlloc(&(*pBackend), SXMEM_POOL_MAXALLOC); + if(zBucket == 0) { + return SXERR_MEM; + } + zBucketEnd = &zBucket[SXMEM_POOL_MAXALLOC]; + /* Divide the big block into mini bucket pool */ + nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR); + pBackend->apPool[nBucket] = pHeader = (SyMemHeader *)zBucket; + for(;;) { + if(&zBucket[nBucketSize] >= zBucketEnd) { + break; + } + pHeader->pNext = (SyMemHeader *)&zBucket[nBucketSize]; + /* Advance the cursor to the next available chunk */ + pHeader = pHeader->pNext; + zBucket += nBucketSize; + } + pHeader->pNext = 0; + return SXRET_OK; +} +static void *MemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nByte) { + SyMemHeader *pBucket, *pNext; + sxu32 nBucketSize; + sxu32 nBucket; + if(nByte + sizeof(SyMemHeader) >= SXMEM_POOL_MAXALLOC) { + /* Allocate a big chunk directly */ + pBucket = (SyMemHeader *)MemBackendAlloc(&(*pBackend), nByte + sizeof(SyMemHeader)); + if(pBucket == 0) { + return 0; + } + /* Record as big block */ + pBucket->nBucket = (sxu32)(SXMEM_POOL_MAGIC << 16) | SXU16_HIGH; + return (void *)(pBucket + 1); + } + /* Locate the appropriate bucket */ + nBucket = 0; + nBucketSize = SXMEM_POOL_MINALLOC; + while(nByte + sizeof(SyMemHeader) > nBucketSize) { + nBucketSize <<= 1; + nBucket++; + } + pBucket = pBackend->apPool[nBucket]; + if(pBucket == 0) { + sxi32 rc; + rc = MemPoolBucketAlloc(&(*pBackend), nBucket); + if(rc != SXRET_OK) { + return 0; + } + pBucket = pBackend->apPool[nBucket]; + } + /* Remove from the free list */ + pNext = pBucket->pNext; + pBackend->apPool[nBucket] = pNext; + /* Record bucket&magic number */ + pBucket->nBucket = (SXMEM_POOL_MAGIC << 16) | nBucket; + return (void *)&pBucket[1]; +} +PH7_PRIVATE void *SyMemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nByte) { + void *pChunk; +#if defined(UNTRUST) + if(SXMEM_BACKEND_CORRUPT(pBackend)) { + return 0; + } +#endif + if(pBackend->pMutexMethods) { + SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); + } + pChunk = MemBackendPoolAlloc(&(*pBackend), nByte); + if(pBackend->pMutexMethods) { + SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); + } + return pChunk; +} +static sxi32 MemBackendPoolFree(SyMemBackend *pBackend, void *pChunk) { + SyMemHeader *pHeader; + sxu32 nBucket; + /* Get the corresponding bucket */ + pHeader = (SyMemHeader *)(((char *)pChunk) - sizeof(SyMemHeader)); + /* Sanity check to avoid misuse */ + if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) { + return SXERR_CORRUPT; + } + nBucket = pHeader->nBucket & 0xFFFF; + if(nBucket == SXU16_HIGH) { + /* Free the big block */ + MemBackendFree(&(*pBackend), pHeader); + } else { + /* Return to the free list */ + pHeader->pNext = pBackend->apPool[nBucket & 0x0f]; + pBackend->apPool[nBucket & 0x0f] = pHeader; + } + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyMemBackendPoolFree(SyMemBackend *pBackend, void *pChunk) { + sxi32 rc; +#if defined(UNTRUST) + if(SXMEM_BACKEND_CORRUPT(pBackend) || pChunk == 0) { + return SXERR_CORRUPT; + } +#endif + if(pBackend->pMutexMethods) { + SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); + } + rc = MemBackendPoolFree(&(*pBackend), pChunk); + if(pBackend->pMutexMethods) { + SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); + } + return rc; +} +#if 0 +static void *MemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) { + sxu32 nBucket, nBucketSize; + SyMemHeader *pHeader; + void *pNew; + if(pOld == 0) { + /* Allocate a new pool */ + pNew = MemBackendPoolAlloc(&(*pBackend), nByte); + return pNew; + } + /* Get the corresponding bucket */ + pHeader = (SyMemHeader *)(((char *)pOld) - sizeof(SyMemHeader)); + /* Sanity check to avoid misuse */ + if((pHeader->nBucket >> 16) != SXMEM_POOL_MAGIC) { + return 0; + } + nBucket = pHeader->nBucket & 0xFFFF; + if(nBucket == SXU16_HIGH) { + /* Big block */ + return MemBackendRealloc(&(*pBackend), pHeader, nByte); + } + nBucketSize = 1 << (nBucket + SXMEM_POOL_INCR); + if(nBucketSize >= nByte + sizeof(SyMemHeader)) { + /* The old bucket can honor the requested size */ + return pOld; + } + /* Allocate a new pool */ + pNew = MemBackendPoolAlloc(&(*pBackend), nByte); + if(pNew == 0) { + return 0; + } + /* Copy the old data into the new block */ + SyMemcpy(pOld, pNew, nBucketSize); + /* Free the stale block */ + MemBackendPoolFree(&(*pBackend), pOld); + return pNew; +} +PH7_PRIVATE void *SyMemBackendPoolRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nByte) { + void *pChunk; +#if defined(UNTRUST) + if(SXMEM_BACKEND_CORRUPT(pBackend)) { + return 0; + } +#endif + if(pBackend->pMutexMethods) { + SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); + } + pChunk = MemBackendPoolRealloc(&(*pBackend), pOld, nByte); + if(pBackend->pMutexMethods) { + SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); + } + return pChunk; +} +#endif +PH7_PRIVATE sxi32 SyMemBackendInit(SyMemBackend *pBackend, ProcMemError xMemErr, void *pUserData) { +#if defined(UNTRUST) + if(pBackend == 0) { + return SXERR_EMPTY; + } +#endif + /* Zero the allocator first */ + SyZero(&(*pBackend), sizeof(SyMemBackend)); + pBackend->xMemError = xMemErr; + pBackend->pUserData = pUserData; + /* Switch to the OS memory allocator */ + pBackend->pMethods = &sOSAllocMethods; + if(pBackend->pMethods->xInit) { + /* Initialize the backend */ + if(SXRET_OK != pBackend->pMethods->xInit(pBackend->pMethods->pUserData)) { + return SXERR_ABORT; + } + } +#if defined(UNTRUST) + pBackend->nMagic = SXMEM_BACKEND_MAGIC; +#endif + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyMemBackendInitFromOthers(SyMemBackend *pBackend, const SyMemMethods *pMethods, ProcMemError xMemErr, void *pUserData) { +#if defined(UNTRUST) + if(pBackend == 0 || pMethods == 0) { + return SXERR_EMPTY; + } +#endif + if(pMethods->xAlloc == 0 || pMethods->xRealloc == 0 || pMethods->xFree == 0 || pMethods->xChunkSize == 0) { + /* mandatory methods are missing */ + return SXERR_INVALID; + } + /* Zero the allocator first */ + SyZero(&(*pBackend), sizeof(SyMemBackend)); + pBackend->xMemError = xMemErr; + pBackend->pUserData = pUserData; + /* Switch to the host application memory allocator */ + pBackend->pMethods = pMethods; + if(pBackend->pMethods->xInit) { + /* Initialize the backend */ + if(SXRET_OK != pBackend->pMethods->xInit(pBackend->pMethods->pUserData)) { + return SXERR_ABORT; + } + } +#if defined(UNTRUST) + pBackend->nMagic = SXMEM_BACKEND_MAGIC; +#endif + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyMemBackendInitFromParent(SyMemBackend *pBackend, SyMemBackend *pParent) { + sxu8 bInheritMutex; +#if defined(UNTRUST) + if(pBackend == 0 || SXMEM_BACKEND_CORRUPT(pParent)) { + return SXERR_CORRUPT; + } +#endif + /* Zero the allocator first */ + SyZero(&(*pBackend), sizeof(SyMemBackend)); + pBackend->pMethods = pParent->pMethods; + pBackend->xMemError = pParent->xMemError; + pBackend->pUserData = pParent->pUserData; + bInheritMutex = pParent->pMutexMethods ? TRUE : FALSE; + if(bInheritMutex) { + pBackend->pMutexMethods = pParent->pMutexMethods; + /* Create a private mutex */ + pBackend->pMutex = pBackend->pMutexMethods->xNew(SXMUTEX_TYPE_FAST); + if(pBackend->pMutex == 0) { + return SXERR_OS; + } + } +#if defined(UNTRUST) + pBackend->nMagic = SXMEM_BACKEND_MAGIC; +#endif + return SXRET_OK; +} +static sxi32 MemBackendRelease(SyMemBackend *pBackend) { + SyMemBlock *pBlock, *pNext; + pBlock = pBackend->pBlocks; + for(;;) { + if(pBackend->nBlock == 0) { + break; + } + pNext = pBlock->pNext; + pBackend->pMethods->xFree(pBlock); + pBlock = pNext; + pBackend->nBlock--; + /* LOOP ONE */ + if(pBackend->nBlock == 0) { + break; + } + pNext = pBlock->pNext; + pBackend->pMethods->xFree(pBlock); + pBlock = pNext; + pBackend->nBlock--; + /* LOOP TWO */ + if(pBackend->nBlock == 0) { + break; + } + pNext = pBlock->pNext; + pBackend->pMethods->xFree(pBlock); + pBlock = pNext; + pBackend->nBlock--; + /* LOOP THREE */ + if(pBackend->nBlock == 0) { + break; + } + pNext = pBlock->pNext; + pBackend->pMethods->xFree(pBlock); + pBlock = pNext; + pBackend->nBlock--; + /* LOOP FOUR */ + } + if(pBackend->pMethods->xRelease) { + pBackend->pMethods->xRelease(pBackend->pMethods->pUserData); + } + pBackend->pMethods = 0; + pBackend->pBlocks = 0; +#if defined(UNTRUST) + pBackend->nMagic = 0x2626; +#endif + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyMemBackendRelease(SyMemBackend *pBackend) { + sxi32 rc; +#if defined(UNTRUST) + if(SXMEM_BACKEND_CORRUPT(pBackend)) { + return SXERR_INVALID; + } +#endif + if(pBackend->pMutexMethods) { + SyMutexEnter(pBackend->pMutexMethods, pBackend->pMutex); + } + rc = MemBackendRelease(&(*pBackend)); + if(pBackend->pMutexMethods) { + SyMutexLeave(pBackend->pMutexMethods, pBackend->pMutex); + SyMutexRelease(pBackend->pMutexMethods, pBackend->pMutex); + } + return SXRET_OK; +} +PH7_PRIVATE void *SyMemBackendDup(SyMemBackend *pBackend, const void *pSrc, sxu32 nSize) { + void *pNew; +#if defined(UNTRUST) + if(pSrc == 0 || nSize <= 0) { + return 0; + } +#endif + pNew = SyMemBackendAlloc(&(*pBackend), nSize); + if(pNew) { + SyMemcpy(pSrc, pNew, nSize); + } + return pNew; +} +PH7_PRIVATE char *SyMemBackendStrDup(SyMemBackend *pBackend, const char *zSrc, sxu32 nSize) { + char *zDest; + zDest = (char *)SyMemBackendAlloc(&(*pBackend), nSize + 1); + if(zDest) { + Systrcpy(zDest, nSize + 1, zSrc, nSize); + } + return zDest; +} +PH7_PRIVATE sxi32 SyBlobInitFromBuf(SyBlob *pBlob, void *pBuffer, sxu32 nSize) { +#if defined(UNTRUST) + if(pBlob == 0 || pBuffer == 0 || nSize < 1) { + return SXERR_EMPTY; + } +#endif + pBlob->pBlob = pBuffer; + pBlob->mByte = nSize; + pBlob->nByte = 0; + pBlob->pAllocator = 0; + pBlob->nFlags = SXBLOB_LOCKED | SXBLOB_STATIC; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyBlobInit(SyBlob *pBlob, SyMemBackend *pAllocator) { +#if defined(UNTRUST) + if(pBlob == 0) { + return SXERR_EMPTY; + } +#endif + pBlob->pBlob = 0; + pBlob->mByte = pBlob->nByte = 0; + pBlob->pAllocator = &(*pAllocator); + pBlob->nFlags = 0; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyBlobReadOnly(SyBlob *pBlob, const void *pData, sxu32 nByte) { +#if defined(UNTRUST) + if(pBlob == 0) { + return SXERR_EMPTY; + } +#endif + pBlob->pBlob = (void *)pData; + pBlob->nByte = nByte; + pBlob->mByte = 0; + pBlob->nFlags |= SXBLOB_RDONLY; + return SXRET_OK; +} +#ifndef SXBLOB_MIN_GROWTH + #define SXBLOB_MIN_GROWTH 16 +#endif +static sxi32 BlobPrepareGrow(SyBlob *pBlob, sxu32 *pByte) { + sxu32 nByte; + void *pNew; + nByte = *pByte; + if(pBlob->nFlags & (SXBLOB_LOCKED | SXBLOB_STATIC)) { + if(SyBlobFreeSpace(pBlob) < nByte) { + *pByte = SyBlobFreeSpace(pBlob); + if((*pByte) == 0) { + return SXERR_SHORT; + } + } + return SXRET_OK; + } + if(pBlob->nFlags & SXBLOB_RDONLY) { + /* Make a copy of the read-only item */ + if(pBlob->nByte > 0) { + pNew = SyMemBackendDup(pBlob->pAllocator, pBlob->pBlob, pBlob->nByte); + if(pNew == 0) { + return SXERR_MEM; + } + pBlob->pBlob = pNew; + pBlob->mByte = pBlob->nByte; + } else { + pBlob->pBlob = 0; + pBlob->mByte = 0; + } + /* Remove the read-only flag */ + pBlob->nFlags &= ~SXBLOB_RDONLY; + } + if(SyBlobFreeSpace(pBlob) >= nByte) { + return SXRET_OK; + } + if(pBlob->mByte > 0) { + nByte = nByte + pBlob->mByte * 2 + SXBLOB_MIN_GROWTH; + } else if(nByte < SXBLOB_MIN_GROWTH) { + nByte = SXBLOB_MIN_GROWTH; + } + pNew = SyMemBackendRealloc(pBlob->pAllocator, pBlob->pBlob, nByte); + if(pNew == 0) { + return SXERR_MEM; + } + pBlob->pBlob = pNew; + pBlob->mByte = nByte; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyBlobAppend(SyBlob *pBlob, const void *pData, sxu32 nSize) { + sxu8 *zBlob; + sxi32 rc; + if(nSize < 1) { + return SXRET_OK; + } + rc = BlobPrepareGrow(&(*pBlob), &nSize); + if(SXRET_OK != rc) { + return rc; + } + if(pData) { + zBlob = (sxu8 *)pBlob->pBlob ; + zBlob = &zBlob[pBlob->nByte]; + pBlob->nByte += nSize; + SX_MACRO_FAST_MEMCPY(pData, zBlob, nSize); + } + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyBlobNullAppend(SyBlob *pBlob) { + sxi32 rc; + sxu32 n; + n = pBlob->nByte; + rc = SyBlobAppend(&(*pBlob), (const void *)"\0", sizeof(char)); + if(rc == SXRET_OK) { + pBlob->nByte = n; + } + return rc; +} +PH7_PRIVATE sxi32 SyBlobDup(SyBlob *pSrc, SyBlob *pDest) { + sxi32 rc = SXRET_OK; +#ifdef UNTRUST + if(pSrc == 0 || pDest == 0) { + return SXERR_EMPTY; + } +#endif + if(pSrc->nByte > 0) { + rc = SyBlobAppend(&(*pDest), pSrc->pBlob, pSrc->nByte); + } + return rc; +} +PH7_PRIVATE sxi32 SyBlobCmp(SyBlob *pLeft, SyBlob *pRight) { + sxi32 rc; +#ifdef UNTRUST + if(pLeft == 0 || pRight == 0) { + return pLeft ? 1 : -1; + } +#endif + if(pLeft->nByte != pRight->nByte) { + /* Length differ */ + return pLeft->nByte - pRight->nByte; + } + if(pLeft->nByte == 0) { + return 0; + } + /* Perform a standard memcmp() operation */ + rc = SyMemcmp(pLeft->pBlob, pRight->pBlob, pLeft->nByte); + return rc; +} +PH7_PRIVATE sxi32 SyBlobReset(SyBlob *pBlob) { + pBlob->nByte = 0; + if(pBlob->nFlags & SXBLOB_RDONLY) { + pBlob->pBlob = 0; + pBlob->mByte = 0; + pBlob->nFlags &= ~SXBLOB_RDONLY; + } + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyBlobRelease(SyBlob *pBlob) { + if((pBlob->nFlags & (SXBLOB_STATIC | SXBLOB_RDONLY)) == 0 && pBlob->mByte > 0) { + SyMemBackendFree(pBlob->pAllocator, pBlob->pBlob); + } + pBlob->pBlob = 0; + pBlob->nByte = pBlob->mByte = 0; + pBlob->nFlags = 0; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyBlobSearch(const void *pBlob, sxu32 nLen, const void *pPattern, sxu32 pLen, sxu32 *pOfft) { + const char *zIn = (const char *)pBlob; + const char *zEnd; + sxi32 rc; + if(pLen > nLen) { + return SXERR_NOTFOUND; + } + zEnd = &zIn[nLen - pLen]; + for(;;) { + 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++; + 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++; + 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++; + 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++; + } + return SXERR_NOTFOUND; +} \ No newline at end of file diff --git a/engine/lib/mutex.c b/engine/lib/mutex.c new file mode 100644 index 0000000..6205ec7 --- /dev/null +++ b/engine/lib/mutex.c @@ -0,0 +1,216 @@ +#include "ph7int.h" +#if defined(__WINNT__) + #include +#else + #include +#endif + +#if defined(PH7_ENABLE_THREADS) +#if defined(__WINNT__) +struct SyMutex { + CRITICAL_SECTION sMutex; + sxu32 nType; /* Mutex type,one of SXMUTEX_TYPE_* */ +}; +/* Preallocated static mutex */ +static SyMutex aStaticMutexes[] = { + {{0}, SXMUTEX_TYPE_STATIC_1}, + {{0}, SXMUTEX_TYPE_STATIC_2}, + {{0}, SXMUTEX_TYPE_STATIC_3}, + {{0}, SXMUTEX_TYPE_STATIC_4}, + {{0}, SXMUTEX_TYPE_STATIC_5}, + {{0}, SXMUTEX_TYPE_STATIC_6} +}; +static BOOL winMutexInit = FALSE; +static LONG winMutexLock = 0; + +static sxi32 WinMutexGlobaInit(void) { + LONG rc; + rc = InterlockedCompareExchange(&winMutexLock, 1, 0); + if(rc == 0) { + sxu32 n; + for(n = 0 ; n < SX_ARRAYSIZE(aStaticMutexes) ; ++n) { + InitializeCriticalSection(&aStaticMutexes[n].sMutex); + } + winMutexInit = TRUE; + } else { + /* Someone else is doing this for us */ + while(winMutexInit == FALSE) { + Sleep(1); + } + } + return SXRET_OK; +} +static void WinMutexGlobalRelease(void) { + LONG rc; + rc = InterlockedCompareExchange(&winMutexLock, 0, 1); + if(rc == 1) { + /* The first to decrement to zero does the actual global release */ + if(winMutexInit == TRUE) { + sxu32 n; + for(n = 0 ; n < SX_ARRAYSIZE(aStaticMutexes) ; ++n) { + DeleteCriticalSection(&aStaticMutexes[n].sMutex); + } + winMutexInit = FALSE; + } + } +} +static SyMutex *WinMutexNew(int nType) { + SyMutex *pMutex = 0; + if(nType == SXMUTEX_TYPE_FAST || nType == SXMUTEX_TYPE_RECURSIVE) { + /* Allocate a new mutex */ + pMutex = (SyMutex *)HeapAlloc(GetProcessHeap(), 0, sizeof(SyMutex)); + if(pMutex == 0) { + return 0; + } + InitializeCriticalSection(&pMutex->sMutex); + } else { + /* Use a pre-allocated static mutex */ + if(nType > SXMUTEX_TYPE_STATIC_6) { + nType = SXMUTEX_TYPE_STATIC_6; + } + pMutex = &aStaticMutexes[nType - 3]; + } + pMutex->nType = nType; + return pMutex; +} +static void WinMutexRelease(SyMutex *pMutex) { + if(pMutex->nType == SXMUTEX_TYPE_FAST || pMutex->nType == SXMUTEX_TYPE_RECURSIVE) { + DeleteCriticalSection(&pMutex->sMutex); + HeapFree(GetProcessHeap(), 0, pMutex); + } +} +static void WinMutexEnter(SyMutex *pMutex) { + EnterCriticalSection(&pMutex->sMutex); +} +static sxi32 WinMutexTryEnter(SyMutex *pMutex) { +#ifdef _WIN32_WINNT + BOOL rc; + /* Only WindowsNT platforms */ + rc = TryEnterCriticalSection(&pMutex->sMutex); + if(rc) { + return SXRET_OK; + } else { + return SXERR_BUSY; + } +#else + return SXERR_NOTIMPLEMENTED; +#endif +} +static void WinMutexLeave(SyMutex *pMutex) { + LeaveCriticalSection(&pMutex->sMutex); +} +/* Export Windows mutex interfaces */ +static const SyMutexMethods sWinMutexMethods = { + WinMutexGlobaInit, /* xGlobalInit() */ + WinMutexGlobalRelease, /* xGlobalRelease() */ + WinMutexNew, /* xNew() */ + WinMutexRelease, /* xRelease() */ + WinMutexEnter, /* xEnter() */ + WinMutexTryEnter, /* xTryEnter() */ + WinMutexLeave /* xLeave() */ +}; +PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) { + return &sWinMutexMethods; +} +#elif defined(__UNIXES__) +#include +struct SyMutex { + pthread_mutex_t sMutex; + sxu32 nType; +}; +static SyMutex *UnixMutexNew(int nType) { + static SyMutex aStaticMutexes[] = { + {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_1}, + {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_2}, + {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_3}, + {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_4}, + {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_5}, + {PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_6} + }; + SyMutex *pMutex; + if(nType == SXMUTEX_TYPE_FAST || nType == SXMUTEX_TYPE_RECURSIVE) { + pthread_mutexattr_t sRecursiveAttr; + /* Allocate a new mutex */ + pMutex = (SyMutex *)malloc(sizeof(SyMutex)); + if(pMutex == 0) { + return 0; + } + if(nType == SXMUTEX_TYPE_RECURSIVE) { + pthread_mutexattr_init(&sRecursiveAttr); + pthread_mutexattr_settype(&sRecursiveAttr, PTHREAD_MUTEX_RECURSIVE); + } + pthread_mutex_init(&pMutex->sMutex, nType == SXMUTEX_TYPE_RECURSIVE ? &sRecursiveAttr : 0); + if(nType == SXMUTEX_TYPE_RECURSIVE) { + pthread_mutexattr_destroy(&sRecursiveAttr); + } + } else { + /* Use a pre-allocated static mutex */ + if(nType > SXMUTEX_TYPE_STATIC_6) { + nType = SXMUTEX_TYPE_STATIC_6; + } + pMutex = &aStaticMutexes[nType - 3]; + } + pMutex->nType = nType; + return pMutex; +} +static void UnixMutexRelease(SyMutex *pMutex) { + if(pMutex->nType == SXMUTEX_TYPE_FAST || pMutex->nType == SXMUTEX_TYPE_RECURSIVE) { + pthread_mutex_destroy(&pMutex->sMutex); + free(pMutex); + } +} +static void UnixMutexEnter(SyMutex *pMutex) { + pthread_mutex_lock(&pMutex->sMutex); +} +static void UnixMutexLeave(SyMutex *pMutex) { + pthread_mutex_unlock(&pMutex->sMutex); +} +/* Export pthread mutex interfaces */ +static const SyMutexMethods sPthreadMutexMethods = { + 0, /* xGlobalInit() */ + 0, /* xGlobalRelease() */ + UnixMutexNew, /* xNew() */ + UnixMutexRelease, /* xRelease() */ + UnixMutexEnter, /* xEnter() */ + 0, /* xTryEnter() */ + UnixMutexLeave /* xLeave() */ +}; +PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) { + return &sPthreadMutexMethods; +} +#else +/* Host application must register their own mutex subsystem if the target + * platform is not an UNIX-like or windows systems. + */ +struct SyMutex { + sxu32 nType; +}; +static SyMutex *DummyMutexNew(int nType) { + static SyMutex sMutex; + SXUNUSED(nType); + return &sMutex; +} +static void DummyMutexRelease(SyMutex *pMutex) { + SXUNUSED(pMutex); +} +static void DummyMutexEnter(SyMutex *pMutex) { + SXUNUSED(pMutex); +} +static void DummyMutexLeave(SyMutex *pMutex) { + SXUNUSED(pMutex); +} +/* Export the dummy mutex interfaces */ +static const SyMutexMethods sDummyMutexMethods = { + 0, /* xGlobalInit() */ + 0, /* xGlobalRelease() */ + DummyMutexNew, /* xNew() */ + DummyMutexRelease, /* xRelease() */ + DummyMutexEnter, /* xEnter() */ + 0, /* xTryEnter() */ + DummyMutexLeave /* xLeave() */ +}; +PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) { + return &sDummyMutexMethods; +} +#endif /* __WINNT__ */ +#endif /* PH7_ENABLE_THREADS */ \ No newline at end of file diff --git a/engine/lib/random.c b/engine/lib/random.c new file mode 100644 index 0000000..09a83d7 --- /dev/null +++ b/engine/lib/random.c @@ -0,0 +1,143 @@ +#include "ph7int.h" + +/* + * Psuedo Random Number Generator (PRNG) + * @authors: SQLite authors + * @status: Public Domain + * NOTE: + * Nothing in this file or anywhere else in the library does any kind of + * encryption.The RC4 algorithm is being used as a PRNG (pseudo-random + * number generator) not as an encryption device. + */ +#define SXPRNG_MAGIC 0x13C4 +#ifdef __UNIXES__ + #include + #include + #include + #include + #include + #include + #include +#endif +static sxi32 SyOSUtilRandomSeed(void *pBuf, sxu32 nLen, void *pUnused) { + char *zBuf = (char *)pBuf; +#ifdef __WINNT__ + DWORD nProcessID; /* Yes,keep it uninitialized when compiling using the MinGW32 builds tools */ +#elif defined(__UNIXES__) + pid_t pid; + int fd; +#else + char zGarbage[128]; /* Yes,keep this buffer uninitialized */ +#endif + SXUNUSED(pUnused); +#ifdef __WINNT__ +#ifndef __MINGW32__ + nProcessID = GetProcessId(GetCurrentProcess()); +#endif + SyMemcpy((const void *)&nProcessID, zBuf, SXMIN(nLen, sizeof(DWORD))); + if((sxu32)(&zBuf[nLen] - &zBuf[sizeof(DWORD)]) >= sizeof(SYSTEMTIME)) { + GetSystemTime((LPSYSTEMTIME)&zBuf[sizeof(DWORD)]); + } +#elif defined(__UNIXES__) + fd = open("/dev/urandom", O_RDONLY); + if(fd >= 0) { + if(read(fd, zBuf, nLen) > 0) { + close(fd); + return SXRET_OK; + } + /* FALL THRU */ + } + close(fd); + pid = getpid(); + SyMemcpy((const void *)&pid, zBuf, SXMIN(nLen, sizeof(pid_t))); + if(&zBuf[nLen] - &zBuf[sizeof(pid_t)] >= (int)sizeof(struct timeval)) { + gettimeofday((struct timeval *)&zBuf[sizeof(pid_t)], 0); + } +#else + /* Fill with uninitialized data */ + SyMemcpy(zGarbage, zBuf, SXMIN(nLen, sizeof(zGarbage))); +#endif + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyRandomnessInit(SyPRNGCtx *pCtx, ProcRandomSeed xSeed, void *pUserData) { + char zSeed[256]; + sxu8 t; + sxi32 rc; + sxu32 i; + if(pCtx->nMagic == SXPRNG_MAGIC) { + return SXRET_OK; /* Already initialized */ + } + /* Initialize the state of the random number generator once, + ** the first time this routine is called.The seed value does + ** not need to contain a lot of randomness since we are not + ** trying to do secure encryption or anything like that... + */ + if(xSeed == 0) { + xSeed = SyOSUtilRandomSeed; + } + rc = xSeed(zSeed, sizeof(zSeed), pUserData); + if(rc != SXRET_OK) { + return rc; + } + pCtx->i = pCtx->j = 0; + for(i = 0; i < SX_ARRAYSIZE(pCtx->s) ; i++) { + pCtx->s[i] = (unsigned char)i; + } + for(i = 0; i < sizeof(zSeed) ; i++) { + pCtx->j += pCtx->s[i] + zSeed[i]; + t = pCtx->s[pCtx->j]; + pCtx->s[pCtx->j] = pCtx->s[i]; + pCtx->s[i] = t; + } + pCtx->nMagic = SXPRNG_MAGIC; + return SXRET_OK; +} +/* + * Get a single 8-bit random value using the RC4 PRNG. + */ +static sxu8 randomByte(SyPRNGCtx *pCtx) { + sxu8 t; + /* Generate and return single random byte */ + pCtx->i++; + t = pCtx->s[pCtx->i]; + pCtx->j += t; + pCtx->s[pCtx->i] = pCtx->s[pCtx->j]; + pCtx->s[pCtx->j] = t; + t += pCtx->s[pCtx->i]; + return pCtx->s[t]; +} +PH7_PRIVATE sxi32 SyRandomness(SyPRNGCtx *pCtx, void *pBuf, sxu32 nLen) { + unsigned char *zBuf = (unsigned char *)pBuf; + unsigned char *zEnd = &zBuf[nLen]; +#if defined(UNTRUST) + if(pCtx == 0 || pBuf == 0 || nLen <= 0) { + return SXERR_EMPTY; + } +#endif + if(pCtx->nMagic != SXPRNG_MAGIC) { + return SXERR_CORRUPT; + } + for(;;) { + if(zBuf >= zEnd) { + break; + } + zBuf[0] = randomByte(pCtx); + zBuf++; + if(zBuf >= zEnd) { + break; + } + zBuf[0] = randomByte(pCtx); + zBuf++; + if(zBuf >= zEnd) { + break; + } + zBuf[0] = randomByte(pCtx); + zBuf++; + if(zBuf >= zEnd) { + break; + } + zBuf[0] = randomByte(pCtx); + zBuf++; + } + return SXRET_OK; +} \ No newline at end of file diff --git a/engine/lib/string.c b/engine/lib/string.c new file mode 100644 index 0000000..f714568 --- /dev/null +++ b/engine/lib/string.c @@ -0,0 +1,342 @@ +#include "ph7int.h" + +PH7_PRIVATE sxu32 SyStrlen(const char *zSrc) { + register const char *zIn = zSrc; +#if defined(UNTRUST) + if(zIn == 0) { + return 0; + } +#endif + for(;;) { + if(!zIn[0]) { + break; + } + zIn++; + if(!zIn[0]) { + break; + } + zIn++; + if(!zIn[0]) { + break; + } + zIn++; + if(!zIn[0]) { + break; + } + zIn++; + } + return (sxu32)(zIn - zSrc); +} +PH7_PRIVATE sxi32 SyByteFind(const char *zStr, sxu32 nLen, sxi32 c, sxu32 *pPos) { + const char *zIn = zStr; + const char *zEnd; + zEnd = &zIn[nLen]; + for(;;) { + if(zIn >= zEnd) { + break; + } + if(zIn[0] == c) { + if(pPos) { + *pPos = (sxu32)(zIn - zStr); + } + return SXRET_OK; + } + zIn++; + if(zIn >= zEnd) { + break; + } + if(zIn[0] == c) { + if(pPos) { + *pPos = (sxu32)(zIn - zStr); + } + return SXRET_OK; + } + zIn++; + if(zIn >= zEnd) { + break; + } + if(zIn[0] == c) { + if(pPos) { + *pPos = (sxu32)(zIn - zStr); + } + return SXRET_OK; + } + zIn++; + if(zIn >= zEnd) { + break; + } + if(zIn[0] == c) { + if(pPos) { + *pPos = (sxu32)(zIn - zStr); + } + return SXRET_OK; + } + zIn++; + } + return SXERR_NOTFOUND; +} +PH7_PRIVATE sxi32 SyByteFind2(const char *zStr, sxu32 nLen, sxi32 c, sxu32 *pPos) { + const char *zIn = zStr; + const char *zEnd; + zEnd = &zIn[nLen - 1]; + for(;;) { + if(zEnd < zIn) { + break; + } + if(zEnd[0] == c) { + if(pPos) { + *pPos = (sxu32)(zEnd - zIn); + } + return SXRET_OK; + } + zEnd--; + if(zEnd < zIn) { + break; + } + if(zEnd[0] == c) { + if(pPos) { + *pPos = (sxu32)(zEnd - zIn); + } + return SXRET_OK; + } + zEnd--; + if(zEnd < zIn) { + break; + } + if(zEnd[0] == c) { + if(pPos) { + *pPos = (sxu32)(zEnd - zIn); + } + return SXRET_OK; + } + zEnd--; + if(zEnd < zIn) { + break; + } + if(zEnd[0] == c) { + if(pPos) { + *pPos = (sxu32)(zEnd - zIn); + } + return SXRET_OK; + } + zEnd--; + } + return SXERR_NOTFOUND; +} +PH7_PRIVATE sxi32 SyByteListFind(const char *zSrc, sxu32 nLen, const char *zList, sxu32 *pFirstPos) { + const char *zIn = zSrc; + const char *zPtr; + const char *zEnd; + sxi32 c; + zEnd = &zSrc[nLen]; + for(;;) { + 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++; + 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++; + 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++; + 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++; + } + return SXERR_NOTFOUND; +} +PH7_PRIVATE sxi32 SyStrncmp(const char *zLeft, const char *zRight, sxu32 nLen) { + const unsigned char *zP = (const unsigned char *)zLeft; + const unsigned char *zQ = (const unsigned char *)zRight; + if(SX_EMPTY_STR(zP) || SX_EMPTY_STR(zQ)) { + return SX_EMPTY_STR(zP) ? (SX_EMPTY_STR(zQ) ? 0 : -1) : 1; + } + if(nLen <= 0) { + return 0; + } + for(;;) { + if(nLen <= 0) { + return 0; + } + if(zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0]) { + break; + } + zP++; + zQ++; + nLen--; + if(nLen <= 0) { + return 0; + } + if(zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0]) { + break; + } + zP++; + zQ++; + nLen--; + if(nLen <= 0) { + return 0; + } + if(zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0]) { + break; + } + zP++; + zQ++; + nLen--; + if(nLen <= 0) { + return 0; + } + if(zP[0] == 0 || zQ[0] == 0 || zP[0] != zQ[0]) { + break; + } + zP++; + zQ++; + nLen--; + } + return (sxi32)(zP[0] - zQ[0]); +} +PH7_PRIVATE sxi32 SyStrnicmp(const char *zLeft, const char *zRight, sxu32 SLen) { + register unsigned char *p = (unsigned char *)zLeft; + register unsigned char *q = (unsigned char *)zRight; + if(SX_EMPTY_STR(p) || SX_EMPTY_STR(q)) { + return SX_EMPTY_STR(p) ? SX_EMPTY_STR(q) ? 0 : -1 : 1; + } + for(;;) { + if(!SLen) { + return 0; + } + if(!*p || !*q || SyCharToLower(*p) != SyCharToLower(*q)) { + break; + } + p++; + q++; + --SLen; + if(!SLen) { + return 0; + } + if(!*p || !*q || SyCharToLower(*p) != SyCharToLower(*q)) { + break; + } + p++; + q++; + --SLen; + if(!SLen) { + return 0; + } + if(!*p || !*q || SyCharToLower(*p) != SyCharToLower(*q)) { + break; + } + p++; + q++; + --SLen; + if(!SLen) { + return 0; + } + if(!*p || !*q || SyCharToLower(*p) != SyCharToLower(*q)) { + break; + } + p++; + q++; + --SLen; + } + return (sxi32)(SyCharToLower(p[0]) - SyCharToLower(q[0])); +} +PH7_PRIVATE sxi32 SyStrnmicmp(const void *pLeft, const void *pRight, sxu32 SLen) { + return SyStrnicmp((const char *)pLeft, (const char *)pRight, SLen); +} +sxu32 Systrcpy(char *zDest, sxu32 nDestLen, const char *zSrc, sxu32 nLen) { + unsigned char *zBuf = (unsigned char *)zDest; + unsigned char *zIn = (unsigned char *)zSrc; + unsigned char *zEnd; +#if defined(UNTRUST) + if(zSrc == (const char *)zDest) { + return 0; + } +#endif + if(nLen <= 0) { + nLen = SyStrlen(zSrc); + } + zEnd = &zBuf[nDestLen - 1]; /* reserve a room for the null terminator */ + for(;;) { + if(zBuf >= zEnd || nLen == 0) { + break; + } + zBuf[0] = zIn[0]; + zIn++; + zBuf++; + nLen--; + if(zBuf >= zEnd || nLen == 0) { + break; + } + zBuf[0] = zIn[0]; + zIn++; + zBuf++; + nLen--; + if(zBuf >= zEnd || nLen == 0) { + break; + } + zBuf[0] = zIn[0]; + zIn++; + zBuf++; + nLen--; + if(zBuf >= zEnd || nLen == 0) { + break; + } + zBuf[0] = zIn[0]; + zIn++; + zBuf++; + nLen--; + } + zBuf[0] = 0; + return (sxu32)(zBuf - (unsigned char *)zDest); +} +sxi32 SyAsciiToHex(sxi32 c) { + if(c >= 'a' && c <= 'f') { + c += 10 - 'a'; + return c; + } + if(c >= '0' && c <= '9') { + c -= '0'; + return c; + } + if(c >= 'A' && c <= 'F') { + c += 10 - 'A'; + return c; + } + return 0; +} \ No newline at end of file diff --git a/engine/lib/tokenizer.c b/engine/lib/tokenizer.c new file mode 100644 index 0000000..9679762 --- /dev/null +++ b/engine/lib/tokenizer.c @@ -0,0 +1,95 @@ +#include "ph7int.h" + +#define INVALID_LEXER(LEX) ( LEX == 0 || LEX->xTokenizer == 0 ) + +PH7_PRIVATE sxi32 SyLexInit(SyLex *pLex, SySet *pSet, ProcTokenizer xTokenizer, void *pUserData) { + SyStream *pStream; +#if defined (UNTRUST) + if(pLex == 0 || xTokenizer == 0) { + return SXERR_CORRUPT; + } +#endif + pLex->pTokenSet = 0; + /* Initialize lexer fields */ + if(pSet) { + if(SySetElemSize(pSet) != sizeof(SyToken)) { + return SXERR_INVALID; + } + pLex->pTokenSet = pSet; + } + pStream = &pLex->sStream; + pLex->xTokenizer = xTokenizer; + pLex->pUserData = pUserData; + pStream->nLine = 1; + pStream->nIgn = 0; + pStream->zText = pStream->zEnd = 0; + pStream->pSet = pSet; + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyLexTokenizeInput(SyLex *pLex, const char *zInput, sxu32 nLen, void *pCtxData, ProcSort xSort, ProcCmp xCmp) { + const unsigned char *zCur; + SyStream *pStream; + SyToken sToken; + sxi32 rc; +#if defined (UNTRUST) + if(INVALID_LEXER(pLex) || zInput == 0) { + return SXERR_CORRUPT; + } +#endif + pStream = &pLex->sStream; + /* Point to the head of the input */ + pStream->zText = pStream->zInput = (const unsigned char *)zInput; + /* Point to the end of the input */ + pStream->zEnd = &pStream->zInput[nLen]; + for(;;) { + if(pStream->zText >= pStream->zEnd) { + /* End of the input reached */ + break; + } + zCur = pStream->zText; + /* Call the tokenizer callback */ + rc = pLex->xTokenizer(pStream, &sToken, pLex->pUserData, pCtxData); + if(rc != SXRET_OK && rc != SXERR_CONTINUE) { + /* Tokenizer callback request an operation abort */ + if(rc == SXERR_ABORT) { + return SXERR_ABORT; + } + break; + } + if(rc == SXERR_CONTINUE) { + /* Request to ignore this token */ + pStream->nIgn++; + } else if(pLex->pTokenSet) { + /* Put the token in the set */ + rc = SySetPut(pLex->pTokenSet, (const void *)&sToken); + if(rc != SXRET_OK) { + break; + } + } + if(zCur >= pStream->zText) { + /* Automatic advance of the stream cursor */ + pStream->zText = &zCur[1]; + } + } + if(xSort && pLex->pTokenSet) { + SyToken *aToken = (SyToken *)SySetBasePtr(pLex->pTokenSet); + /* Sort the extrated tokens */ + if(xCmp == 0) { + /* Use a default comparison function */ + xCmp = SyMemcmp; + } + xSort(aToken, SySetUsed(pLex->pTokenSet), sizeof(SyToken), xCmp); + } + return SXRET_OK; +} +PH7_PRIVATE sxi32 SyLexRelease(SyLex *pLex) { + sxi32 rc = SXRET_OK; +#if defined (UNTRUST) + if(INVALID_LEXER(pLex)) { + return SXERR_CORRUPT; + } +#else + SXUNUSED(pLex); /* Prevent compiler warning */ +#endif + return rc; +} \ No newline at end of file diff --git a/engine/lib/utils.c b/engine/lib/utils.c new file mode 100644 index 0000000..f864024 --- /dev/null +++ b/engine/lib/utils.c @@ -0,0 +1,631 @@ +#include "ph7int.h" + +PH7_PRIVATE sxi32 SyStrIsNumeric(const char *zSrc, sxu32 nLen, sxu8 *pReal, const char **pzTail) { + const char *zCur, *zEnd; +#ifdef UNTRUST + if(SX_EMPTY_STR(zSrc)) { + return SXERR_EMPTY; + } +#endif + zEnd = &zSrc[nLen]; + /* Jump leading white spaces */ + while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) { + zSrc++; + } + zCur = zSrc; + if(pReal) { + *pReal = FALSE; + } + for(;;) { + if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) { + break; + } + zSrc++; + if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) { + break; + } + zSrc++; + if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) { + break; + } + zSrc++; + if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) { + break; + } + zSrc++; + }; + if(zSrc < zEnd && zSrc > zCur) { + int c = zSrc[0]; + if(c == '.') { + zSrc++; + if(pReal) { + *pReal = TRUE; + } + if(pzTail) { + while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) { + zSrc++; + } + if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) { + zSrc++; + if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) { + zSrc++; + } + while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) { + zSrc++; + } + } + } + } else if(c == 'e' || c == 'E') { + zSrc++; + if(pReal) { + *pReal = TRUE; + } + if(pzTail) { + if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) { + zSrc++; + } + while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) { + zSrc++; + } + } + } + } + if(pzTail) { + /* Point to the non numeric part */ + *pzTail = zSrc; + } + return zSrc > zCur ? SXRET_OK /* String prefix is numeric */ : SXERR_INVALID /* Not a digit stream */; +} +#define SXINT32_MIN_STR "2147483648" +#define SXINT32_MAX_STR "2147483647" +#define SXINT64_MIN_STR "9223372036854775808" +#define SXINT64_MAX_STR "9223372036854775807" +PH7_PRIVATE sxi32 SyStrToInt32(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { + int isNeg = FALSE; + const char *zEnd; + sxi32 nVal = 0; + sxi16 i; +#if defined(UNTRUST) + if(SX_EMPTY_STR(zSrc)) { + if(pOutVal) { + *(sxi32 *)pOutVal = 0; + } + return SXERR_EMPTY; + } +#endif + zEnd = &zSrc[nLen]; + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { + isNeg = (zSrc[0] == '-') ? TRUE : FALSE; + zSrc++; + } + /* Skip leading zero */ + while(zSrc < zEnd && zSrc[0] == '0') { + zSrc++; + } + i = 10; + if((sxu32)(zEnd - zSrc) >= 10) { + /* Handle overflow */ + i = SyMemcmp(zSrc, (isNeg == TRUE) ? SXINT32_MIN_STR : SXINT32_MAX_STR, nLen) <= 0 ? 10 : 9; + } + for(;;) { + if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { + break; + } + nVal = nVal * 10 + (zSrc[0] - '0') ; + --i ; + zSrc++; + if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { + break; + } + nVal = nVal * 10 + (zSrc[0] - '0') ; + --i ; + zSrc++; + if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { + break; + } + nVal = nVal * 10 + (zSrc[0] - '0') ; + --i ; + zSrc++; + if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { + break; + } + nVal = nVal * 10 + (zSrc[0] - '0') ; + --i ; + zSrc++; + } + /* Skip trailing spaces */ + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zRest) { + *zRest = (char *)zSrc; + } + if(pOutVal) { + if(isNeg == TRUE && nVal != 0) { + nVal = -nVal; + } + *(sxi32 *)pOutVal = nVal; + } + return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; +} +PH7_PRIVATE sxi32 SyStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { + int isNeg = FALSE; + const char *zEnd; + sxi64 nVal; + sxi16 i; +#if defined(UNTRUST) + if(SX_EMPTY_STR(zSrc)) { + if(pOutVal) { + *(sxi32 *)pOutVal = 0; + } + return SXERR_EMPTY; + } +#endif + zEnd = &zSrc[nLen]; + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { + isNeg = (zSrc[0] == '-') ? TRUE : FALSE; + zSrc++; + } + /* Skip leading zero */ + while(zSrc < zEnd && zSrc[0] == '0') { + zSrc++; + } + i = 19; + if((sxu32)(zEnd - zSrc) >= 19) { + i = SyMemcmp(zSrc, isNeg ? SXINT64_MIN_STR : SXINT64_MAX_STR, 19) <= 0 ? 19 : 18 ; + } + nVal = 0; + for(;;) { + if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { + break; + } + nVal = nVal * 10 + (zSrc[0] - '0') ; + --i ; + zSrc++; + if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { + break; + } + nVal = nVal * 10 + (zSrc[0] - '0') ; + --i ; + zSrc++; + if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { + break; + } + nVal = nVal * 10 + (zSrc[0] - '0') ; + --i ; + zSrc++; + if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) { + break; + } + nVal = nVal * 10 + (zSrc[0] - '0') ; + --i ; + zSrc++; + } + /* Skip trailing spaces */ + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zRest) { + *zRest = (char *)zSrc; + } + if(pOutVal) { + if(isNeg == TRUE && nVal != 0) { + nVal = -nVal; + } + *(sxi64 *)pOutVal = nVal; + } + return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; +} +PH7_PRIVATE sxi32 SyHexToint(sxi32 c) { + switch(c) { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + case 'A': + case 'a': + return 10; + case 'B': + case 'b': + return 11; + case 'C': + case 'c': + return 12; + case 'D': + case 'd': + return 13; + case 'E': + case 'e': + return 14; + case 'F': + case 'f': + return 15; + } + return -1; +} +PH7_PRIVATE sxi32 SyHexStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { + const char *zIn, *zEnd; + int isNeg = FALSE; + sxi64 nVal = 0; +#if defined(UNTRUST) + if(SX_EMPTY_STR(zSrc)) { + if(pOutVal) { + *(sxi32 *)pOutVal = 0; + } + return SXERR_EMPTY; + } +#endif + zEnd = &zSrc[nLen]; + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zSrc < zEnd && (*zSrc == '-' || *zSrc == '+')) { + isNeg = (zSrc[0] == '-') ? TRUE : FALSE; + zSrc++; + } + if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'x' || zSrc[1] == 'X')) { + /* Bypass hex prefix */ + zSrc += sizeof(char) * 2; + } + /* Skip leading zero */ + while(zSrc < zEnd && zSrc[0] == '0') { + zSrc++; + } + zIn = zSrc; + for(;;) { + if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) { + break; + } + nVal = nVal * 16 + SyHexToint(zSrc[0]); + zSrc++ ; + if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) { + break; + } + nVal = nVal * 16 + SyHexToint(zSrc[0]); + zSrc++ ; + if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) { + break; + } + nVal = nVal * 16 + SyHexToint(zSrc[0]); + zSrc++ ; + if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) { + break; + } + nVal = nVal * 16 + SyHexToint(zSrc[0]); + zSrc++ ; + } + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zRest) { + *zRest = zSrc; + } + if(pOutVal) { + if(isNeg == TRUE && nVal != 0) { + nVal = -nVal; + } + *(sxi64 *)pOutVal = nVal; + } + return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX; +} +PH7_PRIVATE sxi32 SyOctalStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { + const char *zIn, *zEnd; + int isNeg = FALSE; + sxi64 nVal = 0; + int c; +#if defined(UNTRUST) + if(SX_EMPTY_STR(zSrc)) { + if(pOutVal) { + *(sxi32 *)pOutVal = 0; + } + return SXERR_EMPTY; + } +#endif + zEnd = &zSrc[nLen]; + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { + isNeg = (zSrc[0] == '-') ? TRUE : FALSE; + zSrc++; + } + /* Skip leading zero */ + while(zSrc < zEnd && zSrc[0] == '0') { + zSrc++; + } + zIn = zSrc; + for(;;) { + if(zSrc >= zEnd || !SyisDigit(zSrc[0])) { + break; + } + if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) { + break; + } + nVal = nVal * 8 + c; + zSrc++; + if(zSrc >= zEnd || !SyisDigit(zSrc[0])) { + break; + } + if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) { + break; + } + nVal = nVal * 8 + c; + zSrc++; + if(zSrc >= zEnd || !SyisDigit(zSrc[0])) { + break; + } + if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) { + break; + } + nVal = nVal * 8 + c; + zSrc++; + if(zSrc >= zEnd || !SyisDigit(zSrc[0])) { + break; + } + if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) { + break; + } + nVal = nVal * 8 + c; + zSrc++; + } + /* Skip trailing spaces */ + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zRest) { + *zRest = zSrc; + } + if(pOutVal) { + if(isNeg == TRUE && nVal != 0) { + nVal = -nVal; + } + *(sxi64 *)pOutVal = nVal; + } + return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; +} +PH7_PRIVATE sxi32 SyBinaryStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { + const char *zIn, *zEnd; + int isNeg = FALSE; + sxi64 nVal = 0; + int c; +#if defined(UNTRUST) + if(SX_EMPTY_STR(zSrc)) { + if(pOutVal) { + *(sxi32 *)pOutVal = 0; + } + return SXERR_EMPTY; + } +#endif + zEnd = &zSrc[nLen]; + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { + isNeg = (zSrc[0] == '-') ? TRUE : FALSE; + zSrc++; + } + if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'b' || zSrc[1] == 'B')) { + /* Bypass binary prefix */ + zSrc += sizeof(char) * 2; + } + /* Skip leading zero */ + while(zSrc < zEnd && zSrc[0] == '0') { + zSrc++; + } + zIn = zSrc; + for(;;) { + if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) { + break; + } + c = zSrc[0] - '0'; + nVal = (nVal << 1) + c; + zSrc++; + if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) { + break; + } + c = zSrc[0] - '0'; + nVal = (nVal << 1) + c; + zSrc++; + if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) { + break; + } + c = zSrc[0] - '0'; + nVal = (nVal << 1) + c; + zSrc++; + if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) { + break; + } + c = zSrc[0] - '0'; + nVal = (nVal << 1) + c; + zSrc++; + } + /* Skip trailing spaces */ + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zRest) { + *zRest = zSrc; + } + if(pOutVal) { + if(isNeg == TRUE && nVal != 0) { + nVal = -nVal; + } + *(sxi64 *)pOutVal = nVal; + } + return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX; +} +PH7_PRIVATE sxi32 SyStrToReal(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) { +#define SXDBL_DIG 15 +#define SXDBL_MAX_EXP 308 +#define SXDBL_MIN_EXP_PLUS 307 + static const sxreal aTab[] = { + 10, + 1.0e2, + 1.0e4, + 1.0e8, + 1.0e16, + 1.0e32, + 1.0e64, + 1.0e128, + 1.0e256 + }; + sxu8 neg = FALSE; + sxreal Val = 0.0; + const char *zEnd; + sxi32 Lim, exp; + sxreal *p = 0; +#ifdef UNTRUST + if(SX_EMPTY_STR(zSrc)) { + if(pOutVal) { + *(sxreal *)pOutVal = 0.0; + } + return SXERR_EMPTY; + } +#endif + zEnd = &zSrc[nLen]; + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { + neg = zSrc[0] == '-' ? TRUE : FALSE ; + zSrc++; + } + Lim = SXDBL_DIG ; + for(;;) { + if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { + break ; + } + Val = Val * 10.0 + (zSrc[0] - '0') ; + zSrc++ ; + --Lim; + if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { + break ; + } + Val = Val * 10.0 + (zSrc[0] - '0') ; + zSrc++ ; + --Lim; + if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { + break ; + } + Val = Val * 10.0 + (zSrc[0] - '0') ; + zSrc++ ; + --Lim; + if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { + break ; + } + Val = Val * 10.0 + (zSrc[0] - '0') ; + zSrc++ ; + --Lim; + } + if(zSrc < zEnd && (zSrc[0] == '.' || zSrc[0] == ',')) { + sxreal dec = 1.0; + zSrc++; + for(;;) { + if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { + break ; + } + Val = Val * 10.0 + (zSrc[0] - '0') ; + dec *= 10.0; + zSrc++ ; + --Lim; + if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { + break ; + } + Val = Val * 10.0 + (zSrc[0] - '0') ; + dec *= 10.0; + zSrc++ ; + --Lim; + if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { + break ; + } + Val = Val * 10.0 + (zSrc[0] - '0') ; + dec *= 10.0; + zSrc++ ; + --Lim; + if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) { + break ; + } + Val = Val * 10.0 + (zSrc[0] - '0') ; + dec *= 10.0; + zSrc++ ; + --Lim; + } + Val /= dec; + } + if(neg == TRUE && Val != 0.0) { + Val = -Val ; + } + if(Lim <= 0) { + /* jump overflow digit */ + while(zSrc < zEnd) { + if(zSrc[0] == 'e' || zSrc[0] == 'E') { + break; + } + zSrc++; + } + } + neg = FALSE; + if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) { + zSrc++; + if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) { + neg = zSrc[0] == '-' ? TRUE : FALSE ; + zSrc++; + } + exp = 0; + while(zSrc < zEnd && SyisDigit(zSrc[0]) && exp < SXDBL_MAX_EXP) { + exp = exp * 10 + (zSrc[0] - '0'); + zSrc++; + } + if(neg) { + if(exp > SXDBL_MIN_EXP_PLUS) { + exp = SXDBL_MIN_EXP_PLUS ; + } + } else if(exp > SXDBL_MAX_EXP) { + exp = SXDBL_MAX_EXP; + } + for(p = (sxreal *)aTab ; exp ; exp >>= 1, p++) { + if(exp & 01) { + if(neg) { + Val /= *p ; + } else { + Val *= *p; + } + } + } + } + while(zSrc < zEnd && SyisSpace(zSrc[0])) { + zSrc++; + } + if(zRest) { + *zRest = zSrc; + } + if(pOutVal) { + *(sxreal *)pOutVal = Val; + } + return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX; +} \ No newline at end of file