Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Remove undocumented extensions from sqlite_mprintf() and friends in order to make it about 10% smaller. (CVS 1207) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
0b3f552b986fd89c48c350b0746be93b |
User & Date: | drh 2004-02-02 12:29:25.000 |
Context
2004-02-08
| ||
00:40 | Preliminary fix for ticket #599. More testing and analysis needed. (CVS 1208) (check-in: dc5be2c82b user: drh tags: trunk) | |
2004-02-02
| ||
12:29 | Remove undocumented extensions from sqlite_mprintf() and friends in order to make it about 10% smaller. (CVS 1207) (check-in: 0b3f552b98 user: drh tags: trunk) | |
2004-02-01
| ||
01:22 | Fix the handling of -init option to the sqlite shell. Ticket #568. Also add hooks for encrypting the database. (CVS 1206) (check-in: 3c796de8d1 user: drh tags: trunk) | |
Changes
Changes to src/printf.c.
1 2 3 | /* ** The "printf" code that follows dates from the 1980's. It is in ** the public domain. The original comments are included here for | | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /* ** The "printf" code that follows dates from the 1980's. It is in ** the public domain. The original comments are included here for ** completeness. They are very out-of-date but might be useful as ** an historical reference. Most of the "enhancements" have been backed ** out so that the functionality is now the same as standard printf(). ** ************************************************************************** ** ** The following modules is an enhanced replacement for the "printf" subroutines ** found in the standard C library. The following enhancements are ** supported: ** ** + Additional functions. The standard set of "printf" functions ** includes printf, fprintf, sprintf, vprintf, vfprintf, and |
︙ | ︙ | |||
55 56 57 58 59 60 61 | */ /* #define COMPATIBILITY / * Compatible with SUN OS 4.1 */ /* ** Conversion types fall into various categories as defined by the ** following enumeration. */ | < | | | | | | | | | | | | | | | > > > > | | > > | < | < > > > > > > > | | | | | | | | | | < | | | | | | | | < | < | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | */ /* #define COMPATIBILITY / * Compatible with SUN OS 4.1 */ /* ** Conversion types fall into various categories as defined by the ** following enumeration. */ #define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */ #define etFLOAT 2 /* Floating point. %f */ #define etEXP 3 /* Exponentional notation. %e and %E */ #define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */ #define etSIZE 5 /* Return number of characters processed so far. %n */ #define etSTRING 6 /* Strings. %s */ #define etDYNSTRING 7 /* Dynamically allocated strings. %z */ #define etPERCENT 8 /* Percent symbol. %% */ #define etCHARX 9 /* Characters. %c */ #define etERROR 10 /* Used to indicate no such conversion type */ /* The rest are extensions, not normally found in printf() */ #define etCHARLIT 11 /* Literal characters. %' */ #define etSQLESCAPE 12 /* Strings with '\'' doubled. %q */ #define etSQLESCAPE2 13 /* Strings with '\'' doubled and enclosed in '', NULL pointers replaced by SQL NULL. %Q */ /* ** 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 */ char *charset; /* The character set for conversion */ char *prefix; /* Prefix on non-zero values in alt format */ } et_info; /* ** Allowed values for et_info.flags */ #define FLAG_SIGNED 1 /* True if the value to convert is signed */ #define FLAG_INTERN 2 /* True if for internal use only */ /* ** The following table is searched linearly, so it is good to put the ** most frequently used conversion types first. */ static et_info fmtinfo[] = { { 'd', 10, 1, etRADIX, "0123456789", 0 }, { 's', 0, 0, etSTRING, 0, 0 }, { 'z', 0, 2, etDYNSTRING, 0, 0 }, { 'q', 0, 0, etSQLESCAPE, 0, 0 }, { 'Q', 0, 0, etSQLESCAPE2, 0, 0 }, { 'c', 0, 0, etCHARX, 0, 0 }, { 'o', 8, 0, etRADIX, "01234567", "0" }, { 'u', 10, 0, etRADIX, "0123456789", 0 }, { 'x', 16, 0, etRADIX, "0123456789abcdef", "x0" }, { 'X', 16, 0, etRADIX, "0123456789ABCDEF", "X0" }, { 'f', 0, 1, etFLOAT, 0, 0 }, { 'e', 0, 1, etEXP, "e", 0 }, { 'E', 0, 1, etEXP, "E", 0 }, { 'g', 0, 1, etGENERIC, "e", 0 }, { 'G', 0, 1, etGENERIC, "E", 0 }, { 'i', 10, 1, etRADIX, "0123456789", 0 }, { 'n', 0, 0, etSIZE, 0, 0 }, { '%', 0, 0, etPERCENT, 0, 0 }, { 'p', 10, 0, etRADIX, "0123456789", 0 }, }; #define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0])) /* ** If NOFLOATINGPOINT is defined, then none of the floating point ** conversions will work. */ |
︙ | ︙ | |||
179 180 181 182 183 184 185 | ** Note that the order in which automatic variables are declared below ** seems to make a big difference in determining how fast this beast ** will run. */ static int vxprintf( void (*func)(void*,char*,int), void *arg, | | < | | | | | | | | | | | | | < | | | | | | | | | | | | | < | | < < | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | ** Note that the order in which automatic variables are declared below ** seems to make a big difference in determining how fast this beast ** will run. */ static int vxprintf( void (*func)(void*,char*,int), void *arg, const char *fmt, va_list ap ){ 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 count; /* Total number of characters output */ 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_alternateform; /* 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 */ unsigned long longvalue; /* Value for integer types */ LONGDOUBLE_TYPE realvalue; /* Value for real types */ et_info *infop; /* Pointer to the appropriate info structure */ char buf[etBUFSIZE]; /* Conversion buffer */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ etByte errorflag = 0; /* True if an error is encountered */ etByte xtype; /* Conversion paradigm */ char *zExtra; /* Extra memory used for etTCLESCAPE conversions */ static char spaces[] = " " " "; #define etSPACESIZE (sizeof(spaces)-1) #ifndef etNOFLOATINGPOINT int exp; /* exponent of real numbers */ double rounder; /* Used for rounding floating point values */ etByte flag_dp; /* True if decimal point should be shown */ etByte flag_rtz; /* True if trailing zeros should be removed */ etByte flag_exp; /* True to force display of the exponent */ int nsd; /* Number of significant digits returned */ #endif count = length = 0; bufpt = 0; for(; (c=(*fmt))!=0; ++fmt){ if( c!='%' ){ int amt; bufpt = (char *)fmt; amt = 1; while( (c=(*++fmt))!='%' && c!=0 ) amt++; (*func)(arg,bufpt,amt); count += amt; if( c==0 ) break; } if( (c=(*++fmt))==0 ){ errorflag = 1; (*func)(arg,"%",1); count++; break; } /* Find out what flags are present */ flag_leftjustify = flag_plussign = flag_blanksign = flag_alternateform = flag_zeropad = 0; do{ switch( c ){ case '-': flag_leftjustify = 1; c = 0; break; case '+': flag_plussign = 1; c = 0; break; case ' ': flag_blanksign = 1; c = 0; break; case '#': flag_alternateform = 1; c = 0; break; case '0': flag_zeropad = 1; c = 0; break; default: break; } }while( c==0 && (c=(*++fmt))!=0 ); /* Get the field width */ width = 0; if( c=='*' ){ width = va_arg(ap,int); if( width<0 ){ flag_leftjustify = 1; width = -width; |
︙ | ︙ | |||
300 301 302 303 304 305 306 307 308 309 310 311 312 | flag_long = 1; c = *++fmt; }else{ flag_long = 0; } /* Fetch the info entry for the field */ infop = 0; for(idx=0; idx<etNINFO; idx++){ if( c==fmtinfo[idx].fmttype ){ infop = &fmtinfo[idx]; break; } } | > > < < < < < < | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | flag_long = 1; c = *++fmt; }else{ flag_long = 0; } /* Fetch the info entry for the field */ infop = 0; xtype = etERROR; for(idx=0; idx<etNINFO; idx++){ if( c==fmtinfo[idx].fmttype ){ infop = &fmtinfo[idx]; xtype = infop->type; break; } } zExtra = 0; /* ** At this point, variables are initialized as follows: ** ** flag_alternateform TRUE if a '#' is present. ** flag_plussign TRUE if a '+' is present. |
︙ | ︙ | |||
333 334 335 336 337 338 339 | ** 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. */ switch( xtype ){ | < | < < < < < < < < < < < < < < < < < < < | 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | ** 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. */ switch( xtype ){ case etRADIX: if( flag_long ) longvalue = va_arg(ap,long); else longvalue = va_arg(ap,int); #ifdef etCOMPATIBILITY /* For the format %#x, the value zero is printed "0" not "0x0". ** I think this is stupid. */ if( longvalue==0 ) flag_alternateform = 0; #else /* More sensible: turn off the prefix for octal (to prevent "00"), ** but leave the prefix for hex. */ if( longvalue==0 && infop->base==8 ) flag_alternateform = 0; #endif if( infop->flags & FLAG_SIGNED ){ if( *(long*)&longvalue<0 ){ longvalue = -*(long*)&longvalue; prefix = '-'; }else if( flag_plussign ) prefix = '+'; else if( flag_blanksign ) prefix = ' '; else prefix = 0; }else prefix = 0; if( flag_zeropad && precision<width-(prefix!=0) ){ precision = width-(prefix!=0); } bufpt = &buf[etBUFSIZE]; { register char *cset; /* Use registers for speed */ register int base; cset = infop->charset; base = infop->base; do{ /* Convert to ascii */ *(--bufpt) = cset[longvalue%base]; |
︙ | ︙ | |||
605 606 607 608 609 610 611 | ** "length" characters long. The field width is "width". Do ** the output. */ if( !flag_leftjustify ){ register int nspace; nspace = width-length; if( nspace>0 ){ | < < < < < | 587 588 589 590 591 592 593 594 595 596 597 598 599 600 | ** "length" characters long. The field width is "width". Do ** the output. */ if( !flag_leftjustify ){ register int nspace; nspace = width-length; if( nspace>0 ){ count += nspace; while( nspace>=etSPACESIZE ){ (*func)(arg,spaces,etSPACESIZE); nspace -= etSPACESIZE; } if( nspace>0 ) (*func)(arg,spaces,nspace); } |
︙ | ︙ |
Changes to test/printf.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the sqlite_*_printf() interface. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the sqlite_*_printf() interface. # # $Id: printf.test,v 1.7 2004/02/02 12:29:25 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl set n 1 foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} { do_test printf-1.$n.1 [subst { |
︙ | ︙ | |||
103 104 105 106 107 108 109 | do_test printf-5.1 { set x [sqlite_mprintf_str {%d %d %100000s} 0 0 {Hello}] string length $x } {994} do_test printf-5.2 { sqlite_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello} } {-9 -10 (HelloHello) %} | < < < | 103 104 105 106 107 108 109 110 111 112 113 114 115 | do_test printf-5.1 { set x [sqlite_mprintf_str {%d %d %100000s} 0 0 {Hello}] string length $x } {994} do_test printf-5.2 { sqlite_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello} } {-9 -10 (HelloHello) %} do_test printf-6.1 { sqlite_mprintf_z_test , one two three four five six } {,one,two,three,four,five,six} finish_test |
Changes to test/tableapi.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the sqlite_exec_printf() and # sqlite_get_table_printf() APIs. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the sqlite_exec_printf() and # sqlite_get_table_printf() APIs. # # $Id: tableapi.test,v 1.7 2004/02/02 12:29:25 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_test tableapi-1.0 { set ::dbx [sqlite_open test.db] catch {sqlite_exec_printf $::dbx {DROP TABLE xyz} {}} |
︙ | ︙ | |||
58 59 60 61 62 63 64 | } {0 1 2 a b 50 (50)} do_test tableapi-2.3.2 { sqlite_get_table_printf $::dbx { SELECT * FROM xyz WHERE a>47 ORDER BY a } {} } {0 3 2 a b 48 (48) 49 (49) 50 (50)} do_test tableapi-2.4 { | > > > > > > > | | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | } {0 1 2 a b 50 (50)} do_test tableapi-2.3.2 { sqlite_get_table_printf $::dbx { SELECT * FROM xyz WHERE a>47 ORDER BY a } {} } {0 3 2 a b 48 (48) 49 (49) 50 (50)} do_test tableapi-2.4 { set manyquote '''''''' append manyquote $manyquote append manyquote $manyquote append manyquote $manyquote append manyquote $manyquote append manyquote $manyquote append manyquote $manyquote set ::big_str "$manyquote Hello $manyquote" sqlite_get_table_printf $::dbx { INSERT INTO xyz VALUES(51,'%q') } $::big_str } {0 0 0} do_test tableapi-2.5 { sqlite_get_table_printf $::dbx { SELECT * FROM xyz WHERE a>49 ORDER BY a; |
︙ | ︙ | |||
116 117 118 119 120 121 122 | } {0 1 2 a b 50 (50)} do_test tableapi-3.3.2 { sqlite_get_table_printf $::dbx { SELECT * FROM xyz WHERE a>47 ORDER BY a } {} } {0 3 2 a b 48 (48) 49 (49) 50 (50)} do_test tableapi-3.4 { | < | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | } {0 1 2 a b 50 (50)} do_test tableapi-3.3.2 { sqlite_get_table_printf $::dbx { SELECT * FROM xyz WHERE a>47 ORDER BY a } {} } {0 3 2 a b 48 (48) 49 (49) 50 (50)} do_test tableapi-3.4 { sqlite_get_table_printf $::dbx { INSERT INTO xyz VALUES(51,'%q') } $::big_str } {0 0 0} do_test tableapi-3.5 { sqlite_get_table_printf $::dbx { SELECT * FROM xyz WHERE a>49 ORDER BY a; |
︙ | ︙ |