Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -959,10 +959,60 @@ sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); break; } } } + +/* +** The unicode() function. Return the integer unicode code-point value +** for the first character of the input string. +*/ +static void unicodeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *z = sqlite3_value_text(argv[0]); + if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z)); +} + +/* +** 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; + zOut = z = sqlite3_malloc( argc*4 ); + if( z==0 ){ + sqlite3_result_error_nomem(context); + return; + } + for(i=0; i0x10ffff ) x = 0xfffd; + c = (unsigned)(x & 0x1fffff); + if( c<=0xFFFF ){ + *zOut++ = (u8)(c&0x00FF); + *zOut++ = (u8)((c>>8)&0x00FF); + }else{ + if( c>=0xd800 && c<=0xdbff ) c = 0xfffd; + *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); +} /* ** The hex() function. Interpret the argument as a blob. Return ** a hexadecimal rendering as text. */ @@ -1587,10 +1637,12 @@ 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 Index: test/func.test ================================================================== --- test/func.test +++ test/func.test @@ -1287,8 +1287,12 @@ do_test func-29.6 { set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1] if {$x<5} {set x 1} set x } {1} - + +do_execsql_test func-30.1 {SELECT unicode('$');} 36 +do_execsql_test func-30.2 {SELECT unicode('¢');} 162 +do_execsql_test func-30.3 {SELECT unicode('€');} 8364 +do_execsql_test func-30.4 {SELECT char(36,162,8364);} {$¢€} finish_test