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.
D 2017-02-09T17:12:22.122
C Add\sthe\s","\sflag\sto\sprintf().
D 2017-02-10T19:38:36.506
F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 067a6766f800cc8d72845ab61f8de4ffe8f3fc99
@ -390,7 +390,7 @@ F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953
F src/pragma.c 7831956012f5d764761fbd023e59b0ffc08f5e8d
F src/pragma.h 61aa5389118594bebb28120a6720401aee34ce1a
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
F src/printf.c ff10a9b9902cd2afe5f655f3013c6307d969b1fd
F src/printf.c 67427bbee66d891fc6f6f5aada857e9cdb368c1c
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c f9bc0de45a30a450da47b3766de00be89bf9be79
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
@ -1021,7 +1021,7 @@ F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
F test/pragma4.test 6e85b6eab8e61ffc9c7db59d842276674e8e3264
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
F test/printf2.test 9e6db85f81c63f2367c34a9d7db384088bd374ad
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
@ -1555,7 +1555,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 1afec5758b624e6a066d4e7ef50695095e9d7ff1
R d99a1e96a3817ca7543fc882a1f70881
P 798fb9d70d2e5f95e64237b04d6692360133381a
R c3dc7f748658995c87bb25e10706fab3
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
** 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 etEXP 2 /* Exponentional notation. %e and %E */
#define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */
@ -33,8 +33,9 @@
#define etPOINTER 13 /* The %p conversion */
#define etSQLESCAPE3 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 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
*/
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
#define FLAG_STRING 4 /* Allow infinity precision */
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
#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 aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
{ 'd', 10, 1, etRADIX, 0, 0 },
{ 'd', 10, 1, etDECIMAL, 0, 0 },
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 4, etDYNSTRING, 0, 0 },
@ -78,7 +79,7 @@ static const et_info fmtinfo[] = {
{ 'w', 0, 4, etSQLESCAPE3, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ '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, 0, 4 },
#ifndef SQLITE_OMIT_FLOATING_POINT
@ -87,7 +88,7 @@ static const et_info fmtinfo[] = {
{ 'E', 0, 1, etEXP, 14, 0 },
{ 'G', 0, 1, etGENERIC, 14, 0 },
#endif
{ 'i', 10, 1, etRADIX, 0, 0 },
{ 'i', 10, 1, etDECIMAL, 0, 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 16, 0, etPOINTER, 0, 1 },
@ -179,14 +180,13 @@ void sqlite3VXPrintf(
int idx; /* A general purpose loop counter */
int width; /* Width of the current field */
etByte flag_leftjustify; /* True if "-" flag is present */
etByte flag_plussign; /* True if "+" flag is present */
etByte flag_blanksign; /* 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; /* True if "l" flag is present */
etByte flag_longlong; /* True if the "ll" flag is present */
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'. */
@ -229,17 +229,18 @@ void sqlite3VXPrintf(
break;
}
/* Find out what flags are present */
flag_leftjustify = flag_plussign = flag_blanksign =
flag_leftjustify = flag_prefix = cThousand =
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
do{
switch( c ){
case '-': flag_leftjustify = 1; break;
case '+': flag_plussign = 1; break;
case ' ': flag_blanksign = 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;
}
}while( !done && (c=(*++fmt))!=0 );
@ -309,13 +310,11 @@ void sqlite3VXPrintf(
flag_long = 1;
c = *++fmt;
if( c=='l' ){
flag_longlong = 1;
flag_long = 2;
c = *++fmt;
}else{
flag_longlong = 0;
}
}else{
flag_long = flag_longlong = 0;
flag_long = 0;
}
/* Fetch the info entry for the field */
infop = &fmtinfo[0];
@ -333,15 +332,11 @@ void sqlite3VXPrintf(
**
** flag_alternateform 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
** field width was negative.
** flag_zeropad TRUE if the width began with 0.
** flag_long TRUE if the letter 'l' (ell) prefixed
** the conversion character.
** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
** the conversion character.
** flag_blanksign TRUE if a ' ' is present.
** 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
@ -351,19 +346,24 @@ void sqlite3VXPrintf(
*/
switch( xtype ){
case etPOINTER:
flag_longlong = sizeof(char*)==sizeof(i64);
flag_long = sizeof(char*)==sizeof(long int);
flag_long = sizeof(char*)==sizeof(i64) ? 2 :
sizeof(char*)==sizeof(long int) ? 1 : 0;
/* Fall through into the next case */
case etORDINAL:
case etRADIX:
case etRADIX:
cThousand = 0;
/* Fall through into the next case */
case etDECIMAL:
if( infop->flags & FLAG_SIGNED ){
i64 v;
if( bArgList ){
v = getIntArg(pArgList);
}else if( flag_longlong ){
v = va_arg(ap,i64);
}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{
v = va_arg(ap,int);
}
@ -376,17 +376,17 @@ void sqlite3VXPrintf(
prefix = '-';
}else{
longvalue = v;
if( flag_plussign ) prefix = '+';
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
prefix = flag_prefix;
}
}else{
if( bArgList ){
longvalue = (u64)getIntArg(pArgList);
}else if( flag_longlong ){
longvalue = va_arg(ap,u64);
}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{
longvalue = va_arg(ap,unsigned int);
}
@ -396,11 +396,11 @@ void sqlite3VXPrintf(
if( flag_zeropad && precision<width-(prefix!=0) ){
precision = width-(prefix!=0);
}
if( precision<etBUFSIZE-10 ){
if( precision<etBUFSIZE-10-etBUFSIZE/3 ){
nOut = etBUFSIZE;
zOut = buf;
}else{
nOut = precision + 10;
nOut = precision + 10 + precision/3;
zOut = zExtra = sqlite3Malloc( nOut );
if( zOut==0 ){
setStrAccumError(pAccum, STRACCUM_NOMEM);
@ -426,8 +426,23 @@ void sqlite3VXPrintf(
}while( longvalue>0 );
}
length = (int)(&zOut[nOut-1]-bufpt);
for(idx=precision-length; idx>0; idx--){
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" */
@ -454,9 +469,7 @@ void sqlite3VXPrintf(
realvalue = -realvalue;
prefix = '-';
}else{
if( flag_plussign ) prefix = '+';
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
prefix = flag_prefix;
}
if( xtype==etGENERIC && precision>0 ) precision--;
testcase( precision>0xfff );

View File

@ -116,6 +116,37 @@ do_execsql_test printf2-3.5 {
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|}