diff options
Diffstat (limited to 'ext/lsm1/lsm_str.c')
-rw-r--r-- | ext/lsm1/lsm_str.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/ext/lsm1/lsm_str.c b/ext/lsm1/lsm_str.c new file mode 100644 index 0000000..9b1b63c --- /dev/null +++ b/ext/lsm1/lsm_str.c @@ -0,0 +1,148 @@ +/* +** 2012-04-27 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** Dynamic string functions. +*/ +#include "lsmInt.h" + +/* +** Turn bulk and uninitialized memory into an LsmString object +*/ +void lsmStringInit(LsmString *pStr, lsm_env *pEnv){ + memset(pStr, 0, sizeof(pStr[0])); + pStr->pEnv = pEnv; +} + +/* +** Increase the memory allocated for holding the string. Realloc as needed. +** +** If a memory allocation error occurs, set pStr->n to -1 and free the existing +** allocation. If a prior memory allocation has occurred, this routine is a +** no-op. +*/ +int lsmStringExtend(LsmString *pStr, int nNew){ + assert( nNew>0 ); + if( pStr->n<0 ) return LSM_NOMEM; + if( pStr->n + nNew >= pStr->nAlloc ){ + int nAlloc = pStr->n + nNew + 100; + char *zNew = lsmRealloc(pStr->pEnv, pStr->z, nAlloc); + if( zNew==0 ){ + lsmFree(pStr->pEnv, pStr->z); + nAlloc = 0; + pStr->n = -1; + } + pStr->nAlloc = nAlloc; + pStr->z = zNew; + } + return (pStr->z ? LSM_OK : LSM_NOMEM_BKPT); +} + +/* +** Clear an LsmString object, releasing any allocated memory that it holds. +** This also clears the error indication (if any). +*/ +void lsmStringClear(LsmString *pStr){ + lsmFree(pStr->pEnv, pStr->z); + lsmStringInit(pStr, pStr->pEnv); +} + +/* +** Append N bytes of text to the end of an LsmString object. If +** N is negative, append the entire string. +** +** If the string is in an error state, this routine is a no-op. +*/ +int lsmStringAppend(LsmString *pStr, const char *z, int N){ + int rc; + if( N<0 ) N = (int)strlen(z); + rc = lsmStringExtend(pStr, N+1); + if( pStr->nAlloc ){ + memcpy(pStr->z+pStr->n, z, N+1); + pStr->n += N; + } + return rc; +} + +int lsmStringBinAppend(LsmString *pStr, const u8 *a, int n){ + int rc; + rc = lsmStringExtend(pStr, n); + if( pStr->nAlloc ){ + memcpy(pStr->z+pStr->n, a, n); + pStr->n += n; + } + return rc; +} + +/* +** Append printf-formatted content to an LsmString. +*/ +void lsmStringVAppendf( + LsmString *pStr, + const char *zFormat, + va_list ap1, + va_list ap2 +){ +#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__<199901L)) && \ + !defined(__APPLE__) + extern int vsnprintf(char *str, size_t size, const char *format, va_list ap) + /* Compatibility crutch for C89 compilation mode. sqlite3_vsnprintf() + does not work identically and causes test failures if used here. + For the time being we are assuming that the target has vsnprintf(), + but that is not guaranteed to be the case for pure C89 platforms. + */; +#endif + int nWrite; + int nAvail; + + nAvail = pStr->nAlloc - pStr->n; + nWrite = vsnprintf(pStr->z + pStr->n, nAvail, zFormat, ap1); + + if( nWrite>=nAvail ){ + lsmStringExtend(pStr, nWrite+1); + if( pStr->nAlloc==0 ) return; + nWrite = vsnprintf(pStr->z + pStr->n, nWrite+1, zFormat, ap2); + } + + pStr->n += nWrite; + pStr->z[pStr->n] = 0; +} + +void lsmStringAppendf(LsmString *pStr, const char *zFormat, ...){ + va_list ap, ap2; + va_start(ap, zFormat); + va_start(ap2, zFormat); + lsmStringVAppendf(pStr, zFormat, ap, ap2); + va_end(ap); + va_end(ap2); +} + +int lsmStrlen(const char *zName){ + int nRet = 0; + while( zName[nRet] ) nRet++; + return nRet; +} + +/* +** Write into memory obtained from lsm_malloc(). +*/ +char *lsmMallocPrintf(lsm_env *pEnv, const char *zFormat, ...){ + LsmString s; + va_list ap, ap2; + lsmStringInit(&s, pEnv); + va_start(ap, zFormat); + va_start(ap2, zFormat); + lsmStringVAppendf(&s, zFormat, ap, ap2); + va_end(ap); + va_end(ap2); + if( s.n<0 ) return 0; + return (char *)lsmReallocOrFree(pEnv, s.z, s.n+1); +} |