summaryrefslogtreecommitdiff
path: root/ext/sqlite/libsqlite/src/printf.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sqlite/libsqlite/src/printf.c')
-rw-r--r--ext/sqlite/libsqlite/src/printf.c62
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