📄 util.c
字号:
/*** 2001 September 15**** 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.***************************************************************************** Utility functions used throughout sqlite.**** This file contains functions for allocating memory, comparing** strings, and stuff like that.**** $Id: util.c,v 1.136 2005/06/06 15:06:39 drh Exp $*/#include "sqliteInt.h"#include <stdarg.h>#include <ctype.h>#if SQLITE_MEMDEBUG>2 && defined(__GLIBC__)#include <execinfo.h>void print_stack_trace(){ void *bt[30]; int i; int n = backtrace(bt, 30); fprintf(stderr, "STACK: "); for(i=0; i<n;i++){ fprintf(stderr, "%p ", bt[i]); } fprintf(stderr, "\n");}#else#define print_stack_trace()#endif/*** If malloc() ever fails, this global variable gets set to 1.** This causes the library to abort and never again function.*/int sqlite3_malloc_failed = 0;/*** If SQLITE_MEMDEBUG is defined, then use versions of malloc() and** free() that track memory usage and check for buffer overruns.*/#ifdef SQLITE_MEMDEBUG/*** For keeping track of the number of mallocs and frees. This** is used to check for memory leaks. The iMallocFail and iMallocReset** values are used to simulate malloc() failures during testing in ** order to verify that the library correctly handles an out-of-memory** condition.*/int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */int sqlite3_nFree; /* Number of sqliteFree() calls */int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */#if SQLITE_MEMDEBUG>1static int memcnt = 0;#endif/*** Number of 32-bit guard words. This should probably be a multiple of** 2 since on 64-bit machines we want the value returned by sqliteMalloc()** to be 8-byte aligned.*/#define N_GUARD 2/*** Allocate new memory and set it to zero. Return NULL if** no memory is available.*/void *sqlite3Malloc_(int n, int bZero, char *zFile, int line){ void *p; int *pi; int i, k; if( sqlite3_iMallocFail>=0 ){ sqlite3_iMallocFail--; if( sqlite3_iMallocFail==0 ){ sqlite3_malloc_failed++;#if SQLITE_MEMDEBUG>1 fprintf(stderr,"**** failed to allocate %d bytes at %s:%d\n", n, zFile,line);#endif sqlite3_iMallocFail = sqlite3_iMallocReset; return 0; } } if( n==0 ) return 0; k = (n+sizeof(int)-1)/sizeof(int); pi = malloc( (N_GUARD*2+1+k)*sizeof(int)); if( pi==0 ){ if( n>0 ) sqlite3_malloc_failed++; return 0; } sqlite3_nMalloc++; for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122; pi[N_GUARD] = n; for(i=0; i<N_GUARD; i++) pi[k+1+N_GUARD+i] = 0xdead3344; p = &pi[N_GUARD+1]; memset(p, bZero==0, n);#if SQLITE_MEMDEBUG>1 print_stack_trace(); fprintf(stderr,"%06d malloc %d bytes at 0x%x from %s:%d\n", ++memcnt, n, (int)p, zFile,line);#endif return p;}/*** This version of malloc is always a real function, never a macro*/void *sqlite3MallocX(int n){ return sqlite3Malloc_(n, 0, __FILE__, __LINE__);}/*** Check to see if the given pointer was obtained from sqliteMalloc()** and is able to hold at least N bytes. Raise an exception if this** is not the case.**** This routine is used for testing purposes only.*/void sqlite3CheckMemory(void *p, int N){ int *pi = p; int n, i, k; pi -= N_GUARD+1; for(i=0; i<N_GUARD; i++){ assert( pi[i]==0xdead1122 ); } n = pi[N_GUARD]; assert( N>=0 && N<n ); k = (n+sizeof(int)-1)/sizeof(int); for(i=0; i<N_GUARD; i++){ assert( pi[k+N_GUARD+1+i]==0xdead3344 ); }}/*** Free memory previously obtained from sqliteMalloc()*/void sqlite3Free_(void *p, char *zFile, int line){ if( p ){ int *pi, i, k, n; pi = p; pi -= N_GUARD+1; sqlite3_nFree++; for(i=0; i<N_GUARD; i++){ if( pi[i]!=0xdead1122 ){ fprintf(stderr,"Low-end memory corruption at 0x%x\n", (int)p); return; } } n = pi[N_GUARD]; k = (n+sizeof(int)-1)/sizeof(int); for(i=0; i<N_GUARD; i++){ if( pi[k+N_GUARD+1+i]!=0xdead3344 ){ fprintf(stderr,"High-end memory corruption at 0x%x\n", (int)p); return; } } memset(pi, 0xff, (k+N_GUARD*2+1)*sizeof(int));#if SQLITE_MEMDEBUG>1 fprintf(stderr,"%06d free %d bytes at 0x%x from %s:%d\n", ++memcnt, n, (int)p, zFile,line);#endif free(pi); }}/*** Resize a prior allocation. If p==0, then this routine** works just like sqliteMalloc(). If n==0, then this routine** works just like sqliteFree().*/void *sqlite3Realloc_(void *oldP, int n, char *zFile, int line){ int *oldPi, *pi, i, k, oldN, oldK; void *p; if( oldP==0 ){ return sqlite3Malloc_(n,1,zFile,line); } if( n==0 ){ sqlite3Free_(oldP,zFile,line); return 0; } oldPi = oldP; oldPi -= N_GUARD+1; if( oldPi[0]!=0xdead1122 ){ fprintf(stderr,"Low-end memory corruption in realloc at 0x%x\n", (int)oldP); return 0; } oldN = oldPi[N_GUARD]; oldK = (oldN+sizeof(int)-1)/sizeof(int); for(i=0; i<N_GUARD; i++){ if( oldPi[oldK+N_GUARD+1+i]!=0xdead3344 ){ fprintf(stderr,"High-end memory corruption in realloc at 0x%x\n", (int)oldP); return 0; } } k = (n + sizeof(int) - 1)/sizeof(int); pi = malloc( (k+N_GUARD*2+1)*sizeof(int) ); if( pi==0 ){ if( n>0 ) sqlite3_malloc_failed++; return 0; } for(i=0; i<N_GUARD; i++) pi[i] = 0xdead1122; pi[N_GUARD] = n; for(i=0; i<N_GUARD; i++) pi[k+N_GUARD+1+i] = 0xdead3344; p = &pi[N_GUARD+1]; memcpy(p, oldP, n>oldN ? oldN : n); if( n>oldN ){ memset(&((char*)p)[oldN], 0x55, n-oldN); } memset(oldPi, 0xab, (oldK+N_GUARD+2)*sizeof(int)); free(oldPi);#if SQLITE_MEMDEBUG>1 print_stack_trace(); fprintf(stderr,"%06d realloc %d to %d bytes at 0x%x to 0x%x at %s:%d\n", ++memcnt, oldN, n, (int)oldP, (int)p, zFile, line);#endif return p;}/*** Make a copy of a string in memory obtained from sqliteMalloc()*/char *sqlite3StrDup_(const char *z, char *zFile, int line){ char *zNew; if( z==0 ) return 0; zNew = sqlite3Malloc_(strlen(z)+1, 0, zFile, line); if( zNew ) strcpy(zNew, z); return zNew;}char *sqlite3StrNDup_(const char *z, int n, char *zFile, int line){ char *zNew; if( z==0 ) return 0; zNew = sqlite3Malloc_(n+1, 0, zFile, line); if( zNew ){ memcpy(zNew, z, n); zNew[n] = 0; } return zNew;}/*** A version of sqliteFree that is always a function, not a macro.*/void sqlite3FreeX(void *p){ sqliteFree(p);}#endif /* SQLITE_MEMDEBUG *//*** The following versions of malloc() and free() are for use in a** normal build.*/#if !defined(SQLITE_MEMDEBUG)/*** Allocate new memory and set it to zero. Return NULL if** no memory is available. See also sqliteMallocRaw().*/void *sqlite3Malloc(int n){ void *p; if( (p = malloc(n))==0 ){ if( n>0 ) sqlite3_malloc_failed++; }else{ memset(p, 0, n); } return p;}/*** Allocate new memory but do not set it to zero. Return NULL if** no memory is available. See also sqliteMalloc().*/void *sqlite3MallocRaw(int n){ void *p; if( (p = malloc(n))==0 ){ if( n>0 ) sqlite3_malloc_failed++; } return p;}/*** Free memory previously obtained from sqliteMalloc()*/void sqlite3FreeX(void *p){ if( p ){ free(p); }}/*** Resize a prior allocation. If p==0, then this routine** works just like sqliteMalloc(). If n==0, then this routine** works just like sqliteFree().*/void *sqlite3Realloc(void *p, int n){ void *p2; if( p==0 ){ return sqliteMalloc(n); } if( n==0 ){ sqliteFree(p); return 0; } p2 = realloc(p, n); if( p2==0 ){ if( n>0 ) sqlite3_malloc_failed++; } return p2;}/*** Make a copy of a string in memory obtained from sqliteMalloc()*/char *sqlite3StrDup(const char *z){ char *zNew; if( z==0 ) return 0; zNew = sqliteMallocRaw(strlen(z)+1); if( zNew ) strcpy(zNew, z); return zNew;}char *sqlite3StrNDup(const char *z, int n){ char *zNew; if( z==0 ) return 0; zNew = sqliteMallocRaw(n+1); if( zNew ){ memcpy(zNew, z, n); zNew[n] = 0; } return zNew;}#endif /* !defined(SQLITE_MEMDEBUG) *//*** Create a string from the 2nd and subsequent arguments (up to the** first NULL argument), store the string in memory obtained from** sqliteMalloc() and make the pointer indicated by the 1st argument** point to that string. The 1st argument must either be NULL or ** point to memory obtained from sqliteMalloc().*/void sqlite3SetString(char **pz, ...){ va_list ap; int nByte; const char *z; char *zResult; if( pz==0 ) return; nByte = 1; va_start(ap, pz); while( (z = va_arg(ap, const char*))!=0 ){ nByte += strlen(z); } va_end(ap); sqliteFree(*pz); *pz = zResult = sqliteMallocRaw( nByte ); if( zResult==0 ){ return; } *zResult = 0; va_start(ap, pz); while( (z = va_arg(ap, const char*))!=0 ){ strcpy(zResult, z); zResult += strlen(zResult); } va_end(ap);#ifdef SQLITE_DEBUG#if SQLITE_DEBUG>1 fprintf(stderr,"string at 0x%x is %s\n", (int)*pz, *pz);#endif#endif}/*** Set the most recent error code and error string for the sqlite** handle "db". The error code is set to "err_code".**** If it is not NULL, string zFormat specifies the format of the** error string in the style of the printf functions: The following** format characters are allowed:**** %s Insert a string** %z A string that should be freed after use** %d Insert an integer** %T Insert a token** %S Insert the first element of a SrcList**** zFormat and any string tokens that follow it are assumed to be** encoded in UTF-8.**** To clear the most recent error for sqlite handle "db", sqlite3Error** should be called with err_code set to SQLITE_OK and zFormat set** to NULL.*/void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){ if( db && (db->pErr || (db->pErr = sqlite3ValueNew())) ){ db->errCode = err_code; if( zFormat ){ char *z; va_list ap; va_start(ap, zFormat); z = sqlite3VMPrintf(zFormat, ap); va_end(ap); sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, sqlite3FreeX); }else{ sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC); } }}/*** Add an error message to pParse->zErrMsg and increment pParse->nErr.** The following formatting characters are allowed:**** %s Insert a string** %z A string that should be freed after use** %d Insert an integer** %T Insert a token** %S Insert the first element of a SrcList**** This function should be used to report any error that occurs whilst** compiling an SQL statement (i.e. within sqlite3_prepare()). The** last thing the sqlite3_prepare() function does is copy the error** stored by this function into the database handle using sqlite3Error().** Function sqlite3Error() should be used during statement execution** (sqlite3_step() etc.).*/void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ va_list ap; pParse->nErr++; sqliteFree(pParse->zErrMsg); va_start(ap, zFormat); pParse->zErrMsg = sqlite3VMPrintf(zFormat, ap); va_end(ap);}/*** Convert an SQL-style quoted string into a normal string by removing** the quote characters. The conversion is done in-place. If the** input does not begin with a quote character, then this routine** is a no-op.**** 2002-Feb-14: This routine is extended to remove MS-Access style** brackets from around identifers. For example: "[a-b-c]" becomes** "a-b-c".*/void sqlite3Dequote(char *z){ int quote; int i, j; if( z==0 ) return; quote = z[0]; switch( quote ){ case '\'': break; case '"': break; case '[': quote = ']'; break; default: return; } for(i=1, j=0; z[i]; i++){ if( z[i]==quote ){ if( z[i+1]==quote ){ z[j++] = quote; i++; }else{ z[j++] = 0; break; } }else{ z[j++] = z[i]; } }}/* An array to map all upper-case characters into their corresponding** lower-case character. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -