From: drh <> Date: Sat, 22 Feb 2025 23:18:38 +0000 (+0000) Subject: Prototype implementation of the unistr() SQL function. X-Git-Tag: major-release~241^2~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4d70dbad57c2099aac75a46b3dfb646df09587aa;p=thirdparty%2Fsqlite.git Prototype implementation of the unistr() SQL function. FossilOrigin-Name: 7cc302de05ed2a973372c05f55b048bf99af3d2590dd29f6fd0f379fb451aa0e --- diff --git a/manifest b/manifest index f2b2a13a57..6f0eef751f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Tamp\sdown\svarious\sharmless\scompiler\swarnings.\s\sUse\s"int"\sin\splaces\sinstead\nof\s"u16"\sor\s"i16"\ssince\sthe\scompiler\scomplains\sless\sand\sgenerates\sfaster\ncode. -D 2025-02-22T16:44:14.174 +C Prototype\simplementation\sof\sthe\sunistr()\sSQL\sfunction. +D 2025-02-22T23:18:38.072 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d @@ -735,7 +735,7 @@ F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42 F src/expr.c 6769d3f0ca9b1792e883e3ff21fdc5ca0033cece65571ebbf9d8b8fe2f47cd27 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f -F src/func.c 6c8b7bbdc5b588f3cfc79ed5effcfd3031758f5034c464fcd8891e8010b4d317 +F src/func.c ddfb4f3b8d2fbbe46dbe2bb28c9c79fc1defb7855975dfd851f2dd8417cc70be F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b F src/hash.c 73934a7f7ab1cb110614a9388cb516893b0cf5b7b69e4fd1a0780ac4ce166be7 F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf @@ -2210,8 +2210,11 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P eeea11278bdebe336f0c30fbad79e30e3456ab67dae46abdd5f9951ea1b61bed -R 8078ee78be0e4d7d18ee35dbad7406fe +P 742827f049768c4f69ccdfaadfad339aaad3bc126d3a68b90cfea01d825bf7ce +R 487d823b2a97be800308516e5c94d276 +T *branch * unistr +T *sym-unistr * +T -sym-trunk * U drh -Z 2ee0c7ad1f2d8a9853a04c1df0464ab5 +Z f399533fbf6bd526a1da3885c8fdaf47 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 5eab3882ff..080a91b1b8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -742827f049768c4f69ccdfaadfad339aaad3bc126d3a68b90cfea01d825bf7ce +7cc302de05ed2a973372c05f55b048bf99af3d2590dd29f6fd0f379fb451aa0e diff --git a/src/func.c b/src/func.c index 5784b75e2b..c80ac915a7 100644 --- a/src/func.c +++ b/src/func.c @@ -1149,6 +1149,132 @@ void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){ } } +/* +** Write a single UTF8 character whose value if v into the +** buffer starting at zOut. Return the number of bytes needed +** to encode that character. +*/ +static int appendOneUtf8Char(char *zOut, u32 v){ + if( v<0x00080 ){ + zOut[0] = (u8)(v & 0xff); + return 1; + } + if( v<0x00800 ){ + zOut[0] = 0xc0 + (u8)((v>>6) & 0x1f); + zOut[1] = 0x80 + (u8)(v & 0x3f); + return 2; + } + if( v<0x10000 ){ + zOut[0] = 0xe0 + (u8)((v>>12) & 0x0f); + zOut[1] = 0x80 + (u8)((v>>6) & 0x3f); + zOut[2] = 0x80 + (u8)(v & 0x3f); + return 3; + } + zOut[0] = 0xf0 + (u8)((v>>18) & 0x07); + zOut[1] = 0x80 + (u8)((v>>12) & 0x3f); + zOut[2] = 0x80 + (u8)((v>>6) & 0x3f); + zOut[3] = 0x80 + (u8)(v & 0x3f); + return 4; +} + +/* +** Return true if z[] begins with N hexadecimal digits, and write +** a decoding of those digits into *pVal. Or return false if any +** one of the first N characters in z[] is not a hexadecimal digit. +*/ +static int isNHex(const char *z, int N, u32 *pVal){ + int i; + int v = 0; + for(i=0; i0 ){ + memmove(&zOut[j], &zIn[i], n); + j += n; + i += n; + } + if( zIn[i+1]=='\\' ){ + i += 2; + zOut[j++] = '\\'; + }else if( sqlite3Isxdigit(zIn[i+1]) ){ + if( !isNHex(&zIn[i+1], 4, &v) ) goto unistr_error; + i += 5; + j += appendOneUtf8Char(&zOut[j], v); + }else if( zIn[i+1]=='+' ){ + if( !isNHex(&zIn[i+2], 6, &v) ) goto unistr_error; + i += 8; + j += appendOneUtf8Char(&zOut[j], v); + }else if( zIn[i+1]=='u' ){ + if( !isNHex(&zIn[i+2], 4, &v) ) goto unistr_error; + i += 6; + j += appendOneUtf8Char(&zOut[j], v); + }else if( zIn[i+1]=='U' ){ + if( !isNHex(&zIn[i+2], 8, &v) ) goto unistr_error; + i += 10; + j += appendOneUtf8Char(&zOut[j], v); + }else{ + goto unistr_error; + } + } + zOut[j] = 0; + sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8); + return; + +unistr_error: + sqlite3_free(zOut); + sqlite3_result_error(context, "invalid Unicode escape", -1); + return; +} + + /* ** Implementation of the QUOTE() function. ** @@ -2736,6 +2862,7 @@ void sqlite3RegisterBuiltinFunctions(void){ DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ), DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ), + FUNCTION(unistr, 1, 0, 0, unistrFunc ), FUNCTION(quote, 1, 0, 0, quoteFunc ), VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid), VFUNCTION(changes, 0, 0, 0, changes ),