summaryrefslogtreecommitdiffstats
path: root/ext/lsm1/lsm_str.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/lsm1/lsm_str.c')
-rw-r--r--ext/lsm1/lsm_str.c148
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);
+}