#include SQLITE_EXTENSION_INIT1 #include #include #include #include #include "compress.c" #define EVA_SIZE (sizeof(uint64_t) * MVEC_SIZE) void eva_render(sqlite3_context *context, int argc, sqlite3_value **argv) { assert(context); assert(argc == 4); assert(argv); (void)argc; size_t left = (size_t)sqlite3_value_int(argv[0]); #if defined(MVEC_LOOP) left %= MVEC_SIZE; #endif size_t px_count = (size_t)sqlite3_value_int(argv[1]); size_t px_pow = (size_t)sqlite3_value_int(argv[2]); size_t px_res = 1 << px_pow; #if !defined(MVEC_LOOP) #if !defined(NDEBUG) size_t right = left + px_res * px_count; #endif assert(left < MVEC_SIZE); assert(right <= MVEC_SIZE); #endif const void *blob = sqlite3_value_blob(argv[3]); size_t blob_size = (size_t)sqlite3_value_bytes(argv[3]); // Inflate blob size_t out_size = sizeof(uint64_t) * px_count; uint64_t *eva = sqlite3_malloc(EVA_SIZE); uint64_t *out = sqlite3_malloc(out_size); z_stream strm = { 0 }; salis_inflate(&strm, blob_size, EVA_SIZE, (Bytef *)blob, (Bytef *)eva); salis_inflate_end(&strm); // Render image for (size_t i = 0; i < px_count; i++) { out[i] = 0; for (size_t j = 0; j < px_res; j++) { size_t in_coord = left + i * px_res + j; #if defined(MVEC_LOOP) in_coord %= MVEC_SIZE; #endif out[i] += eva[in_coord]; } } sqlite3_free(eva); // Transform rendered image into textual representation // A comma-separated list of hexadecimal integers char *csv = sqlite3_malloc(px_count * 17 + 1); char *ptr = csv; for (size_t i = 0; i < px_count; i++) { ptr += sprintf(ptr, "%lx ", out[i]); } *(--ptr) = '\0'; sqlite3_free(out); sqlite3_result_text(context, csv, -1, sqlite3_free); } int sqlite3_render_init(sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi) { assert(db); assert(pzErrMsg); assert(pApi); (void)pzErrMsg; SQLITE_EXTENSION_INIT2(pApi); return sqlite3_create_function(db, "eva_render", 4, SQLITE_DETERMINISTIC | SQLITE_INNOCUOUS | SQLITE_UTF8, NULL, eva_render, NULL, NULL); }