/ Check-in [b9c7ecc2]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added %Q format specifier: like %q but automatic enclosing in single quotes, NULL pointers replaced by NULL w/o single-quotes. (CVS 621)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b9c7ecc2f9d8d7d57c51dc4ba0aaa520e89eb31f
User & Date: chw 2002-06-16 04:55:48
Context
2002-06-16
04:56
Added printf-4.(2-4) test cases to test new %Q format specifier. (CVS 622) check-in: 7d5fc35b user: chw tags: trunk
04:55
Added %Q format specifier: like %q but automatic enclosing in single quotes, NULL pointers replaced by NULL w/o single-quotes. (CVS 621) check-in: b9c7ecc2 user: chw tags: trunk
04:54
Changed sqlite_mprintf_str to allow a NULL string parameter. Command template now is cmd FORMAT INT INT ?STRING?. When STRING omitted a NULL is passed to sqlite_mprintf. (CVS 620) check-in: 8bc71157 user: chw tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/printf.c.

68
69
70
71
72
73
74


75
76
77
78
79
80
81
..
92
93
94
95
96
97
98

99
100
101
102
103
104
105
...
549
550
551
552
553
554
555

556
557
558
559


560
561
562
563
564
565
566
567
568
569


570
571
572
573

574
575
576
577
578
579
580
   etSTRING,           /* Strings. %s */
   etPERCENT,          /* Percent symbol. %% */
   etCHARX,            /* Characters. %c */
   etERROR,            /* Used to indicate no such conversion type */
/* The rest are extensions, not normally found in printf() */
   etCHARLIT,          /* Literal characters.  %' */
   etSQLESCAPE,        /* Strings with '\'' doubled.  %q */


   etORDINAL           /* 1st, 2nd, 3rd and so forth */
};

/*
** Each builtin conversion character (ex: the 'd' in "%d") is described
** by an instance of the following structure
*/
................................................................................
** 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,  "0123456789",       1,    0, etRADIX,      },
  { 's',   0,  0,                  0,    0, etSTRING,     }, 
  { 'q',   0,  0,                  0,    0, etSQLESCAPE,  },

  { 'c',   0,  0,                  0,    0, etCHARX,      },
  { 'o',   8,  "01234567",         0,  "0", etRADIX,      },
  { 'u',  10,  "0123456789",       0,    0, etRADIX,      },
  { 'x',  16,  "0123456789abcdef", 0, "x0", etRADIX,      },
  { 'X',  16,  "0123456789ABCDEF", 0, "X0", etRADIX,      },
  { 'r',  10,  "0123456789",       0,    0, etORDINAL,    },
  { 'f',   0,  0,                  1,    0, etFLOAT,      },
................................................................................
      case etSTRING:
        zMem = bufpt = va_arg(ap,char*);
        if( bufpt==0 ) bufpt = "(null)";
        length = strlen(bufpt);
        if( precision>=0 && precision<length ) length = precision;
        break;
      case etSQLESCAPE:

        {
          int i, j, n, c;
          char *arg = va_arg(ap,char*);
          if( arg==0 ) arg = "(NULL)";


          for(i=n=0; (c=arg[i])!=0; i++){
            if( c=='\'' )  n++;
          }
          n += i + 1;
          if( n>etBUFSIZE ){
            bufpt = zExtra = sqliteMalloc( n );
            if( bufpt==0 ) return -1;
          }else{
            bufpt = buf;
          }


          for(i=j=0; (c=arg[i])!=0; i++){
            bufpt[j++] = c;
            if( c=='\'' ) bufpt[j++] = c;
          }

          bufpt[j] = 0;
          length = j;
          if( precision>=0 && precision<length ) length = precision;
        }
        break;
      case etERROR:
        buf[0] = '%';







>
>







 







>







 







>

|

<
>
>



|






>
>
|



>







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
..
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
552
553
554
555
556
557
558
559
560
561
562

563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
   etSTRING,           /* Strings. %s */
   etPERCENT,          /* Percent symbol. %% */
   etCHARX,            /* Characters. %c */
   etERROR,            /* Used to indicate no such conversion type */
/* The rest are extensions, not normally found in printf() */
   etCHARLIT,          /* Literal characters.  %' */
   etSQLESCAPE,        /* Strings with '\'' doubled.  %q */
   etSQLESCAPE2,       /* Strings with '\'' doubled and enclosed in '',
                          NULL pointers replaced by SQL NULL.  %Q */
   etORDINAL           /* 1st, 2nd, 3rd and so forth */
};

/*
** Each builtin conversion character (ex: the 'd' in "%d") is described
** by an instance of the following structure
*/
................................................................................
** 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,  "0123456789",       1,    0, etRADIX,      },
  { 's',   0,  0,                  0,    0, etSTRING,     }, 
  { 'q',   0,  0,                  0,    0, etSQLESCAPE,  },
  { 'Q',   0,  0,                  0,    0, etSQLESCAPE2, },
  { 'c',   0,  0,                  0,    0, etCHARX,      },
  { 'o',   8,  "01234567",         0,  "0", etRADIX,      },
  { 'u',  10,  "0123456789",       0,    0, etRADIX,      },
  { 'x',  16,  "0123456789abcdef", 0, "x0", etRADIX,      },
  { 'X',  16,  "0123456789ABCDEF", 0, "X0", etRADIX,      },
  { 'r',  10,  "0123456789",       0,    0, etORDINAL,    },
  { 'f',   0,  0,                  1,    0, etFLOAT,      },
................................................................................
      case etSTRING:
        zMem = bufpt = va_arg(ap,char*);
        if( bufpt==0 ) bufpt = "(null)";
        length = strlen(bufpt);
        if( precision>=0 && precision<length ) length = precision;
        break;
      case etSQLESCAPE:
      case etSQLESCAPE2:
        {
          int i, j, n, c, isnull;
          char *arg = va_arg(ap,char*);

          isnull = arg==0;
          if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
          for(i=n=0; (c=arg[i])!=0; i++){
            if( c=='\'' )  n++;
          }
          n += i + 1 + ((!isnull && xtype==etSQLESCAPE2) ? 2 : 0);
          if( n>etBUFSIZE ){
            bufpt = zExtra = sqliteMalloc( n );
            if( bufpt==0 ) return -1;
          }else{
            bufpt = buf;
          }
          j = 0;
          if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
          for(i=0; (c=arg[i])!=0; i++){
            bufpt[j++] = c;
            if( c=='\'' ) bufpt[j++] = c;
          }
          if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
          bufpt[j] = 0;
          length = j;
          if( precision>=0 && precision<length ) length = precision;
        }
        break;
      case etERROR:
        buf[0] = '%';