/ Check-in [af542c82]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Fix the char() function so that it works even if SQLITE_OMIT_UTF16 is defined.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: af542c82e8e7f0415530b639fa397429c5f377f6
User & Date: drh 2013-03-07 14:00:04
Context
2013-03-08
18:16
If SQLITE_OMIT_UTF16 is defined, avoid setting the 'enc' field of Schema objects to any value except SQLITE_UTF8. Otherwise, assert() statements may fail or spurious SQLITE_NOMEM errors may be returned at the vdbe level later on. check-in: f2fecfb2 user: dan tags: trunk
2013-03-07
14:00
Fix the char() function so that it works even if SQLITE_OMIT_UTF16 is defined. check-in: af542c82 user: drh tags: trunk
09:39
Skip tests that require UTF-16 support when compiled with SQLITE_OMIT_UTF16. check-in: e3939142 user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/func.c.

977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
...
996
997
998
999
1000
1001
1002
1003
1004
1005

1006
1007

1008
1009
1010
1011
1012





1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
....
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
}

/*
** The char() function takes zero or more arguments, each of which is
** an integer.  It constructs a string where each character of the string
** is the unicode character for the corresponding integer argument.
*/
#ifndef SQLITE_OMIT_UTF16
static void charFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  unsigned char *z, *zOut;
  int i;
................................................................................
  }
  for(i=0; i<argc; i++){
    sqlite3_int64 x;
    unsigned c;
    x = sqlite3_value_int64(argv[i]);
    if( x<0 || x>0x10ffff ) x = 0xfffd;
    c = (unsigned)(x & 0x1fffff);
    if( c<=0xFFFF ){
      if( c>=0xd800 && c<=0xdfff ) c = 0xfffd;
      *zOut++ = (u8)(c&0x00FF);

      *zOut++ = (u8)((c>>8)&0x00FF);
    }else{

      *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));
      *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03));
      *zOut++ = (u8)(c&0x00FF);
      *zOut++ = (u8)(0x00DC + ((c>>8)&0x03));
    }





  }
  sqlite3_result_text16le(context, (char*)z, (int)(zOut-z), sqlite3_free);
}
#endif

/*
** The hex() function.  Interpret the argument as a blob.  Return
** a hexadecimal rendering as text.
*/
static void hexFunc(
  sqlite3_context *context,
................................................................................
    AGGREGATE(max,               1, 1, 1, minmaxStep,      minMaxFinalize ),
    FUNCTION2(typeof,            1, 0, 0, typeofFunc,  SQLITE_FUNC_TYPEOF),
    FUNCTION2(length,            1, 0, 0, lengthFunc,  SQLITE_FUNC_LENGTH),
    FUNCTION(instr,              2, 0, 0, instrFunc        ),
    FUNCTION(substr,             2, 0, 0, substrFunc       ),
    FUNCTION(substr,             3, 0, 0, substrFunc       ),
    FUNCTION(unicode,            1, 0, 0, unicodeFunc      ),
#ifndef SQLITE_OMIT_UTF16
    FUNCTION(char,              -1, 0, 0, charFunc         ),
#endif
    FUNCTION(abs,                1, 0, 0, absFunc          ),
#ifndef SQLITE_OMIT_FLOATING_POINT
    FUNCTION(round,              1, 0, 0, roundFunc        ),
    FUNCTION(round,              2, 0, 0, roundFunc        ),
#endif
    FUNCTION(upper,              1, 0, 0, upperFunc        ),
    FUNCTION(lower,              1, 0, 0, lowerFunc        ),







<







 







|
<
|
>
|
<
>
|
|
|
|
|
>
>
>
>
>

|

<







 







<

<







977
978
979
980
981
982
983

984
985
986
987
988
989
990
...
995
996
997
998
999
1000
1001
1002

1003
1004
1005

1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019

1020
1021
1022
1023
1024
1025
1026
....
1642
1643
1644
1645
1646
1647
1648

1649

1650
1651
1652
1653
1654
1655
1656
}

/*
** The char() function takes zero or more arguments, each of which is
** an integer.  It constructs a string where each character of the string
** is the unicode character for the corresponding integer argument.
*/

static void charFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  unsigned char *z, *zOut;
  int i;
................................................................................
  }
  for(i=0; i<argc; i++){
    sqlite3_int64 x;
    unsigned c;
    x = sqlite3_value_int64(argv[i]);
    if( x<0 || x>0x10ffff ) x = 0xfffd;
    c = (unsigned)(x & 0x1fffff);
    if( c<0x00080 ){

      *zOut++ = (u8)(c&0xFF);
    }else if( c<0x00800 ){
      *zOut++ = 0xC0 + (u8)((c>>6)&0x1F);

      *zOut++ = 0x80 + (u8)(c & 0x3F);
    }else if( c<0x10000 ){
      *zOut++ = 0xE0 + (u8)((c>>12)&0x0F);
      *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
      *zOut++ = 0x80 + (u8)(c & 0x3F);
    }else{
      *zOut++ = 0xF0 + (u8)((c>>18) & 0x07);
      *zOut++ = 0x80 + (u8)((c>>12) & 0x3F);
      *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
      *zOut++ = 0x80 + (u8)(c & 0x3F);
    }                                                    \
  }
  sqlite3_result_text(context, (char*)z, (int)(zOut-z), sqlite3_free);
}


/*
** The hex() function.  Interpret the argument as a blob.  Return
** a hexadecimal rendering as text.
*/
static void hexFunc(
  sqlite3_context *context,
................................................................................
    AGGREGATE(max,               1, 1, 1, minmaxStep,      minMaxFinalize ),
    FUNCTION2(typeof,            1, 0, 0, typeofFunc,  SQLITE_FUNC_TYPEOF),
    FUNCTION2(length,            1, 0, 0, lengthFunc,  SQLITE_FUNC_LENGTH),
    FUNCTION(instr,              2, 0, 0, instrFunc        ),
    FUNCTION(substr,             2, 0, 0, substrFunc       ),
    FUNCTION(substr,             3, 0, 0, substrFunc       ),
    FUNCTION(unicode,            1, 0, 0, unicodeFunc      ),

    FUNCTION(char,              -1, 0, 0, charFunc         ),

    FUNCTION(abs,                1, 0, 0, absFunc          ),
#ifndef SQLITE_OMIT_FLOATING_POINT
    FUNCTION(round,              1, 0, 0, roundFunc        ),
    FUNCTION(round,              2, 0, 0, roundFunc        ),
#endif
    FUNCTION(upper,              1, 0, 0, upperFunc        ),
    FUNCTION(lower,              1, 0, 0, lowerFunc        ),

Changes to test/func.test.

1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
  if {$x<5} {set x 1}
  set x
} {1}

do_execsql_test func-30.1 {SELECT unicode('$');} 36
do_execsql_test func-30.2 [subst {SELECT unicode('\u00A2');}] 162
do_execsql_test func-30.3 [subst {SELECT unicode('\u20AC');}] 8364

ifcapable !utf16 {
  finish_test
  return
}

do_execsql_test func-30.4 {SELECT char(36,162,8364);} [subst {$\u00A2\u20AC}]

for {set i 1} {$i<0xd800} {incr i 13} {
  do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
}
for {set i 57344} {$i<=0xfffd} {incr i 17} {
  if {$i==0xfeff} continue







<
<
<
<
<
<







1289
1290
1291
1292
1293
1294
1295






1296
1297
1298
1299
1300
1301
1302
  if {$x<5} {set x 1}
  set x
} {1}

do_execsql_test func-30.1 {SELECT unicode('$');} 36
do_execsql_test func-30.2 [subst {SELECT unicode('\u00A2');}] 162
do_execsql_test func-30.3 [subst {SELECT unicode('\u20AC');}] 8364






do_execsql_test func-30.4 {SELECT char(36,162,8364);} [subst {$\u00A2\u20AC}]

for {set i 1} {$i<0xd800} {incr i 13} {
  do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
}
for {set i 57344} {$i<=0xfffd} {incr i 17} {
  if {$i==0xfeff} continue