Add the "," flag to printf().

FossilOrigin-Name: 064445b12f99f76e9a12957be97edd520ab3ae27
This commit is contained in:
drh 2017-02-10 19:38:36 +00:00
parent a39284bfa8
commit 2c338a9d9a
4 changed files with 94 additions and 50 deletions

View File

@ -1,5 +1,5 @@
C Cleanup\sthe\susage\sof\sthe\sSQLITE_DISABLE_INTRINSIC\scompile-time\soption.\nRemove\sthe\sSQLITE_RUNTIME_BYTEORDER\scompile-time\soption.\s\sUse\n-DSQLITE_BYTEORDER=0\sinstead.\s\sFix\sa\sbug\sin\sR-Tree\sthat\soccurs\swhen\scompiling\non\sa\sknown\slittle-endian\smachine\swithout\sthe\suse\sof\sintrinsic\sbyteswapping\nfunctions. C Add\sthe\s","\sflag\sto\sprintf().
D 2017-02-09T17:12:22.122 D 2017-02-10T19:38:36.506
F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918 F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 067a6766f800cc8d72845ab61f8de4ffe8f3fc99 F Makefile.msc 067a6766f800cc8d72845ab61f8de4ffe8f3fc99
@ -390,7 +390,7 @@ F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953
F src/pragma.c 7831956012f5d764761fbd023e59b0ffc08f5e8d F src/pragma.c 7831956012f5d764761fbd023e59b0ffc08f5e8d
F src/pragma.h 61aa5389118594bebb28120a6720401aee34ce1a F src/pragma.h 61aa5389118594bebb28120a6720401aee34ce1a
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
F src/printf.c ff10a9b9902cd2afe5f655f3013c6307d969b1fd F src/printf.c 67427bbee66d891fc6f6f5aada857e9cdb368c1c
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c f9bc0de45a30a450da47b3766de00be89bf9be79 F src/resolve.c f9bc0de45a30a450da47b3766de00be89bf9be79
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
@ -1021,7 +1021,7 @@ F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
F test/pragma4.test 6e85b6eab8e61ffc9c7db59d842276674e8e3264 F test/pragma4.test 6e85b6eab8e61ffc9c7db59d842276674e8e3264
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054 F test/printf2.test 9e6db85f81c63f2367c34a9d7db384088bd374ad
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
@ -1555,7 +1555,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 1afec5758b624e6a066d4e7ef50695095e9d7ff1 P 798fb9d70d2e5f95e64237b04d6692360133381a
R d99a1e96a3817ca7543fc882a1f70881 R c3dc7f748658995c87bb25e10706fab3
U drh U drh
Z 871c0b5ab0829dba2d37da91622734c8 Z 3add84968b9ef1dfcf3d7b3eaefd30ad

View File

@ -1 +1 @@
798fb9d70d2e5f95e64237b04d6692360133381a 064445b12f99f76e9a12957be97edd520ab3ae27

View File

@ -15,7 +15,7 @@
** Conversion types fall into various categories as defined by the ** Conversion types fall into various categories as defined by the
** following enumeration. ** following enumeration.
*/ */
#define etRADIX 0 /* Integer types. %d, %x, %o, and so forth */ #define etRADIX 0 /* non-decimal integer types. %x %o */
#define etFLOAT 1 /* Floating point. %f */ #define etFLOAT 1 /* Floating point. %f */
#define etEXP 2 /* Exponentional notation. %e and %E */ #define etEXP 2 /* Exponentional notation. %e and %E */
#define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */ #define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */
@ -33,8 +33,9 @@
#define etPOINTER 13 /* The %p conversion */ #define etPOINTER 13 /* The %p conversion */
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */ #define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */ #define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
#define etDECIMAL 16 /* %d or %u, but not %x, %o */
#define etINVALID 16 /* Any unrecognized conversion type */ #define etINVALID 17 /* Any unrecognized conversion type */
/* /*
@ -58,8 +59,8 @@ typedef struct et_info { /* Information about each format field */
/* /*
** Allowed values for et_info.flags ** Allowed values for et_info.flags
*/ */
#define FLAG_SIGNED 1 /* True if the value to convert is signed */ #define FLAG_SIGNED 1 /* True if the value to convert is signed */
#define FLAG_STRING 4 /* Allow infinity precision */ #define FLAG_STRING 4 /* Allow infinite precision */
/* /*
@ -69,7 +70,7 @@ typedef struct et_info { /* Information about each format field */
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef"; static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
static const char aPrefix[] = "-x0\000X0"; static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = { static const et_info fmtinfo[] = {
{ 'd', 10, 1, etRADIX, 0, 0 }, { 'd', 10, 1, etDECIMAL, 0, 0 },
{ 's', 0, 4, etSTRING, 0, 0 }, { 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 }, { 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 4, etDYNSTRING, 0, 0 }, { 'z', 0, 4, etDYNSTRING, 0, 0 },
@ -78,7 +79,7 @@ static const et_info fmtinfo[] = {
{ 'w', 0, 4, etSQLESCAPE3, 0, 0 }, { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 }, { 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, 0, 2 }, { 'o', 8, 0, etRADIX, 0, 2 },
{ 'u', 10, 0, etRADIX, 0, 0 }, { 'u', 10, 0, etDECIMAL, 0, 0 },
{ 'x', 16, 0, etRADIX, 16, 1 }, { 'x', 16, 0, etRADIX, 16, 1 },
{ 'X', 16, 0, etRADIX, 0, 4 }, { 'X', 16, 0, etRADIX, 0, 4 },
#ifndef SQLITE_OMIT_FLOATING_POINT #ifndef SQLITE_OMIT_FLOATING_POINT
@ -87,7 +88,7 @@ static const et_info fmtinfo[] = {
{ 'E', 0, 1, etEXP, 14, 0 }, { 'E', 0, 1, etEXP, 14, 0 },
{ 'G', 0, 1, etGENERIC, 14, 0 }, { 'G', 0, 1, etGENERIC, 14, 0 },
#endif #endif
{ 'i', 10, 1, etRADIX, 0, 0 }, { 'i', 10, 1, etDECIMAL, 0, 0 },
{ 'n', 0, 0, etSIZE, 0, 0 }, { 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 }, { '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 16, 0, etPOINTER, 0, 1 }, { 'p', 16, 0, etPOINTER, 0, 1 },
@ -179,14 +180,13 @@ void sqlite3VXPrintf(
int idx; /* A general purpose loop counter */ int idx; /* A general purpose loop counter */
int width; /* Width of the current field */ int width; /* Width of the current field */
etByte flag_leftjustify; /* True if "-" flag is present */ etByte flag_leftjustify; /* True if "-" flag is present */
etByte flag_plussign; /* True if "+" flag is present */ etByte flag_prefix; /* '+' or ' ' or 0 for prefix */
etByte flag_blanksign; /* True if " " flag is present */
etByte flag_alternateform; /* True if "#" flag is present */ etByte flag_alternateform; /* True if "#" flag is present */
etByte flag_altform2; /* 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_zeropad; /* True if field width constant starts with zero */
etByte flag_long; /* True if "l" flag is present */ etByte flag_long; /* 1 for the "l" flag, 2 for "ll", 0 by default */
etByte flag_longlong; /* True if the "ll" flag is present */
etByte done; /* Loop termination flag */ etByte done; /* Loop termination flag */
etByte cThousand; /* Thousands separator for %d and %u */
etByte xtype = etINVALID; /* Conversion paradigm */ etByte xtype = etINVALID; /* Conversion paradigm */
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
@ -229,17 +229,18 @@ void sqlite3VXPrintf(
break; break;
} }
/* Find out what flags are present */ /* Find out what flags are present */
flag_leftjustify = flag_plussign = flag_blanksign = flag_leftjustify = flag_prefix = cThousand =
flag_alternateform = flag_altform2 = flag_zeropad = 0; flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0; done = 0;
do{ do{
switch( c ){ switch( c ){
case '-': flag_leftjustify = 1; break; case '-': flag_leftjustify = 1; break;
case '+': flag_plussign = 1; break; case '+': flag_prefix = '+'; break;
case ' ': flag_blanksign = 1; break; case ' ': flag_prefix = ' '; break;
case '#': flag_alternateform = 1; break; case '#': flag_alternateform = 1; break;
case '!': flag_altform2 = 1; break; case '!': flag_altform2 = 1; break;
case '0': flag_zeropad = 1; break; case '0': flag_zeropad = 1; break;
case ',': cThousand = ','; break;
default: done = 1; break; default: done = 1; break;
} }
}while( !done && (c=(*++fmt))!=0 ); }while( !done && (c=(*++fmt))!=0 );
@ -309,13 +310,11 @@ void sqlite3VXPrintf(
flag_long = 1; flag_long = 1;
c = *++fmt; c = *++fmt;
if( c=='l' ){ if( c=='l' ){
flag_longlong = 1; flag_long = 2;
c = *++fmt; c = *++fmt;
}else{
flag_longlong = 0;
} }
}else{ }else{
flag_long = flag_longlong = 0; flag_long = 0;
} }
/* Fetch the info entry for the field */ /* Fetch the info entry for the field */
infop = &fmtinfo[0]; infop = &fmtinfo[0];
@ -333,15 +332,11 @@ void sqlite3VXPrintf(
** **
** flag_alternateform TRUE if a '#' is present. ** flag_alternateform TRUE if a '#' is present.
** flag_altform2 TRUE if a '!' is present. ** flag_altform2 TRUE if a '!' is present.
** flag_plussign TRUE if a '+' is present. ** flag_prefix '+' or ' ' or zero
** flag_leftjustify TRUE if a '-' is present or if the ** flag_leftjustify TRUE if a '-' is present or if the
** field width was negative. ** field width was negative.
** flag_zeropad TRUE if the width began with 0. ** flag_zeropad TRUE if the width began with 0.
** flag_long TRUE if the letter 'l' (ell) prefixed ** flag_long 1 for "l", 2 for "ll"
** the conversion character.
** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
** the conversion character.
** flag_blanksign TRUE if a ' ' is present.
** width The specified field width. This is ** width The specified field width. This is
** always non-negative. Zero is the default. ** always non-negative. Zero is the default.
** precision The specified precision. The default ** precision The specified precision. The default
@ -351,19 +346,24 @@ void sqlite3VXPrintf(
*/ */
switch( xtype ){ switch( xtype ){
case etPOINTER: case etPOINTER:
flag_longlong = sizeof(char*)==sizeof(i64); flag_long = sizeof(char*)==sizeof(i64) ? 2 :
flag_long = sizeof(char*)==sizeof(long int); sizeof(char*)==sizeof(long int) ? 1 : 0;
/* Fall through into the next case */ /* Fall through into the next case */
case etORDINAL: case etORDINAL:
case etRADIX: case etRADIX:
cThousand = 0;
/* Fall through into the next case */
case etDECIMAL:
if( infop->flags & FLAG_SIGNED ){ if( infop->flags & FLAG_SIGNED ){
i64 v; i64 v;
if( bArgList ){ if( bArgList ){
v = getIntArg(pArgList); v = getIntArg(pArgList);
}else if( flag_longlong ){
v = va_arg(ap,i64);
}else if( flag_long ){ }else if( flag_long ){
v = va_arg(ap,long int); if( flag_long==2 ){
v = va_arg(ap,i64) ;
}else{
v = va_arg(ap,long int);
}
}else{ }else{
v = va_arg(ap,int); v = va_arg(ap,int);
} }
@ -376,17 +376,17 @@ void sqlite3VXPrintf(
prefix = '-'; prefix = '-';
}else{ }else{
longvalue = v; longvalue = v;
if( flag_plussign ) prefix = '+'; prefix = flag_prefix;
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
} }
}else{ }else{
if( bArgList ){ if( bArgList ){
longvalue = (u64)getIntArg(pArgList); longvalue = (u64)getIntArg(pArgList);
}else if( flag_longlong ){
longvalue = va_arg(ap,u64);
}else if( flag_long ){ }else if( flag_long ){
longvalue = va_arg(ap,unsigned long int); if( flag_long==2 ){
longvalue = va_arg(ap,u64);
}else{
longvalue = va_arg(ap,unsigned long int);
}
}else{ }else{
longvalue = va_arg(ap,unsigned int); longvalue = va_arg(ap,unsigned int);
} }
@ -396,11 +396,11 @@ void sqlite3VXPrintf(
if( flag_zeropad && precision<width-(prefix!=0) ){ if( flag_zeropad && precision<width-(prefix!=0) ){
precision = width-(prefix!=0); precision = width-(prefix!=0);
} }
if( precision<etBUFSIZE-10 ){ if( precision<etBUFSIZE-10-etBUFSIZE/3 ){
nOut = etBUFSIZE; nOut = etBUFSIZE;
zOut = buf; zOut = buf;
}else{ }else{
nOut = precision + 10; nOut = precision + 10 + precision/3;
zOut = zExtra = sqlite3Malloc( nOut ); zOut = zExtra = sqlite3Malloc( nOut );
if( zOut==0 ){ if( zOut==0 ){
setStrAccumError(pAccum, STRACCUM_NOMEM); setStrAccumError(pAccum, STRACCUM_NOMEM);
@ -426,8 +426,23 @@ void sqlite3VXPrintf(
}while( longvalue>0 ); }while( longvalue>0 );
} }
length = (int)(&zOut[nOut-1]-bufpt); length = (int)(&zOut[nOut-1]-bufpt);
for(idx=precision-length; idx>0; idx--){ while( precision>length ){
*(--bufpt) = '0'; /* Zero pad */ *(--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( prefix ) *(--bufpt) = prefix; /* Add sign */
if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */ if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
@ -454,9 +469,7 @@ void sqlite3VXPrintf(
realvalue = -realvalue; realvalue = -realvalue;
prefix = '-'; prefix = '-';
}else{ }else{
if( flag_plussign ) prefix = '+'; prefix = flag_prefix;
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
} }
if( xtype==etGENERIC && precision>0 ) precision--; if( xtype==etGENERIC && precision>0 ) precision--;
testcase( precision>0xfff ); testcase( precision>0xfff );

View File

@ -116,6 +116,37 @@ do_execsql_test printf2-3.5 {
SELECT printf('|%7.8c|%-7.8c|','*','*'); SELECT printf('|%7.8c|%-7.8c|','*','*');
} {|********|********|} } {|********|********|}
# The "," separator
do_execsql_test printf2-4.1 {
SELECT printf('|%,d|%,d|',0,-1);
} {|0|-1|}
do_execsql_test printf2-4.2 {
SELECT printf('|%,d|%,d|',12,-12);
} {|12|-12|}
do_execsql_test printf2-4.3 {
SELECT printf('|%,d|%,d|',123,-123);
} {|123|-123|}
do_execsql_test printf2-4.4 {
SELECT printf('|%,d|%,d|',1234,-1234);
} {|1,234|-1,234|}
do_execsql_test printf2-4.5 {
SELECT printf('|%,d|%,d|',12345,-12345);
} {|12,345|-12,345|}
do_execsql_test printf2-4.6 {
SELECT printf('|%,d|%,d|',123456,-123456);
} {|123,456|-123,456|}
do_execsql_test printf2-4.7 {
SELECT printf('|%,d|%,d|',1234567,-1234567);
} {|1,234,567|-1,234,567|}
do_execsql_test printf2-4.8 {
SELECT printf('|%,d|%,d|',12345678,-12345678);
} {|12,345,678|-12,345,678|}
do_execsql_test printf2-4.9 {
SELECT printf('|%,d|%,d|',123456789,-123456789);
} {|123,456,789|-123,456,789|}
do_execsql_test printf2-4.10 {
SELECT printf('|%,d|%,d|',1234567890,-1234567890);
} {|1,234,567,890|-1,234,567,890|}