038af0bdc6
FossilOrigin-Name: 989a5c1745a7145c14c6d9b713176ecba6b99296de8bdd09f666eeef10da9c2e
149 lines
3.7 KiB
C
149 lines
3.7 KiB
C
/*
|
|
** 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);
|
|
}
|