Skip to content

Instantly share code, notes, and snippets.

@youz
Created January 1, 2017 06:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save youz/2e34413d8b934401f907a0f131b98983 to your computer and use it in GitHub Desktop.
Save youz/2e34413d8b934401f907a0f131b98983 to your computer and use it in GitHub Desktop.
garray
#include <sqlite3ext.h>
SQLITE_EXTENSION_INIT1
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
static int g_arr_size;
static int* g_arr;
static void gaSizeOfIntFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
sqlite3_result_int64(context, sizeof(int));
}
static void gaInitFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
assert(argc == 1);
if (sqlite3_value_type(argv[0]) != SQLITE_INTEGER) {
sqlite3_result_error(context, "len must be an integer ", -1);
return;
}
int64_t len = sqlite3_value_int64(argv[0]);
if (len <= 0 || len > 0x1000000) {
sqlite3_result_error(context, "len must be in range [1 .. 2^24]", -1);
return;
}
free(g_arr);
g_arr = calloc((size_t)len, sizeof(int));
if (!g_arr) {
sqlite3_result_error_nomem(context);
g_arr_size = 0;
} else {
sqlite3_result_int64(context, len);
g_arr_size = len;
}
}
static void gaRefFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
assert(argc == 1);
if (g_arr_size == 0) {
sqlite3_result_error(context, "garray is not initialized", -1);
return;
}
if (sqlite3_value_type(argv[0]) != SQLITE_INTEGER) {
sqlite3_result_error(context, "index must be an integer", -1);
return;
}
int64_t idx = sqlite3_value_int64(argv[0]);
if (idx < 0 || idx >= g_arr_size) {
sqlite3_result_error(context, "range error", -1);
} else {
sqlite3_result_int64(context, g_arr[idx]);
}
}
static void gaSetFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
assert(argc == 2);
if (g_arr_size == 0) {
sqlite3_result_error(context, "garray is not initialized", -1);
return;
}
if (sqlite3_value_type(argv[0]) != SQLITE_INTEGER) {
sqlite3_result_error(context, "idx must be an integer", -1);
return;
}
if (sqlite3_value_type(argv[1]) != SQLITE_INTEGER) {
sqlite3_result_error(context, "value must be an integer", -1);
}
int64_t idx = sqlite3_value_int64(argv[0]);
int64_t set_value = sqlite3_value_int64(argv[1]);
if (idx < 0 || idx >= g_arr_size) {
sqlite3_result_error(context, "range error", -1);
} else {
g_arr[idx] = (int)set_value;
sqlite3_result_int64(context, g_arr[idx]);
}
}
static void gaReleaseFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
free(g_arr);
g_arr = NULL;
g_arr_size = 0;
sqlite3_result_int64(context, 0);
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_extension_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
g_arr = NULL;
g_arr_size = 0;
sqlite3_create_function_v2(db, "gainit", 1, SQLITE_UTF8, 0, gaInitFunc, 0, 0, NULL);
sqlite3_create_function_v2(db, "garef", 1, SQLITE_UTF8, 0, gaRefFunc, 0, 0, NULL);
sqlite3_create_function_v2(db, "gaset", 2, SQLITE_UTF8, 0, gaSetFunc, 0, 0, NULL);
sqlite3_create_function_v2(db, "garelease", 0, SQLITE_UTF8, 0, gaReleaseFunc, 0, 0, NULL);
sqlite3_create_function_v2(db, "gasizeofint", 0, SQLITE_UTF8, 0, gaSizeOfIntFunc, 0, 0, NULL);
return rc;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment