diff options
Diffstat (limited to 'ext/sqlite/libsqlite/src/printf.c')
-rw-r--r-- | ext/sqlite/libsqlite/src/printf.c | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/ext/sqlite/libsqlite/src/printf.c b/ext/sqlite/libsqlite/src/printf.c index 8587f80d28..e32487e6f4 100644 --- a/ext/sqlite/libsqlite/src/printf.c +++ b/ext/sqlite/libsqlite/src/printf.c @@ -66,6 +66,7 @@ enum et_type { /* The type of the format field */ etGENERIC, /* Floating or exponential, depending on exponent. %g */ etSIZE, /* Return number of characters processed so far. %n */ etSTRING, /* Strings. %s */ + etDYNSTRING, /* Dynamically allocated strings. %z */ etPERCENT, /* Percent symbol. %% */ etCHARX, /* Characters. %c */ etERROR, /* Used to indicate no such conversion type */ @@ -97,6 +98,7 @@ typedef struct et_info { /* Information about each format field */ static et_info fmtinfo[] = { { 'd', 10, "0123456789", 1, 0, etRADIX, }, { 's', 0, 0, 0, 0, etSTRING, }, + { 'z', 0, 0, 0, 0, etDYNSTRING, }, { 'q', 0, 0, 0, 0, etSQLESCAPE, }, { 'Q', 0, 0, 0, 0, etSQLESCAPE2, }, { 'c', 0, 0, 0, 0, etCHARX, }, @@ -389,7 +391,7 @@ static int vxprintf( longvalue = longvalue/base; }while( longvalue>0 ); } - length = (long)&buf[etBUFSIZE]-(long)bufpt; + length = &buf[etBUFSIZE]-bufpt; for(idx=precision-length; idx>0; idx--){ *(--bufpt) = '0'; /* Zero pad */ } @@ -401,7 +403,7 @@ static int vxprintf( for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x; } } - length = (long)&buf[etBUFSIZE]-(long)bufpt; + length = &buf[etBUFSIZE]-bufpt; break; case etFLOAT: case etEXP: @@ -511,7 +513,7 @@ static int vxprintf( /* 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 = (long)bufpt-(long)buf; + length = bufpt-buf; bufpt = buf; /* Special case: Add leading zeros if the flag_zeropad flag is @@ -549,8 +551,13 @@ static int vxprintf( bufpt = buf; break; case etSTRING: + case etDYNSTRING: bufpt = va_arg(ap,char*); - if( bufpt==0 ) bufpt = "(null)"; + if( bufpt==0 ){ + bufpt = ""; + }else if( xtype==etDYNSTRING ){ + zExtra = bufpt; + } length = strlen(bufpt); if( precision>=0 && precision<length ) length = precision; break; @@ -632,7 +639,11 @@ static int vxprintf( } } if( zExtra ){ - sqliteFree(zExtra); + if( xtype==etDYNSTRING ){ + free(zExtra); + }else{ + sqliteFree(zExtra); + } } }/* End for loop over the format string */ return errorflag ? -1 : count; @@ -747,6 +758,47 @@ char *sqlite_vmprintf(const char *zFormat, va_list ap){ return zNew; } +/* +** This function implements the callback from vxprintf. +** +** This routine add nNewChar characters of text in zNewText to +** the sgMprintf structure pointed to by "arg". Unlike mout() above, +** this routine does not allocate new space when the buffer fills. +** It just truncates. +*/ +static void sout(void *arg, char *zNewText, int nNewChar){ + struct sgMprintf *pM = (struct sgMprintf*)arg; + if( pM->nChar + nNewChar + 1 > pM->nAlloc ){ + nNewChar = pM->nAlloc - pM->nChar - 1; + if( nNewChar<=0 ) return; + } + memcpy(&pM->zText[pM->nChar], zNewText, nNewChar); + pM->nChar += nNewChar; + pM->zText[pM->nChar] = 0; +} + +/* +** sqlite_sprintf() works like sprintf() 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. +*/ +int sqlite_snprintf(int n, char *zBuf, const char *zFormat, ...){ + va_list ap; + struct sgMprintf sMprintf; + + sMprintf.nChar = 0; + sMprintf.nAlloc = n; + sMprintf.zText = zBuf; + sMprintf.zBase = zBuf; + va_start(ap,zFormat); + vxprintf(sout,&sMprintf,zFormat,ap); + va_end(ap); + return sMprintf.nChar; +} + + + /* ** The following four routines implement the varargs versions of the ** sqlite_exec() and sqlite_get_table() interfaces. See the sqlite.h |