mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-27 20:41:58 +03:00
Merge kv-vfs branch into fiddle-opfs branch to add kvvfs-based wasm build and demo.
FossilOrigin-Name: a7d8b26acd3c1ae344369e4d70804c0cab45272c0983cfd32d616a0a7b28acb9
This commit is contained in:
@ -523,226 +523,5 @@ int sqlite3_wasm_init_opfs(void){
|
||||
}
|
||||
#endif /* __EMSCRIPTEN__ && SQLITE_WASM_OPFS */
|
||||
|
||||
#if defined(__EMSCRIPTEN__) // && defined(SQLITE_OS_KV)
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/console.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 zKeyOut 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 "_".
|
||||
*/
|
||||
WASM_KEEP
|
||||
int sqlite3_wasm__kvvfsMakeKey(const char *zClass,
|
||||
const char *zKeyIn,
|
||||
char *zKeyOut){
|
||||
if(zKeyOut) 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. Though more verbose, this approach enables removal of
|
||||
** sqlite3_wasm__kvvfsMakeKey(). The only catch is that the
|
||||
** KVSTORAGE_KEY_SZ constant has to be hard-coded into this function.
|
||||
*/
|
||||
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
|
||||
|
||||
/*
|
||||
** Internal helper for kvstorageWrite/Read/Delete() which creates a
|
||||
** storage key for the given zClass/zKeyIn combination. Returns a
|
||||
** pointer to the key: a C string allocated on the WASM stack, or 0 if
|
||||
** allocation fails. It is up to the caller to save/restore the stack
|
||||
** before/after this operation.
|
||||
*/
|
||||
EM_JS(const char *, kvstorageMakeKeyOnJSStack,
|
||||
(const char *zClass, const char *zKeyIn),{
|
||||
if( 0==zClass || 0==zKeyIn) return 0;
|
||||
const zXKey = stackAlloc(_sqlite3_wasm__kvvfsMakeKey(0,0,0));
|
||||
if(zXKey) _sqlite3_wasm__kvvfsMakeKey(zClass, zKeyIn, zXKey);
|
||||
return zXKey;
|
||||
});
|
||||
|
||||
/*
|
||||
** JS impl of kvstorageWrite(). Main docs are in the C impl. This impl
|
||||
** writes zData to the global sessionStorage (if zClass starts with
|
||||
** 's') or localStorage, using a storage key derived from zClass and
|
||||
** zKey.
|
||||
*/
|
||||
EM_JS(int, kvstorageWrite,
|
||||
(const char *zClass, const char *zKey, const char *zData),{
|
||||
const stack = stackSave();
|
||||
try {
|
||||
const zXKey = kvstorageMakeKeyOnJSStack(zClass,zKey);
|
||||
if(!zXKey) return 1/*OOM*/;
|
||||
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;
|
||||
});
|
||||
|
||||
/*
|
||||
** JS impl of kvstorageDelete(). Main docs are in the C impl. This
|
||||
** impl generates a key derived from zClass and zKey, and removes the
|
||||
** matching entry (if any) from global sessionStorage (if zClass
|
||||
** starts with 's') or localStorage.
|
||||
*/
|
||||
EM_JS(int, kvstorageDelete,
|
||||
(const char *zClass, const char *zKey),{
|
||||
const stack = stackSave();
|
||||
try {
|
||||
const zXKey = kvstorageMakeKeyOnJSStack(zClass,zKey);
|
||||
if(!zXKey) return 1/*OOM*/;
|
||||
_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;
|
||||
});
|
||||
|
||||
/*
|
||||
** JS impl of kvstorageRead(). Main docs are in the C impl. This impl
|
||||
** reads its data from the global sessionStorage (if zClass starts
|
||||
** with 's') or localStorage, using a storage key derived from zClass
|
||||
** and zKey.
|
||||
*/
|
||||
EM_JS(int, kvstorageRead,
|
||||
(const char *zClass, const char *zKey, char *zBuf, int nBuf),{
|
||||
const stack = stackSave();
|
||||
try {
|
||||
const zXKey = kvstorageMakeKeyOnJSStack(zClass,zKey);
|
||||
if(!zXKey) return -3/*OOM*/;
|
||||
const jKey = UTF8ToString(zXKey);
|
||||
const jV = ((115/*=='s'*/===getValue(zClass))
|
||||
? sessionStorage : localStorage).getItem(jKey);
|
||||
if(!jV) return -1;
|
||||
const nV = jV.length /* Note that we are relying 100% on v being
|
||||
ASCII so that jV.length is equal to the
|
||||
C-string's byte length. */;
|
||||
if(nBuf<=0) return nV;
|
||||
else if(1===nBuf){
|
||||
setValue(zBuf, 0);
|
||||
return nV;
|
||||
}
|
||||
const zV = allocateUTF8OnStack(jV);
|
||||
if(nBuf > nV + 1) nBuf = nV + 1;
|
||||
HEAPU8.copyWithin(zBuf, zV, zV + nBuf - 1);
|
||||
setValue( zBuf + nBuf - 1, 0 );
|
||||
return nBuf - 1;
|
||||
}catch(e){
|
||||
console.error("kvstorageRead()",e);
|
||||
return -2;
|
||||
}finally{
|
||||
stackRestore(stack);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
** 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.
|
||||
*/
|
||||
WASM_KEEP
|
||||
int sqlite3_wasm__emjs_keep(int whichOp){
|
||||
int rc = 0;
|
||||
const char * zClass = "session";
|
||||
const char * zKey = "hello";
|
||||
switch( whichOp ){
|
||||
case 0: break;
|
||||
case 1:
|
||||
kvstorageWrite(zClass, zKey, "world");
|
||||
break;
|
||||
case 2: {
|
||||
char buffer[128] = {0};
|
||||
char * zBuf = &buffer[0];
|
||||
rc = kvstorageRead(zClass, zKey, zBuf, (int)sizeof(buffer));
|
||||
emscripten_console_logf("kvstorageRead()=%d %s\n", rc, zBuf);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
kvstorageDelete(zClass, zKey);
|
||||
break;
|
||||
case 4:
|
||||
kvstorageMakeKeyOnJSStack(0,0) /* force Emscripten to include this */;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif /* ifdef __EMSCRIPTEN__ (kvvfs method impls) */
|
||||
|
||||
#undef WASM_KEEP
|
||||
|
Reference in New Issue
Block a user