diff options
author | drh <> | 2023-07-25 15:08:18 +0000 |
---|---|---|
committer | drh <> | 2023-07-25 15:08:18 +0000 |
commit | f02cc9a3248b07095847f9a5e93e092e4fa6e116 (patch) | |
tree | 44aa63dcc95e939bdd3f2aeed233e1bb347fd811 /src/printf.c | |
parent | b715fe9d80b3656fd0afb82847932e6592306609 (diff) | |
download | sqlite-f02cc9a3248b07095847f9a5e93e092e4fa6e116.tar.gz sqlite-f02cc9a3248b07095847f9a5e93e092e4fa6e116.zip |
Create the new RCStr class of strings and try to use them for JSON storage.
FossilOrigin-Name: c1b8725089bb3d006ec69add28f4fcb3f4e79412c7f438b5b1067c2227e77b9c
Diffstat (limited to 'src/printf.c')
-rw-r--r-- | src/printf.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/printf.c b/src/printf.c index 3fb1a322a..7b8428816 100644 --- a/src/printf.c +++ b/src/printf.c @@ -1366,3 +1366,146 @@ void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){ sqlite3_str_vappendf(p, zFormat, ap); va_end(ap); } + + +/***************************************************************************** +** Reference counted string storage +*****************************************************************************/ + +/* +** Increase the reference count of the string by one. +** +** The input parameter is returned. +*/ +char *sqlite3RCStrRef(char *z){ + RCStr *p = (RCStr*)z; + assert( p!=0 ); + p--; + p->nRCRef++; + return z; +} + +/* +** Decrease the reference count by one. Free the string when the +** reference count reaches zero. +*/ +void sqlite3RCStrUnref(char *z){ + RCStr *p = (RCStr*)z; + assert( p!=0 ); + p--; + assert( p->nRCRef>0 ); + assert( p->uMagic==SQLITE_RCSTR_MAGIC ); + if( p->nRCRef>=2 ){ + p->nRCRef--; + }else{ + if( p->xFree ) p->xFree(p->pAttach); +#ifdef SQLITE_DEBUG + p->uMagic = 0; +#endif + sqlite3_free(p); + } +} + +/* +** Return true if the reference count on the string is exactly one, meaning +** that the string can be modified. Return false if the reference count +** is greater than one. +*/ +int sqlite3RCStrIsWriteable(char *z){ + RCStr *p = (RCStr*)z; + assert( p!=0 ); + p--; + assert( p->nRCRef>0 ); + assert( p->uMagic==SQLITE_RCSTR_MAGIC ); + return p->nRCRef==1; +} + +/* +** Create a new string that is capable of holding N bytes of text, not counting +** the zero byte at the end. The string is uninitialized. +** +** The reference count is initially 1. Call sqlite3RCStrUnref() to free the +** newly allocated string. +** +** This routine returns 0 on an OOM. +*/ +char *sqlite3RCStrNew(u64 N){ + RCStr *p = sqlite3_malloc64( N + sizeof(*p) ); + if( p==0 ) return 0; + p->nRCRef = 1; + p->xFree = 0; + p->pAttach = 0; +#ifdef SQLITE_DEBUG + p->uMagic = SQLITE_RCSTR_MAGIC; +#endif + return (char*)&p[1]; +} + +/* +** Return the number of bytes allocated to the string. The value returned +** does not include the space for the zero-terminator at the end. +*/ +u64 sqlite3RCStrSize(char *z){ + RCStr *p = (RCStr*)z; + u64 N; + assert( p!=0 ); + p--; + assert( p->nRCRef>0 ); + assert( p->uMagic==SQLITE_RCSTR_MAGIC ); + N = sqlite3_msize(p); + N -= sizeof(p) + 1; + return N; +} + +/* +** Change the size of the string so that it is able to hold N bytes. +** The string might be reallocated, so return the new allocation. +*/ +char *sqlite3RCStrResize(char *z, u64 N){ + RCStr *p = (RCStr*)z; + RCStr *pNew; + assert( p!=0 ); + p--; + assert( p->nRCRef==1 ); + assert( p->uMagic==SQLITE_RCSTR_MAGIC ); + pNew = sqlite3_realloc64(p, N+sizeof(RCStr)+1); + if( pNew==0 ){ + sqlite3_free(p); + return 0; + }else{ + return (char*)&pNew[1]; + } +} + +/* +** Add a new attachment to the string. +** +** A string may have no more than one attachment. When a new attachment +** is added, any prior attachment is destroyed. Remove an attachment +** by adding a zero-attachment. +*/ +void sqlite3RCStrAttach(char *z, void *pAttach, void(*xFree)(void*)){ + RCStr *p = (RCStr*)z; + assert( p!=0 ); + p--; + assert( p->nRCRef>0 ); + assert( p->uMagic==SQLITE_RCSTR_MAGIC ); + if( p->xFree ) p->xFree(p->pAttach); + p->xFree = xFree; + p->pAttach = pAttach; +} + +/* +** Return the attachment associated with a string if the attachment +** has the destructure specified in the second argument. If the +** string has no attachment or if the destructor does not match, +** then return a NULL pointr. +*/ +void *sqlite3RCStrGetAttachment(char *z, void(*xFree)(void*)){ + RCStr *p = (RCStr*)z; + assert( p!=0 ); + p--; + assert( p->nRCRef>0 ); + assert( p->uMagic==SQLITE_RCSTR_MAGIC ); + return p->xFree==xFree ? p->pAttach : 0; +} |