diff options
author | Hans Hagen <pragma@wxs.nl> | 2022-09-16 15:53:42 +0200 |
---|---|---|
committer | Context Git Mirror Bot <phg@phi-gamma.net> | 2022-09-16 15:53:42 +0200 |
commit | c161b7d6fe142231346cc1844e6e27c0ab7718c1 (patch) | |
tree | 3fd877b8986137703e987e4651a2db8e946a0f72 /source/luametatex/source/luaoptional/lmtsqlite.c | |
parent | e94fa4dc30ec28a6727aa85e17aaac18b76aeadb (diff) | |
download | context-c161b7d6fe142231346cc1844e6e27c0ab7718c1.tar.gz |
2022-09-16 14:41:00
Diffstat (limited to 'source/luametatex/source/luaoptional/lmtsqlite.c')
-rw-r--r-- | source/luametatex/source/luaoptional/lmtsqlite.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/source/luametatex/source/luaoptional/lmtsqlite.c b/source/luametatex/source/luaoptional/lmtsqlite.c new file mode 100644 index 000000000..e6e8f1239 --- /dev/null +++ b/source/luametatex/source/luaoptional/lmtsqlite.c @@ -0,0 +1,228 @@ +/* + See license.txt in the root of this project. +*/ + +# include "luametatex.h" +# include "lmtoptional.h" + +typedef struct sqlite3_instance sqlite3_instance; + +# define SQLITELIB_METATABLE "luatex.sqlitelib" + +typedef struct sqlitelib_data { + /*tex There is not much more than a pointer currently. */ + sqlite3_instance *db; +} sqlitelib_data ; + +typedef struct sqlitelib_state_info { + + int initialized; + int padding; + + int (*sqlite3_initialize) ( + void + ); + + int (*sqlite3_open) ( + const char *filename, + sqlite3_instance **ppDb + ); + + int (*sqlite3_close) ( + sqlite3_instance * + ); + + int (*sqlite3_exec) ( + sqlite3_instance *, + const char *sql, + int (*callback)(void*, int, char**, char**), + void *, + char **errmsg + ); + + const char * (*sqlite3_errmsg) ( + sqlite3_instance * + ); + +} sqlitelib_state_info; + +static sqlitelib_state_info sqlitelib_state = { + + .initialized = 0, + .padding = 0, + + .sqlite3_initialize = NULL, + .sqlite3_open = NULL, + .sqlite3_close = NULL, + .sqlite3_exec = NULL, + .sqlite3_errmsg = NULL, + +}; + +static int sqlitelib_initialize(lua_State * L) +{ + if (! sqlitelib_state.initialized) { + const char *filename = lua_tostring(L, 1); + if (filename) { + + lmt_library lib = lmt_library_load(filename); + + sqlitelib_state.sqlite3_initialize = lmt_library_find(lib, "sqlite3_initialize"); + sqlitelib_state.sqlite3_open = lmt_library_find(lib, "sqlite3_open"); + sqlitelib_state.sqlite3_close = lmt_library_find(lib, "sqlite3_close"); + sqlitelib_state.sqlite3_exec = lmt_library_find(lib, "sqlite3_exec"); + sqlitelib_state.sqlite3_errmsg = lmt_library_find(lib, "sqlite3_errmsg"); + + sqlitelib_state.initialized = lmt_library_okay(lib); + } + if (sqlitelib_state.initialized) { + sqlitelib_state.sqlite3_initialize(); + } + } + lua_pushboolean(L, sqlitelib_state.initialized); + return 1; +} + +static int sqlitelib_open(lua_State * L) +{ + if (sqlitelib_state.initialized) { + const char *filename = lua_tostring(L, 1); + if (filename != NULL) { + sqlitelib_data *data = lua_newuserdatauv(L, sizeof(data), 0); + if (! sqlitelib_state.sqlite3_open(filename, &(data->db))) { + luaL_getmetatable(L, SQLITELIB_METATABLE); + lua_setmetatable(L, -2); + return 1; + } + } + } + return 0; +} + +static int sqlitelib_close(lua_State * L) +{ + if (sqlitelib_state.initialized) { + sqlitelib_data * data = luaL_checkudata(L, 1, SQLITELIB_METATABLE); + if (data != NULL) { + sqlitelib_state.sqlite3_close(data->db); + data->db = NULL; + } + } + return 0; +} + +/* we could save the fields in the registry */ + +static int rows_done = 0; /* can go on stack */ + +static int sqlitelib_callback(void * L, int nofcolumns, char **values, char **fields) +{ + lua_pushvalue(L, -1); + lua_pushinteger(L, nofcolumns); + if (nofcolumns > 0 && values != NULL) { + lua_createtable(L, nofcolumns, 0); + for (int i = 0; i < nofcolumns; i++) { + lua_pushstring(L, values[i]); + lua_rawseti(L, -2, (lua_Integer)i + 1); + } + if (! rows_done && fields != NULL) { + lua_createtable(L, nofcolumns, 0); + for (int i = 0; i < nofcolumns; i++) { + lua_pushstring(L, fields[i]); + lua_rawseti(L, -2, (lua_Integer)i + 1); + } + lua_call(L, 3, 0); + } else { + lua_call(L, 2, 0); + } + } else { + lua_call(L, 1, 0); + } + ++rows_done; + return 0; +} + +/* execute(database,querystring,callback) : callback(nofcolumns,values,fields) */ + +static int sqlitelib_execute(lua_State * L) +{ + if (sqlitelib_state.initialized && ! rows_done) { + sqlitelib_data * data = luaL_checkudata(L, 1, SQLITELIB_METATABLE); + if (data != NULL) { + const char *query = lua_tostring(L, 2); + if (query != NULL) { + int result = 0; + rows_done = 0; + if (lua_isfunction(L, 3)) { + result = sqlitelib_state.sqlite3_exec(data->db, query, &sqlitelib_callback, L, NULL); + } else { + result = sqlitelib_state.sqlite3_exec(data->db, query, NULL, NULL, NULL); + } + rows_done = 0; + lua_pushboolean(L, ! result); + return 1; + } + } + } + lua_pushboolean(L, 0); + return 1; +} + +static int sqlitelib_getmessage(lua_State * L) +{ + if (sqlitelib_state.initialized) { + sqlitelib_data * data = luaL_checkudata(L, 1, SQLITELIB_METATABLE); + if (data != NULL) { + lua_pushstring(L, sqlitelib_state.sqlite3_errmsg(data->db)); + return 1; + } + } + return 0; +} + +/* private */ + +static int sqlitelib_free(lua_State * L) +{ + return sqlitelib_close(L); +} + +/* <string> = tostring(instance) */ + +static int sqlitelib_tostring(lua_State * L) +{ + if (sqlitelib_state.initialized) { + sqlitelib_data * data = luaL_checkudata(L, 1, SQLITELIB_METATABLE); + if (data != NULL) { + (void) lua_pushfstring(L, "<sqlitelib-instance %p>", data); + } else { + lua_pushnil(L); + } + return 1; + } else { + return 0; + } +} + +static const struct luaL_Reg sqlitelib_metatable[] = { + { "__tostring", sqlitelib_tostring }, + { "__gc", sqlitelib_free }, + { NULL, NULL }, +}; + +static struct luaL_Reg sqlitelib_function_list[] = { + { "initialize", sqlitelib_initialize }, + { "open", sqlitelib_open }, + { "close", sqlitelib_close }, + { "execute", sqlitelib_execute }, + { "getmessage", sqlitelib_getmessage }, + { NULL, NULL }, +}; + +int luaopen_sqlite(lua_State * L) +{ + luaL_newmetatable(L, SQLITELIB_METATABLE); + luaL_setfuncs(L, sqlitelib_metatable, 0); + lmt_library_register(L, "sqlite", sqlitelib_function_list); + return 0; +} |