01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
static const unsigned char sqlite3UtfTrans1[] = {  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,  0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,};int sqlite3Utf8Read(  const unsigned char *z,         /* First byte of UTF-8 character */  const unsigned char *zTerm,     /* Pretend this byte is 0x00 */  const unsigned char **pzNext    /* Write first byte past UTF-8 char here */){  int c = *(z++);  if( c>=0xc0 ){    c = sqlite3UtfTrans1[c-0xc0];    while( z!=zTerm && (*z & 0xc0)==0x80 ){      c = (c<<6) + (0x3f & *(z++));    }    if( c<0x80        || (c&0xFFFFF800)==0xD800        || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }  }  *pzNext = z;  return c;}int main(int argc, char** argv) {    unsigned char *str = (unsigned char*) argv[1];    unsigned int c, i;    printf("ORIGINAL:  %s\nORIGINAL:  ", str);    for(i = 0; i < strlen(str); i++) {	printf("\\x%02x", str[i]);    }    printf("\nConverted: ");    while( *str ) {	c = sqlite3Utf8Read(str, 0, &str);	printf("\\x%02x", c);    }    printf("\n");}% cc test_utf.c	  % ./a.out "サービスラーニング"ORIGINAL:  サービスラーニングORIGINAL:  \xa5\xb5\xa1\xbc\xa5\xd3\xa5\xb9\xa5\xe9\xa1\xbc\xa5\xcb\xa5\xf3\xa5\xb0Converted: \xa5\xb5\xa1\xbc\xa5\x4e5e65\x261f25\x2e5\x3970% ./a.out "サービス"ORIGINAL:  サービスORIGINAL:  \xa5\xb5\xa1\xbc\xa5\xd3\xa5\xb9Converted: \xa5\xb5\xa1\xbc\xa5\x13979% ./a.out "ラーニング"ORIGINAL:  ラーニングORIGINAL:  \xa5\xe9\xa1\xbc\xa5\xcb\xa5\xf3\xa5\xb0Converted: \xa5\x261f25\x2e5\x3970% ./a.out "「サービスラーニング」"ORIGINAL:  「サービスラーニング」ORIGINAL:  \xa1\xd6\xa5\xb5\xa1\xbc\xa5\xd3\xa5\xb9\xa5\xe9\xa1\xbc\xa5\xcb\xa5\xf3\xa5\xb0\xa1\xd7Converted: \xa1\xfffd\x4e5e65\x261f25\x2e5\xe5c21\xfffd