Aer Interpreter Source
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

4901 lines
130 KiB

/*
* 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 <chm@symisc.net> $ */
/*
* 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 <Windows.h>
#else
#include <stdlib.h>
#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 <pthread.h>
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[<