/*** The "printf" code that follows dates from the 1980's. It is in** the public domain.******************************************************************************** This file contains code for a set of "printf"-like routines. These** routines format strings much like the printf() from the standard C** library, though the implementation here has enhancements to support** SQLite.*/#include "sqliteInt.h"/*** Conversion types fall into various categories as defined by the** following enumeration.*/#define etRADIX 0 /* non-decimal integer types. %x %o */#define etFLOAT 1 /* Floating point. %f */#define etEXP 2 /* Exponentional notation. %e and %E */#define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */#define etSIZE 4 /* Return number of characters processed so far. %n */#define etSTRING 5 /* Strings. %s */#define etDYNSTRING 6 /* Dynamically allocated strings. %z */#define etPERCENT 7 /* Percent symbol. %% */#define etCHARX 8 /* Characters. %c *//* The rest are extensions, not normally found in printf() */#define etESCAPE_q 9 /* Strings with '\'' doubled. %q */#define etESCAPE_Q 10 /* Strings with '\'' doubled and enclosed in '',NULL pointers replaced by SQL NULL. %Q */#define etTOKEN 11 /* a pointer to a Token structure */#define etSRCITEM 12 /* a pointer to a SrcItem */#define etPOINTER 13 /* The %p conversion */#define etESCAPE_w 14 /* %w -> Strings with '\"' doubled */#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */#define etDECIMAL 16 /* %d or %u, but not %x, %o */#define etINVALID 17 /* Any unrecognized conversion type *//*** An "etByte" is an 8-bit unsigned value.*/typedef unsigned char etByte;/*** Each builtin conversion character (ex: the 'd' in "%d") is described** by an instance of the following structure*/typedef struct et_info { /* Information about each format field */char fmttype; /* The format field code letter */etByte base; /* The base for radix conversion */etByte flags; /* One or more of FLAG_ constants below */etByte type; /* Conversion paradigm */etByte charset; /* Offset into aDigits[] of the digits string */etByte prefix; /* Offset into aPrefix[] of the prefix string */char iNxt; /* Next with same hash, or 0 for end of chain */} et_info;/*** Allowed values for et_info.flags*/#define FLAG_SIGNED 1 /* True if the value to convert is signed */#define FLAG_STRING 4 /* Allow infinite precision *//*** The table is searched by hash. In the case of %C where C is the character** and that character has ASCII value j, then the hash is j%23.**** The order of the entries in fmtinfo[] and the hash chain was entered** manually, but based on the output of the following TCL script:*/#if 0 /***** Beginning of script ******/foreach c {d s g z q Q w c o u x X f e E G i n % p T S r} {scan $c %c xset n($c) $x}set mx [llength [array names n]]puts "count: $mx"set mx 27puts "*********** mx=$mx ************"for {set r 0} {$r<$mx} {incr r} {puts -nonewline [format %2d: $r]foreach c [array names n] {if {($n($c))%$mx==$r} {puts -nonewline " $c"}}puts ""}#endif /***** End of script ********/static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";static const char aPrefix[] = "-x0000円X0";static const et_info fmtinfo[23] = {/* 0 */ { 's', 0, 4, etSTRING, 0, 0, 1 },/* 1 */ { 'E', 0, 1, etEXP, 14, 0, 0 }, /* Hash: 0 *//* 2 */ { 'u', 10, 0, etDECIMAL, 0, 0, 3 },/* 3 */ { 'G', 0, 1, etGENERIC, 14, 0, 0 }, /* Hash: 2 *//* 4 */ { 'w', 0, 4, etESCAPE_w, 0, 0, 0 },/* 5 */ { 'x', 16, 0, etRADIX, 16, 1, 0 },/* 6 */ { 'c', 0, 0, etCHARX, 0, 0, 0 }, /* Hash: 7 *//* 7 */ { 'z', 0, 4, etDYNSTRING, 0, 0, 6 },/* 8 */ { 'd', 10, 1, etDECIMAL, 0, 0, 0 },/* 9 */ { 'e', 0, 1, etEXP, 30, 0, 0 },/* 10 */ { 'f', 0, 1, etFLOAT, 0, 0, 0 },/* 11 */ { 'g', 0, 1, etGENERIC, 30, 0, 0 },/* 12 */ { 'Q', 0, 4, etESCAPE_Q, 0, 0, 0 },/* 13 */ { 'i', 10, 1, etDECIMAL, 0, 0, 0 },/* 14 */ { '%', 0, 0, etPERCENT, 0, 0, 16 },/* 15 */ { 'T', 0, 0, etTOKEN, 0, 0, 0 },/* 16 */ { 'S', 0, 0, etSRCITEM, 0, 0, 0 }, /* Hash: 14 *//* 17 */ { 'X', 16, 0, etRADIX, 0, 4, 0 }, /* Hash: 19 *//* 18 */ { 'n', 0, 0, etSIZE, 0, 0, 0 },/* 19 */ { 'o', 8, 0, etRADIX, 0, 2, 17 },/* 20 */ { 'p', 16, 0, etPOINTER, 0, 1, 0 },/* 21 */ { 'q', 0, 4, etESCAPE_q, 0, 0, 0 },/* 22 */ { 'r', 10, 1, etORDINAL, 0, 0, 0 }};/* Additional Notes:**** %S Takes a pointer to SrcItem. Shows name or database.name** %!S Like %S but prefer the zName over the zAlias*//*** Set the StrAccum object to an error mode.*/void sqlite3StrAccumSetError(StrAccum *p, u8 eError){assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );p->accError = eError;if( p->mxAlloc ) sqlite3_str_reset(p);if( eError==SQLITE_TOOBIG ) sqlite3ErrorToParser(p->db, eError);}/*** Extra argument values from a PrintfArguments object*/static sqlite3_int64 getIntArg(PrintfArguments *p){if( p->nArg<=p->nUsed ) return 0;return sqlite3_value_int64(p->apArg[p->nUsed++]);}static double getDoubleArg(PrintfArguments *p){if( p->nArg<=p->nUsed ) return 0.0;return sqlite3_value_double(p->apArg[p->nUsed++]);}static char *getTextArg(PrintfArguments *p){if( p->nArg<=p->nUsed ) return 0;return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);}/*** Allocate memory for a temporary buffer needed for printf rendering.**** If the requested size of the temp buffer is larger than the size** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error.** Do the size check before the memory allocation to prevent rogue** SQL from requesting large allocations using the precision or width** field of the printf() function.*/static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){char *z;if( pAccum->accError ) return 0;if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG);return 0;}z = sqlite3DbMallocRaw(pAccum->db, n);if( z==0 ){sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);}return z;}/*** On machines with a small stack size, you can redefine the** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.*/#ifndef SQLITE_PRINT_BUF_SIZE# define SQLITE_PRINT_BUF_SIZE 70#endif#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer *//*** Hard limit on the precision of floating-point conversions.*/#ifndef SQLITE_PRINTF_PRECISION_LIMIT# define SQLITE_FP_PRECISION_LIMIT 100000000#endif/*** Render a string given by "fmt" into the StrAccum object.*/void sqlite3_str_vappendf(sqlite3_str *pAccum, /* Accumulate results here */const char *fmt, /* Format string */va_list ap /* arguments */){int c; /* Next character in the format string */char *bufpt; /* Pointer to the conversion buffer */int precision; /* Precision of the current field */int length; /* Length of the field */int idx; /* A general purpose loop counter */int width; /* Width of the current field */etByte flag_leftjustify; /* True if "-" flag is present */etByte flag_prefix; /* '+' or ' ' or 0 for prefix */etByte flag_alternateform; /* True if "#" flag is present */etByte flag_altform2; /* True if "!" flag is present */etByte flag_zeropad; /* True if field width constant starts with zero */etByte flag_long; /* 1 for the "l" flag, 2 for "ll", 0 by default */etByte done; /* Loop termination flag */etByte cThousand; /* Thousands separator for %d and %u */etByte xtype = etINVALID; /* Conversion paradigm */u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */char prefix; /* Prefix character. "+" or "-" or " " or '0円'. */sqlite_uint64 longvalue; /* Value for integer types */double realvalue; /* Value for real types */const et_info *infop; /* Pointer to the appropriate info structure */char *zOut; /* Rendering buffer */int nOut; /* Size of the rendering buffer */char *zExtra = 0; /* Malloced memory used by some conversion */int exp, e2; /* exponent of real numbers */etByte flag_dp; /* True if decimal point should be shown */etByte flag_rtz; /* True if trailing zeros should be removed */PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */char buf[etBUFSIZE]; /* Conversion buffer *//* pAccum never starts out with an empty buffer that was obtained from** malloc(). This precondition is required by the mprintf("%z...")** optimization. */assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );bufpt = 0;if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){pArgList = va_arg(ap, PrintfArguments*);bArgList = 1;}else{bArgList = 0;}for(; (c=(*fmt))!=0; ++fmt){if( c!='%' ){bufpt = (char *)fmt;#if HAVE_STRCHRNULfmt = strchrnul(fmt, '%');#elsefmt = strchr(fmt, '%');if( fmt==0 ){fmt = bufpt + strlen(bufpt);}#endifsqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt));if( *fmt==0 ) break;}if( (c=(*++fmt))==0 ){sqlite3_str_append(pAccum, "%", 1);break;}/* Find out what flags are present */flag_leftjustify = flag_prefix = cThousand =flag_alternateform = flag_altform2 = flag_zeropad = 0;done = 0;width = 0;flag_long = 0;precision = -1;do{switch( c ){case '-': flag_leftjustify = 1; break;case '+': flag_prefix = '+'; break;case ' ': flag_prefix = ' '; break;case '#': flag_alternateform = 1; break;case '!': flag_altform2 = 1; break;case '0': flag_zeropad = 1; break;case ',': cThousand = ','; break;default: done = 1; break;case 'l': {flag_long = 1;c = *++fmt;if( c=='l' ){c = *++fmt;flag_long = 2;}done = 1;break;}case '1': case '2': case '3': case '4': case '5':case '6': case '7': case '8': case '9': {unsigned wx = c - '0';while( (c = *++fmt)>='0' && c<='9' ){wx = wx*10 + c - '0';}testcase( wx>0x7fffffff );width = wx & 0x7fffffff;#ifdef SQLITE_PRINTF_PRECISION_LIMITif( width>SQLITE_PRINTF_PRECISION_LIMIT ){width = SQLITE_PRINTF_PRECISION_LIMIT;}#endifif( c!='.' && c!='l' ){done = 1;}else{fmt--;}break;}case '*': {if( bArgList ){width = (int)getIntArg(pArgList);}else{width = va_arg(ap,int);}if( width<0 ){flag_leftjustify = 1;width = width >= -2147483647 ? -width : 0;}#ifdef SQLITE_PRINTF_PRECISION_LIMITif( width>SQLITE_PRINTF_PRECISION_LIMIT ){width = SQLITE_PRINTF_PRECISION_LIMIT;}#endifif( (c = fmt[1])!='.' && c!='l' ){c = *++fmt;done = 1;}break;}case '.': {c = *++fmt;if( c=='*' ){if( bArgList ){precision = (int)getIntArg(pArgList);}else{precision = va_arg(ap,int);}if( precision<0 ){precision = precision >= -2147483647 ? -precision : -1;}c = *++fmt;}else{unsigned px = 0;while( c>='0' && c<='9' ){px = px*10 + c - '0';c = *++fmt;}testcase( px>0x7fffffff );precision = px & 0x7fffffff;}#ifdef SQLITE_PRINTF_PRECISION_LIMITif( precision>SQLITE_PRINTF_PRECISION_LIMIT ){precision = SQLITE_PRINTF_PRECISION_LIMIT;}#endifif( c=='l' ){--fmt;}else{done = 1;}break;}}}while( !done && (c=(*++fmt))!=0 );/* Fetch the info entry for the field */#ifdef SQLITE_EBCDIC/* The hash table only works for ASCII. For EBCDIC, we need to do** a linear search of the table */infop = &fmtinfo[0];xtype = etINVALID;for(idx=0; idx<ArraySize(fmtinfo); idx++){if( c==fmtinfo[idx].fmttype ){infop = &fmtinfo[idx];xtype = infop->type;break;}}#else/* Fast hash-table lookup */assert( ArraySize(fmtinfo)==23 );idx = ((unsigned)c) % 23;if( fmtinfo[idx].fmttype==c|| fmtinfo[idx = fmtinfo[idx].iNxt].fmttype==c){infop = &fmtinfo[idx];xtype = infop->type;}else{infop = &fmtinfo[0];xtype = etINVALID;}#endif/*** At this point, variables are initialized as follows:**** flag_alternateform TRUE if a '#' is present.** flag_altform2 TRUE if a '!' is present.** flag_prefix '+' or ' ' or zero** flag_leftjustify TRUE if a '-' is present or if the** field width was negative.** flag_zeropad TRUE if the width began with 0.** flag_long 1 for "l", 2 for "ll"** width The specified field width. This is** always non-negative. Zero is the default.** precision The specified precision. The default** is -1.** xtype The class of the conversion.** infop Pointer to the appropriate info struct.*/assert( width>=0 );assert( precision>=(-1) );switch( xtype ){case etPOINTER:flag_long = sizeof(char*)==sizeof(i64) ? 2 :sizeof(char*)==sizeof(long int) ? 1 : 0;/* no break */ deliberate_fall_throughcase etORDINAL:case etRADIX:cThousand = 0;/* no break */ deliberate_fall_throughcase etDECIMAL:if( infop->flags & FLAG_SIGNED ){i64 v;if( bArgList ){v = getIntArg(pArgList);}else if( flag_long ){if( flag_long==2 ){v = va_arg(ap,i64) ;}else{v = va_arg(ap,long int);}}else{v = va_arg(ap,int);}if( v<0 ){testcase( v==SMALLEST_INT64 );testcase( v==(-1) );longvalue = ~v;longvalue++;prefix = '-';}else{longvalue = v;prefix = flag_prefix;}}else{if( bArgList ){longvalue = (u64)getIntArg(pArgList);}else if( flag_long ){if( flag_long==2 ){longvalue = va_arg(ap,u64);}else{longvalue = va_arg(ap,unsigned long int);}}else{longvalue = va_arg(ap,unsigned int);}prefix = 0;}#if WHERETRACE_ENABLEDif( xtype==etPOINTER && sqlite3WhereTrace & 0x100000 ) longvalue = 0;#endif#if TREETRACE_ENABLEDif( xtype==etPOINTER && sqlite3TreeTrace & 0x100000 ) longvalue = 0;#endifif( longvalue==0 ) flag_alternateform = 0;if( flag_zeropad && precision<width-(prefix!=0) ){precision = width-(prefix!=0);}if( precision<etBUFSIZE-10-etBUFSIZE/3 ){nOut = etBUFSIZE;zOut = buf;}else{u64 n;n = (u64)precision + 10;if( cThousand ) n += precision/3;zOut = zExtra = printfTempBuf(pAccum, n);if( zOut==0 ) return;nOut = (int)n;}bufpt = &zOut[nOut-1];if( xtype==etORDINAL ){static const char zOrd[] = "thstndrd";int x = (int)(longvalue % 10);if( x>=4 || (longvalue/10)%10==1 ){x = 0;}*(--bufpt) = zOrd[x*2+1];*(--bufpt) = zOrd[x*2];}{const char *cset = &aDigits[infop->charset];u8 base = infop->base;do{ /* Convert to ascii */*(--bufpt) = cset[longvalue%base];longvalue = longvalue/base;}while( longvalue>0 );}length = (int)(&zOut[nOut-1]-bufpt);while( precision>length ){*(--bufpt) = '0'; /* Zero pad */length++;}if( cThousand ){int nn = (length - 1)/3; /* Number of "," to insert */int ix = (length - 1)%3 + 1;bufpt -= nn;for(idx=0; nn>0; idx++){bufpt[idx] = bufpt[idx+nn];ix--;if( ix==0 ){bufpt[++idx] = cThousand;nn--;ix = 3;}}}if( prefix ) *(--bufpt) = prefix; /* Add sign */if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */const char *pre;char x;pre = &aPrefix[infop->prefix];for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;}length = (int)(&zOut[nOut-1]-bufpt);break;case etFLOAT:case etEXP:case etGENERIC: {FpDecode s;int iRound;int j;if( bArgList ){realvalue = getDoubleArg(pArgList);}else{realvalue = va_arg(ap,double);}if( precision<0 ) precision = 6; /* Set default precision */#ifdef SQLITE_FP_PRECISION_LIMITif( precision>SQLITE_FP_PRECISION_LIMIT ){precision = SQLITE_FP_PRECISION_LIMIT;}#endifif( xtype==etFLOAT ){iRound = -precision;}else if( xtype==etGENERIC ){if( precision==0 ) precision = 1;iRound = precision;}else{iRound = precision+1;}sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16);if( s.isSpecial ){if( s.isSpecial==2 ){bufpt = flag_zeropad ? "null" : "NaN";length = sqlite3Strlen30(bufpt);break;}else if( flag_zeropad ){s.z[0] = '9';s.iDP = 1000;s.n = 1;}else{memcpy(buf, "-Inf", 5);bufpt = buf;if( s.sign=='-' ){/* no-op */}else if( flag_prefix ){buf[0] = flag_prefix;}else{bufpt++;}length = sqlite3Strlen30(bufpt);break;}}if( s.sign=='-' ){if( flag_alternateform&& !flag_prefix&& xtype==etFLOAT&& s.iDP<=iRound){/* Suppress the minus sign if all of the following are true:** * The value displayed is zero** * The '#' flag is used** * The '+' flag is not used, and** * The format is %f*/prefix = 0;}else{prefix = '-';}}else{prefix = flag_prefix;}exp = s.iDP-1;/*** If the field type is etGENERIC, then convert to either etEXP** or etFLOAT, as appropriate.*/if( xtype==etGENERIC ){assert( precision>0 );precision--;flag_rtz = !flag_alternateform;if( exp<-4 || exp>precision ){xtype = etEXP;}else{precision = precision - exp;xtype = etFLOAT;}}else{flag_rtz = flag_altform2;}if( xtype==etEXP ){e2 = 0;}else{e2 = s.iDP - 1;}bufpt = buf;{i64 szBufNeeded; /* Size of a temporary buffer needed */szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15;if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3;if( szBufNeeded > etBUFSIZE ){bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded);if( bufpt==0 ) return;}}zOut = bufpt;flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;/* The sign in front of the number */if( prefix ){*(bufpt++) = prefix;}/* Digits prior to the decimal point */j = 0;if( e2<0 ){*(bufpt++) = '0';}else{for(; e2>=0; e2--){*(bufpt++) = j<s.n ? s.z[j++] : '0';if( cThousand && (e2%3)==0 && e2>1 ) *(bufpt++) = ',';}}/* The decimal point */if( flag_dp ){*(bufpt++) = '.';}/* "0" digits after the decimal point but before the first** significant digit of the number */for(e2++; e2<0 && precision>0; precision--, e2++){*(bufpt++) = '0';}/* Significant digits after the decimal point */while( (precision--)>0 ){*(bufpt++) = j<s.n ? s.z[j++] : '0';}/* Remove trailing zeros and the "." if no digits follow the "." */if( flag_rtz && flag_dp ){while( bufpt[-1]=='0' ) *(--bufpt) = 0;assert( bufpt>zOut );if( bufpt[-1]=='.' ){if( flag_altform2 ){*(bufpt++) = '0';}else{*(--bufpt) = 0;}}}/* Add the "eNNN" suffix */if( xtype==etEXP ){exp = s.iDP - 1;*(bufpt++) = aDigits[infop->charset];if( exp<0 ){*(bufpt++) = '-'; exp = -exp;}else{*(bufpt++) = '+';}if( exp>=100 ){*(bufpt++) = (char)((exp/100)+'0'); /* 100's digit */exp %= 100;}*(bufpt++) = (char)(exp/10+'0'); /* 10's digit */*(bufpt++) = (char)(exp%10+'0'); /* 1's digit */}*bufpt = 0;/* The converted number is in buf[] and zero terminated. Output it.** Note that the number is in the usual order, not reversed as with** integer conversions. */length = (int)(bufpt-zOut);bufpt = zOut;/* Special case: Add leading zeros if the flag_zeropad flag is** set and we are not left justified */if( flag_zeropad && !flag_leftjustify && length < width){int i;int nPad = width - length;for(i=width; i>=nPad; i--){bufpt[i] = bufpt[i-nPad];}i = prefix!=0;while( nPad-- ) bufpt[i++] = '0';length = width;}break;}case etSIZE:if( !bArgList ){*(va_arg(ap,int*)) = pAccum->nChar;}length = width = 0;break;case etPERCENT:buf[0] = '%';bufpt = buf;length = 1;break;case etCHARX:if( bArgList ){bufpt = getTextArg(pArgList);length = 1;if( bufpt ){buf[0] = c = *(bufpt++);if( (c&0xc0)==0xc0 ){while( length<4 && (bufpt[0]&0xc0)==0x80 ){buf[length++] = *(bufpt++);}}}else{buf[0] = 0;}}else{unsigned int ch = va_arg(ap,unsigned int);length = sqlite3AppendOneUtf8Character(buf, ch);}if( precision>1 ){i64 nPrior = 1;width -= precision-1;if( width>1 && !flag_leftjustify ){sqlite3_str_appendchar(pAccum, width-1, ' ');width = 0;}sqlite3_str_append(pAccum, buf, length);precision--;while( precision > 1 ){i64 nCopyBytes;if( nPrior > precision-1 ) nPrior = precision - 1;nCopyBytes = length*nPrior;if( nCopyBytes + pAccum->nChar >= pAccum->nAlloc ){sqlite3StrAccumEnlarge(pAccum, nCopyBytes);}if( pAccum->accError ) break;sqlite3_str_append(pAccum,&pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes);precision -= nPrior;nPrior *= 2;}}bufpt = buf;flag_altform2 = 1;goto adjust_width_for_utf8;case etSTRING:case etDYNSTRING:if( bArgList ){bufpt = getTextArg(pArgList);xtype = etSTRING;}else{bufpt = va_arg(ap,char*);}if( bufpt==0 ){bufpt = "";}else if( xtype==etDYNSTRING ){if( pAccum->nChar==0&& pAccum->mxAlloc&& width==0&& precision<0&& pAccum->accError==0){/* Special optimization for sqlite3_mprintf("%z..."):** Extend an existing memory allocation rather than creating** a new one. */assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );pAccum->zText = bufpt;pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt);pAccum->nChar = 0x7fffffff & (int)strlen(bufpt);pAccum->printfFlags |= SQLITE_PRINTF_MALLOCED;length = 0;break;}zExtra = bufpt;}if( precision>=0 ){if( flag_altform2 ){/* Set length to the number of bytes needed in order to display** precision characters */unsigned char *z = (unsigned char*)bufpt;while( precision-- > 0 && z[0] ){SQLITE_SKIP_UTF8(z);}length = (int)(z - (unsigned char*)bufpt);}else{for(length=0; length<precision && bufpt[length]; length++){}}}else{length = 0x7fffffff & (int)strlen(bufpt);}adjust_width_for_utf8:if( flag_altform2 && width>0 ){/* Adjust width to account for extra bytes in UTF-8 characters */int ii = length - 1;while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;}break;case etESCAPE_q: /* %q: Escape ' characters */case etESCAPE_Q: /* %Q: Escape ' and enclose in '...' */case etESCAPE_w: { /* %w: Escape " characters */i64 i, j, k, n;int needQuote = 0;char ch;char *escarg;char q;if( bArgList ){escarg = getTextArg(pArgList);}else{escarg = va_arg(ap,char*);}if( escarg==0 ){escarg = (xtype==etESCAPE_Q ? "NULL" : "(NULL)");}else if( xtype==etESCAPE_Q ){needQuote = 1;}if( xtype==etESCAPE_w ){q = '"';flag_alternateform = 0;}else{q = '\'';}/* For %q, %Q, and %w, the precision is the number of bytes (or** characters if the ! flags is present) to use from the input.** Because of the extra quoting characters inserted, the number** of output characters may be larger than the precision.*/k = precision;for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){if( ch==q ) n++;if( flag_altform2 && (ch&0xc0)==0xc0 ){while( (escarg[i+1]&0xc0)==0x80 ){ i++; }}}if( flag_alternateform ){/* For %#q, do unistr()-style backslash escapes for** all control characters, and for backslash itself.** For %#Q, do the same but only if there is at least** one control character. */u32 nBack = 0;u32 nCtrl = 0;for(k=0; k<i; k++){if( escarg[k]=='\\' ){nBack++;}else if( ((u8*)escarg)[k]<=0x1f ){nCtrl++;}}if( nCtrl || xtype==etESCAPE_q ){n += nBack + 5*nCtrl;if( xtype==etESCAPE_Q ){n += 10;needQuote = 2;}}else{flag_alternateform = 0;}}n += i + 3;if( n>etBUFSIZE ){bufpt = zExtra = printfTempBuf(pAccum, n);if( bufpt==0 ) return;}else{bufpt = buf;}j = 0;if( needQuote ){if( needQuote==2 ){memcpy(&bufpt[j], "unistr('", 8);j += 8;}else{bufpt[j++] = '\'';}}k = i;if( flag_alternateform ){for(i=0; i<k; i++){bufpt[j++] = ch = escarg[i];if( ch==q ){bufpt[j++] = ch;}else if( ch=='\\' ){bufpt[j++] = '\\';}else if( ((unsigned char)ch)<=0x1f ){bufpt[j-1] = '\\';bufpt[j++] = 'u';bufpt[j++] = '0';bufpt[j++] = '0';bufpt[j++] = ch>=0x10 ? '1' : '0';bufpt[j++] = "0123456789abcdef"[ch&0xf];}}}else{for(i=0; i<k; i++){bufpt[j++] = ch = escarg[i];if( ch==q ) bufpt[j++] = ch;}}if( needQuote ){bufpt[j++] = '\'';if( needQuote==2 ) bufpt[j++] = ')';}bufpt[j] = 0;length = j;goto adjust_width_for_utf8;}case etTOKEN: {if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;if( flag_alternateform ){/* %#T means an Expr pointer that uses Expr.u.zToken */Expr *pExpr = va_arg(ap,Expr*);if( ALWAYS(pExpr) && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken);sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr);}}else{/* %T means a Token pointer */Token *pToken = va_arg(ap, Token*);assert( bArgList==0 );if( pToken && pToken->n ){sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);sqlite3RecordErrorByteOffset(pAccum->db, pToken->z);}}length = width = 0;break;}case etSRCITEM: {SrcItem *pItem;if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;pItem = va_arg(ap, SrcItem*);assert( bArgList==0 );if( pItem->zAlias && !flag_altform2 ){sqlite3_str_appendall(pAccum, pItem->zAlias);}else if( pItem->zName ){if( pItem->fg.fixedSchema==0&& pItem->fg.isSubquery==0&& pItem->u4.zDatabase!=0){sqlite3_str_appendall(pAccum, pItem->u4.zDatabase);sqlite3_str_append(pAccum, ".", 1);}sqlite3_str_appendall(pAccum, pItem->zName);}else if( pItem->zAlias ){sqlite3_str_appendall(pAccum, pItem->zAlias);}else if( ALWAYS(pItem->fg.isSubquery) ){/* Because of tag-20240424-1 */Select *pSel = pItem->u4.pSubq->pSelect;assert( pSel!=0 );if( pSel->selFlags & SF_NestedFrom ){sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);}else if( pSel->selFlags & SF_MultiValue ){assert( !pItem->fg.isTabFunc && !pItem->fg.isIndexedBy );sqlite3_str_appendf(pAccum, "%u-ROW VALUES CLAUSE",pItem->u1.nRow);}else{sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);}}length = width = 0;break;}default: {assert( xtype==etINVALID );return;}}/* End switch over the format type *//*** The text of the conversion is pointed to by "bufpt" and is** "length" characters long. The field width is "width". Do** the output. Both length and width are in bytes, not characters,** at this point. If the "!" flag was present on string conversions** indicating that width and precision should be expressed in characters,** then the values have been translated prior to reaching this point.*/width -= length;if( width>0 ){if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');sqlite3_str_append(pAccum, bufpt, length);if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');}else{sqlite3_str_append(pAccum, bufpt, length);}if( zExtra ){sqlite3DbFree(pAccum->db, zExtra);zExtra = 0;}}/* End for loop over the format string */} /* End of function *//*** The z string points to the first character of a token that is** associated with an error. If db does not already have an error** byte offset recorded, try to compute the error byte offset for** z and set the error byte offset in db.*/void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){const Parse *pParse;const char *zText;const char *zEnd;assert( z!=0 );if( NEVER(db==0) ) return;if( db->errByteOffset!=(-2) ) return;pParse = db->pParse;if( NEVER(pParse==0) ) return;zText =pParse->zTail;if( NEVER(zText==0) ) return;zEnd = &zText[strlen(zText)];if( SQLITE_WITHIN(z,zText,zEnd) ){db->errByteOffset = (int)(z-zText);}}/*** If pExpr has a byte offset for the start of a token, record that as** as the error offset.*/void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){while( pExpr&& (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)){pExpr = pExpr->pLeft;}if( pExpr==0 ) return;if( ExprHasProperty(pExpr, EP_FromDDL) ) return;db->errByteOffset = pExpr->w.iOfst;}/*** Enlarge the memory allocation on a StrAccum object so that it is** able to accept at least N more bytes of text.**** Return the number of bytes of text that StrAccum is able to accept** after the attempted enlargement. The value returned might be zero.*/int sqlite3StrAccumEnlarge(StrAccum *p, i64 N){char *zNew;assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */if( p->accError ){testcase(p->accError==SQLITE_TOOBIG);testcase(p->accError==SQLITE_NOMEM);return 0;}if( p->mxAlloc==0 ){sqlite3StrAccumSetError(p, SQLITE_TOOBIG);return p->nAlloc - p->nChar - 1;}else{char *zOld = isMalloced(p) ? p->zText : 0;i64 szNew = p->nChar + N + 1;if( szNew+p->nChar<=p->mxAlloc ){/* Force exponential buffer size growth as long as it does not overflow,** to avoid having to call this routine too often */szNew += p->nChar;}if( szNew > p->mxAlloc ){sqlite3_str_reset(p);sqlite3StrAccumSetError(p, SQLITE_TOOBIG);return 0;}else{p->nAlloc = (int)szNew;}if( p->db ){zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);}else{zNew = sqlite3Realloc(zOld, p->nAlloc);}if( zNew ){assert( p->zText!=0 || p->nChar==0 );if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);p->zText = zNew;p->nAlloc = sqlite3DbMallocSize(p->db, zNew);p->printfFlags |= SQLITE_PRINTF_MALLOCED;}else{sqlite3_str_reset(p);sqlite3StrAccumSetError(p, SQLITE_NOMEM);return 0;}}assert( N>=0 && N<=0x7fffffff );return (int)N;}/*** Append N copies of character c to the given string buffer.*/void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){testcase( p->nChar + (i64)N > 0x7fffffff );if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){return;}while( (N--)>0 ) p->zText[p->nChar++] = c;}/*** The StrAccum "p" is not large enough to accept N new bytes of z[].** So enlarge if first, then do the append.**** This is a helper routine to sqlite3_str_append() that does special-case** work (enlarging the buffer) using tail recursion, so that the** sqlite3_str_append() routine can use fast calling semantics.*/static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){N = sqlite3StrAccumEnlarge(p, N);if( N>0 ){memcpy(&p->zText[p->nChar], z, N);p->nChar += N;}}/*** Append N bytes of text from z to the StrAccum object. Increase the** size of the memory allocation for StrAccum if necessary.*/void sqlite3_str_append(sqlite3_str *p, const char *z, int N){assert( z!=0 || N==0 );assert( p->zText!=0 || p->nChar==0 || p->accError );assert( N>=0 );assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 );if( p->nChar+N >= p->nAlloc ){enlargeAndAppend(p,z,N);}else if( N ){assert( p->zText );p->nChar += N;memcpy(&p->zText[p->nChar-N], z, N);}}/*** Append the complete text of zero-terminated string z[] to the p string.*/void sqlite3_str_appendall(sqlite3_str *p, const char *z){sqlite3_str_append(p, z, sqlite3Strlen30(z));}/*** Finish off a string by making sure it is zero-terminated.** Return a pointer to the resulting string. Return a NULL** pointer if any kind of error was encountered.*/static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){char *zText;assert( p->mxAlloc>0 && !isMalloced(p) );zText = sqlite3DbMallocRaw(p->db, 1+(u64)p->nChar );if( zText ){memcpy(zText, p->zText, p->nChar+1);p->printfFlags |= SQLITE_PRINTF_MALLOCED;}else{sqlite3StrAccumSetError(p, SQLITE_NOMEM);}p->zText = zText;return zText;}char *sqlite3StrAccumFinish(StrAccum *p){if( p->zText ){p->zText[p->nChar] = 0;if( p->mxAlloc>0 && !isMalloced(p) ){return strAccumFinishRealloc(p);}}return p->zText;}/*** Use the content of the StrAccum passed as the second argument** as the result of an SQL function.*/void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){if( p->accError ){sqlite3_result_error_code(pCtx, p->accError);sqlite3_str_reset(p);}else if( isMalloced(p) ){sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC);}else{sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);sqlite3_str_reset(p);}}/*** This singleton is an sqlite3_str object that is returned if** sqlite3_malloc() fails to provide space for a real one. This** sqlite3_str object accepts no new text and always returns** an SQLITE_NOMEM error.*/static sqlite3_str sqlite3OomStr = {0, 0, 0, 0, 0, SQLITE_NOMEM, 0};/* Finalize a string created using sqlite3_str_new().*/char *sqlite3_str_finish(sqlite3_str *p){char *z;if( p!=0 && p!=&sqlite3OomStr ){z = sqlite3StrAccumFinish(p);sqlite3_free(p);}else{z = 0;}return z;}/* Return any error code associated with p */int sqlite3_str_errcode(sqlite3_str *p){return p ? p->accError : SQLITE_NOMEM;}/* Return the current length of p in bytes */int sqlite3_str_length(sqlite3_str *p){return p ? p->nChar : 0;}/* Truncate the text of the string to be no more than N bytes. */void sqlite3_str_truncate(sqlite3_str *p, int N){if( p!=0 && N>=0 && (u32)N<p->nChar ){p->nChar = N;p->zText[p->nChar] = 0;}}/* Return the current value for p */char *sqlite3_str_value(sqlite3_str *p){if( p==0 || p->nChar==0 ) return 0;p->zText[p->nChar] = 0;return p->zText;}/*** Reset an StrAccum string. Reclaim all malloced memory.*/void sqlite3_str_reset(StrAccum *p){if( isMalloced(p) ){sqlite3DbFree(p->db, p->zText);p->printfFlags &= ~SQLITE_PRINTF_MALLOCED;}p->nAlloc = 0;p->nChar = 0;p->zText = 0;}/*** Destroy a dynamically allocate sqlite3_str object and all** of its content, all in one call.*/void sqlite3_str_free(sqlite3_str *p){if( p ){sqlite3_str_reset(p);sqlite3_free(p);}}/*** Initialize a string accumulator.**** p: The accumulator to be initialized.** db: Pointer to a database connection. May be NULL. Lookaside** memory is used if not NULL. db->mallocFailed is set appropriately** when not NULL.** zBase: An initial buffer. May be NULL in which case the initial buffer** is malloced.** n: Size of zBase in bytes. If total space requirements never exceed** n then no memory allocations ever occur.** mx: Maximum number of bytes to accumulate. If mx==0 then no memory** allocations will ever occur.*/void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){p->zText = zBase;p->db = db;p->nAlloc = n;p->mxAlloc = mx;p->nChar = 0;p->accError = 0;p->printfFlags = 0;}/* Allocate and initialize a new dynamic string object */sqlite3_str *sqlite3_str_new(sqlite3 *db){sqlite3_str *p = sqlite3_malloc64(sizeof(*p));if( p ){sqlite3StrAccumInit(p, 0, 0, 0,db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);}else{p = &sqlite3OomStr;}return p;}/*** Print into memory obtained from sqliteMalloc(). Use the internal** %-conversion extensions.*/char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){char *z;char zBase[SQLITE_PRINT_BUF_SIZE];StrAccum acc;assert( db!=0 );sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase),db->aLimit[SQLITE_LIMIT_LENGTH]);acc.printfFlags = SQLITE_PRINTF_INTERNAL;sqlite3_str_vappendf(&acc, zFormat, ap);z = sqlite3StrAccumFinish(&acc);if( acc.accError==SQLITE_NOMEM ){sqlite3OomFault(db);}return z;}/*** Print into memory obtained from sqliteMalloc(). Use the internal** %-conversion extensions.*/char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){va_list ap;char *z;va_start(ap, zFormat);z = sqlite3VMPrintf(db, zFormat, ap);va_end(ap);return z;}/*** Print into memory obtained from sqlite3_malloc(). Omit the internal** %-conversion extensions.*/char *sqlite3_vmprintf(const char *zFormat, va_list ap){char *z;char zBase[SQLITE_PRINT_BUF_SIZE];StrAccum acc;#ifdef SQLITE_ENABLE_API_ARMORif( zFormat==0 ){(void)SQLITE_MISUSE_BKPT;return 0;}#endif#ifndef SQLITE_OMIT_AUTOINITif( sqlite3_initialize() ) return 0;#endifsqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);sqlite3_str_vappendf(&acc, zFormat, ap);z = sqlite3StrAccumFinish(&acc);return z;}/*** Print into memory obtained from sqlite3_malloc()(). Omit the internal** %-conversion extensions.*/char *sqlite3_mprintf(const char *zFormat, ...){va_list ap;char *z;#ifndef SQLITE_OMIT_AUTOINITif( sqlite3_initialize() ) return 0;#endifva_start(ap, zFormat);z = sqlite3_vmprintf(zFormat, ap);va_end(ap);return z;}/*** sqlite3_snprintf() works like snprintf() except that it ignores the** current locale settings. This is important for SQLite because we** are not able to use a "," as the decimal point in place of "." as** specified by some locales.**** Oops: The first two arguments of sqlite3_snprintf() are backwards** from the snprintf() standard. Unfortunately, it is too late to change** this without breaking compatibility, so we just have to live with the** mistake.**** sqlite3_vsnprintf() is the varargs version.*/char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){StrAccum acc;if( n<=0 ) return zBuf;#ifdef SQLITE_ENABLE_API_ARMORif( zBuf==0 || zFormat==0 ) {(void)SQLITE_MISUSE_BKPT;if( zBuf ) zBuf[0] = 0;return zBuf;}#endifsqlite3StrAccumInit(&acc, 0, zBuf, n, 0);sqlite3_str_vappendf(&acc, zFormat, ap);zBuf[acc.nChar] = 0;return zBuf;}char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){StrAccum acc;va_list ap;if( n<=0 ) return zBuf;#ifdef SQLITE_ENABLE_API_ARMORif( zBuf==0 || zFormat==0 ) {(void)SQLITE_MISUSE_BKPT;if( zBuf ) zBuf[0] = 0;return zBuf;}#endifsqlite3StrAccumInit(&acc, 0, zBuf, n, 0);va_start(ap,zFormat);sqlite3_str_vappendf(&acc, zFormat, ap);va_end(ap);zBuf[acc.nChar] = 0;return zBuf;}/* Maximum size of an sqlite3_log() message. */#if defined(SQLITE_MAX_LOG_MESSAGE)/* Leave the definition as supplied */#elif SQLITE_PRINT_BUF_SIZE*10>10000# define SQLITE_MAX_LOG_MESSAGE 10000#else# define SQLITE_MAX_LOG_MESSAGE (SQLITE_PRINT_BUF_SIZE*10)#endif/*** This is the routine that actually formats the sqlite3_log() message.** We house it in a separate routine from sqlite3_log() to avoid using** stack space on small-stack systems when logging is disabled.**** sqlite3_log() must render into a static buffer. It cannot dynamically** allocate memory because it might be called while the memory allocator** mutex is held.**** sqlite3_str_vappendf() might ask for *temporary* memory allocations for** certain format characters (%q) or for very large precisions or widths.** Care must be taken that any sqlite3_log() calls that occur while the** memory mutex is held do not use these mechanisms.*/static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){StrAccum acc; /* String accumulator */char zMsg[SQLITE_MAX_LOG_MESSAGE]; /* Complete log message */sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);sqlite3_str_vappendf(&acc, zFormat, ap);sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,sqlite3StrAccumFinish(&acc));}/*** Format and write a message to the log if logging is enabled.*/void sqlite3_log(int iErrCode, const char *zFormat, ...){va_list ap; /* Vararg list */if( sqlite3GlobalConfig.xLog ){va_start(ap, zFormat);renderLogMsg(iErrCode, zFormat, ap);va_end(ap);}}#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)/*** A version of printf() that understands %lld. Used for debugging.** The printf() built into some versions of windows does not understand %lld** and segfaults if you give it a long long int.*/void sqlite3DebugPrintf(const char *zFormat, ...){va_list ap;StrAccum acc;char zBuf[SQLITE_PRINT_BUF_SIZE*10];sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);va_start(ap,zFormat);sqlite3_str_vappendf(&acc, zFormat, ap);va_end(ap);sqlite3StrAccumFinish(&acc);#ifdef SQLITE_OS_TRACE_PROC{extern void SQLITE_OS_TRACE_PROC(const char *zBuf, int nBuf);SQLITE_OS_TRACE_PROC(zBuf, sizeof(zBuf));}#elsefprintf(stdout,"%s", zBuf);fflush(stdout);#endif}#endif/*** variable-argument wrapper around sqlite3_str_vappendf(). The bFlags argument** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats.*/void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){va_list ap;va_start(ap,zFormat);sqlite3_str_vappendf(p, zFormat, ap);va_end(ap);}/******************************************************************************* Reference counted string/blob 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(void *z){RCStr *p = (RCStr*)z;assert( p!=0 );p--;assert( p->nRCRef>0 );if( p->nRCRef>=2 ){p->nRCRef--;}else{sqlite3_free(p);}}/*** 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) + 1 );if( p==0 ) return 0;p->nRCRef = 1;return (char*)&p[1];}/*** 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 );pNew = sqlite3_realloc64(p, N+sizeof(RCStr)+1);if( pNew==0 ){sqlite3_free(p);return 0;}else{return (char*)&pNew[1];}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。