aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2023-03-19 20:39:32 +0000
committerthe lemons <citrons@mondecitronne.com>2023-03-20 22:24:06 -0500
commitf6a88e1ee6d62dc447a8d8b1d77d63f1ab9b5ade (patch)
treef474ee7763b1314f718bca961d986905c831af9b
parent2731d37fe4f62b1ce9bfd7da09d1636082526fc2 (diff)
add support for lua 5.1
uses a weak-keyed table in the registry to store parent-child mappings, instead of associated uservalues, which were only added in 5.2.
-rw-r--r--Makefile6
-rw-r--r--lmdb.c68
2 files changed, 65 insertions, 9 deletions
diff --git a/Makefile b/Makefile
index 4b4860a..21d3629 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,11 @@
LUA_VER=5.3
CC = cc
LD = ld
-CFLAGS = -std=c99 -Wall -O2 -fPIC -I/usr/include/lua$(LUA_VER)
+MORE_CFLAGS=
+ifeq ($(LUA_VER),5.1)
+ MORE_CFLAGS=-DLUA_5_1
+endif
+CFLAGS = $(MORE_CFLAGS) -std=c99 -Wall -O2 -fPIC -I/usr/include/lua$(LUA_VER)
LFLAGS = -shared -llmdb
lmdb.so: lmdb.o
diff --git a/lmdb.c b/lmdb.c
index d85ce4f..41bb2cf 100644
--- a/lmdb.c
+++ b/lmdb.c
@@ -26,6 +26,10 @@ struct handle {
luaL_error(L, "%s", mdb_strerror(__res)); \
} while (0)
+static void get_parent(lua_State *L, int index);
+static void set_parent(lua_State *L, int index);
+
+
static void check_valid(lua_State *L, struct handle *h) {
if (h->closed) luaL_error(L, "attempt to use expired handle");
}
@@ -49,6 +53,14 @@ static int version(lua_State *L) {
return 3;
}
+#ifdef LUA_5_1
+lua_Integer lua_tointegerx(lua_State *L, int index, int *isnum) {
+ if (isnum != NULL)
+ *isnum = lua_isnumber(L,index);
+ return lua_tointeger(L, index);
+}
+#endif
+
static int env_open(lua_State *L) {
lua_settop(L, 2);
luaL_argcheck(L, lua_isstring(L, 1), 1, "expected string");
@@ -118,7 +130,7 @@ static int env_copy(lua_State *L) {
static MDB_env *get_env(lua_State *L, int idx) {
lua_pushvalue(L, idx);
struct handle *ud = NULL;
- while (lua_getuservalue(L, -1) == LUA_TUSERDATA) {
+ while (get_parent(L, -1), lua_type(L, -1) == LUA_TUSERDATA) {
ud = lua_touserdata(L, -1);
if (ud->closed) return NULL;
check_valid(L, ud);
@@ -161,7 +173,7 @@ static int txn_begin(lua_State *L, bool nested) {
lua_setmetatable(L, -2);
// store the supplied transaction/env as the parent
lua_pushvalue(L, 1);
- lua_setuservalue(L, -2);
+ set_parent(L, -2);
ud->has_child = true;
return 1;
@@ -185,7 +197,7 @@ static int txn_abort(lua_State *L) {
mdb_txn_abort(ud->obj);
ud->closed = true;
- lua_getuservalue(L, 1);
+ get_parent(L, 1);
struct handle *pud = lua_touserdata(L, -1);
pud->has_child = false;
@@ -200,7 +212,7 @@ static int txn_commit(lua_State *L) {
check_env(L, 1);
ud->closed = true;
- lua_getuservalue(L, 1);
+ get_parent(L, 1);
struct handle *pud = lua_touserdata(L, -1);
pud->has_child = false;
@@ -225,7 +237,7 @@ static int db_open(lua_State *L) {
lua_setmetatable(L, -2);
// transaction is parent of DB handle
lua_pushvalue(L, 1);
- lua_setuservalue(L, -2);
+ set_parent(L, -2);
return 1;
}
@@ -245,7 +257,7 @@ static int db_get(lua_State *L) {
check_env(L, 1);
luaL_argcheck(L, lua_isstring(L, 2), 2, "expected string");
- lua_getuservalue(L, 1);
+ get_parent(L, 1);
struct handle *tud = lua_touserdata(L, -1);
MDB_val key = toval(L, 2);
MDB_val data;
@@ -266,7 +278,7 @@ static int db_put(lua_State *L) {
luaL_argcheck(
L, lua_isnil(L, 3) || lua_isstring(L, 3), 3, "expected string or nil");
- lua_getuservalue(L, 1);
+ get_parent(L, 1);
struct handle *tud = lua_touserdata(L, -1);
MDB_val key = toval(L, 2);
if (!lua_isnil(L, 3)) {
@@ -283,7 +295,7 @@ static int db_next(lua_State *L) {
luaL_argcheck(
L, lua_isnil(L, 2) || lua_isstring(L, 2), 2, "expected string or nil");
- lua_getuservalue(L, 1);
+ get_parent(L, 1);
struct handle *tud = lua_touserdata(L, -1);
MDB_cursor *curs;
asserr(mdb_cursor_open(tud->obj, dbi, &curs));
@@ -370,7 +382,11 @@ static const struct luaL_Reg lmdb_db[] = {
static void mt(lua_State *L, const char *name, const struct luaL_Reg l[]) {
luaL_newmetatable(L, name);
+#ifdef LUA_5_1
+ luaL_register(L, NULL, l);
+#else
luaL_setfuncs(L, l, 0);
+#endif
lua_getfield(L, -1, "__index");
if (lua_isnil(L, -1)){
lua_pop(L, 1);
@@ -379,11 +395,47 @@ static void mt(lua_State *L, const char *name, const struct luaL_Reg l[]) {
lua_pop(L, 2);
}
+static void parentmap(lua_State *L) {
+ lua_getfield(L, LUA_REGISTRYINDEX, "lmdb.parentmap");
+}
+
+static void get_parent(lua_State *L, int index) {
+ lua_pushvalue(L, index); // k ... k
+ parentmap(L); // k ... k t
+ lua_insert(L, -2); // k ... t k
+ lua_gettable(L, -2); // k ... t v
+ lua_remove(L, -2); // k ... v
+}
+static void set_parent(lua_State *L, int index) {
+ // references to `index` need to be before anything changes the stack,
+ // otherwise indices will be off
+ // k ... v
+ lua_pushvalue(L, index); // k ... v k
+ parentmap(L); // k ... v k t
+ lua_insert(L, -3); // k ... t v k
+ lua_insert(L, -2); // k ... t k v
+ lua_settable(L, -3); // k ... t
+ lua_pop(L, 1); // k ...
+}
+
+
int luaopen_lmdb(lua_State *L) {
mt(L, "lmdb.env", lmdb_env);
mt(L, "lmdb.txn", lmdb_txn);
mt(L, "lmdb.db", lmdb_db);
+ lua_newtable(L);
+ lua_newtable(L);
+ lua_pushliteral(L, "k");
+ lua_setfield(L, -2, "__mode");
+ lua_setmetatable(L, -2);
+ lua_setfield(L, LUA_REGISTRYINDEX, "lmdb.parentmap");
+
+#ifdef LUA_5_1
+ lua_newtable(L);
+ luaL_register(L, NULL, lmdb);
+#else
luaL_newlib(L, lmdb);
+#endif
return 1;
}