diff options
author | stephan <stephan@noemail.net> | 2022-09-11 02:43:08 +0000 |
---|---|---|
committer | stephan <stephan@noemail.net> | 2022-09-11 02:43:08 +0000 |
commit | d15822965be3898e9b306bbcdbfb72cbcdec4683 (patch) | |
tree | c3755fe5ce7106b44101cd278484a96ccd846d78 /ext/wasm/api/sqlite3-wasm.c | |
parent | f5bf66c8750b77b786ba52acac5e2838b8a4d91b (diff) | |
download | sqlite-d15822965be3898e9b306bbcdbfb72cbcdec4683.tar.gz sqlite-d15822965be3898e9b306bbcdbfb72cbcdec4683.zip |
Initial prototype impls of write/delete-key ops for the pending kvvfs which use sessionStorage or localStorage for db page storage. read-key op is pending.
FossilOrigin-Name: a4bd96f5348e607d0fcb627b751f9d86a188173a4b3bfb2c95f92913a78bd31e
Diffstat (limited to 'ext/wasm/api/sqlite3-wasm.c')
-rw-r--r-- | ext/wasm/api/sqlite3-wasm.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/ext/wasm/api/sqlite3-wasm.c b/ext/wasm/api/sqlite3-wasm.c index cea6dffa1..b0e51d068 100644 --- a/ext/wasm/api/sqlite3-wasm.c +++ b/ext/wasm/api/sqlite3-wasm.c @@ -483,3 +483,147 @@ int sqlite3_wasm_init_opfs(void){ return SQLITE_NOTFOUND; } #endif /* __EMSCRIPTEN__ && SQLITE_WASM_OPFS */ + +#if defined(__EMSCRIPTEN__) // && defined(SQLITE_OS_KV) +#include "emscripten.h" + +#ifndef KVSTORAGE_KEY_SZ +/* We can remove this once kvvfs and this bit is merged. */ +# define KVSTORAGE_KEY_SZ 32 +static void kvstorageMakeKey( + const char *zClass, + const char *zKeyIn, + char *zKeyOut +){ + sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn); +} +#endif + +/* +** An internal level of indirection for accessing the static +** kvstorageMakeKey() from EM_JS()-generated functions. This must be +** made available for export via Emscripten but is not intended to be +** used from client code. If called with a NULL zClass it is a no-op. +** It returns KVSTORAGE_KEY_SZ, so JS code (which cannot see that +** constant) may call it with NULL arguments to get the size of the +** allocation they'll need for a kvvfs key. +** +** Maintenance reminder: Emscripten will install this in the Module +** init scope and will prefix its name with "_". +*/ +int sqlite3_wasm__kvvfsMakeKey(const char *zClass, + const char *zKeyIn, + char *zKeyOut){ + if(zClass) kvstorageMakeKey(zClass, zKeyIn, zKeyOut); + return KVSTORAGE_KEY_SZ; +} + +#if 0 +/* +** Alternately, we can implement kvstorageMakeKey() in JS in such a +** way that it's visible to kvstorageWrite/Delete/Read() but not the +** rest of the world. This impl is considerably more verbose than +** the C impl because writing directly to memory requires more code in +** JS. +*/ +EM_JS(void, kvstorageMakeKeyJS, + (const char *zClass, const char *zKeyIn, char *zKeyOut),{ + const max = 32; + if(!arguments.length) return max; + let n = 0, i = 0, ch = 0; + // Write key prefix to dest... + if(0){ + const prefix = "kvvfs-"; + for(i in prefix) setValue(zKeyOut+(n++), prefix.charCodeAt(i)); + }else{ + // slightly optimized but less readable... + setValue(zKeyOut + (n++), 107/*'k'*/); + setValue(zKeyOut + (n++), 118/*'v'*/); + setValue(zKeyOut + (n++), 118/*'v'*/); + setValue(zKeyOut + (n++), 102/*'f'*/); + setValue(zKeyOut + (n++), 115/*'s'*/); + setValue(zKeyOut + (n++), 45/*'-'*/); + } + // Write zClass to dest... + for(i = 0; n < max && (ch = getValue(zClass+i)); ++n, ++i){ + setValue(zKeyOut + n, ch); + } + // Write "-" separator to dest... + if(n<max) setValue(zKeyOut + (n++), 45/* == '-'*/); + // Write zKeyIn to dest... + for(i = 0; n < max && (ch = getValue(zKeyIn+i)); ++n, ++i){ + setValue(zKeyOut + n, ch); + } + // NUL terminate... + if(n<max) setValue(zKeyOut + n, 0); +}); +#endif + +EM_JS(int, kvstorageWrite, + (const char *zClass, const char *zKey, const char *zData),{ + const stack = stackSave(); + try { + //const zXKey = stackAlloc(kvstorageMakeKeyJS()); + //kvstorageMakeKeyJS(zClass, zKey, zXKey); + const zXKey = stackAlloc(_sqlite3_wasm__kvvfsMakeKey(0,0,0)); + _sqlite3_wasm__kvvfsMakeKey(zClass, zKey, zXKey); + const jKey = UTF8ToString(zXKey); + /** + We could simplify this function and eliminate the + kvstorageMakeKey() symbol acrobatics if we'd simply hard-code + the key algo into the 3 functions which need it: + + const jKey = "kvvfs-"+UTF8ToString(zClass)+"-"+UTF8ToString(zKey); + */ + ((115/*=='s'*/===getValue(zClass)) + ? sessionStorage : localStorage).setItem(jKey, UTF8ToString(zData)); + }catch(e){ + console.error("kvstorageWrite()",e); + return 1; // Can't access SQLITE_xxx from here + }finally{ + stackRestore(stack); + } + return 0; +}); + +EM_JS(int, kvstorageDelete, + (const char *zClass, const char *zKey),{ + const stack = stackSave(); + try { + const zXKey = stackAlloc(_sqlite3_wasm__kvvfsMakeKey(0,0,0)); + _sqlite3_wasm__kvvfsMakeKey(zClass, zKey, zXKey); + const jKey = UTF8ToString(zXKey); + ((115/*=='s'*/===getValue(zClass)) + ? sessionStorage : localStorage).removeItem(jKey); + }catch(e){ + console.error("kvstorageDelete()",e); + return 1; + }finally{ + stackRestore(stack); + } + return 0; +}); + +/* +** This function exists for (1) WASM testing purposes and (2) as a +** hook to get Emscripten to export several EM_JS()-generated +** functions. It is not part of the public API and its signature +** and semantics may change at any time. +*/ +void sqlite3_wasm__emjs_test(int whichOp){ + const char * zClass = "session"; + const char * zKey = "hello"; + switch( whichOp ){ + case 1: + kvstorageWrite(zClass, zKey, "world"); + break; + case 2: + kvstorageDelete(zClass, zKey); + break; + default: + //kvstorageMakeKeyJS(0,0,0) /* force Emscripten to include this */; + break; + } +} + +#endif /* ifdef __EMSCRIPTEN__ */ |