Keep callbacks in an uservalue instead of by reference

Sun, 19 Nov 2017 20:06:07 +0100

author
Kim Alvefur <zash@zash.se>
date
Sun, 19 Nov 2017 20:06:07 +0100
changeset 26
a8caec6c5429
parent 25
8c3a5b827e48
child 27
04cfdac393cc

Keep callbacks in an uservalue instead of by reference

src/lxplib.c file | annotate | diff | comparison | revisions
--- a/src/lxplib.c	Thu Apr 03 14:59:03 2014 +0100
+++ b/src/lxplib.c	Sun Nov 19 20:06:07 2017 +0100
@@ -17,6 +17,10 @@
 
 #include "lxplib.h"
 
+#if (LUA_VERSION_NUM == 501)
+#define lua_getuservalue(L, i) lua_getfenv(L, i)
+#define lua_setuservalue(L, i) lua_setfenv(L, i)
+#endif
 
 #if !defined(lua_pushliteral)
 #define lua_pushliteral(L, s)	\
@@ -35,7 +39,7 @@
 struct lxp_userdata {
   lua_State *L;
   XML_Parser parser;  /* associated expat parser */
-  int tableref;  /* table with callbacks for this parser */
+  int errorref;  /* reference to error message if state is XPSerror */
   enum XPState state;
   luaL_Buffer *b;  /* to concatenate sequences of cdata pieces */
   int bufferCharData; /* whether to buffer cdata pieces */
@@ -58,7 +62,7 @@
 
 static lxp_userdata *createlxp (lua_State *L) {
   lxp_userdata *xpu = (lxp_userdata *)lua_newuserdata(L, sizeof(lxp_userdata));
-  xpu->tableref = LUA_REFNIL;  /* in case of errors... */
+  xpu->errorref = LUA_REFNIL;
   xpu->parser = NULL;
   xpu->L = NULL;
   xpu->state = XPSpre;
@@ -69,8 +73,8 @@
 
 
 static void lxpclose (lua_State *L, lxp_userdata *xpu) {
-  luaL_unref(L, LUA_REGISTRYINDEX, xpu->tableref);
-  xpu->tableref = LUA_REFNIL;
+  luaL_unref(L, LUA_REGISTRYINDEX, xpu->errorref);
+  xpu->errorref = LUA_REFNIL;
   if (xpu->parser)
     XML_ParserFree(xpu->parser);
   xpu->parser = NULL;
@@ -87,8 +91,7 @@
   assert(xpu->state == XPSok);
   if (lua_pcall(L, nargs + 1, nres, 0) != 0) {
     xpu->state = XPSerror;
-    luaL_unref(L, LUA_REGISTRYINDEX, xpu->tableref);
-    xpu->tableref = luaL_ref(L, LUA_REGISTRYINDEX);  /* error message */
+    xpu->errorref = luaL_ref(L, LUA_REGISTRYINDEX);  /* error message */
   }
 }
 
@@ -233,8 +236,8 @@
   child->parser = XML_ExternalEntityParserCreate(p, context, NULL);
   if (!child->parser)
     luaL_error(L, "XML_ParserCreate failed");
-  lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref); /*lua_getref(L, xpu->tableref); */ /* child uses the same table of its father */
-  child->tableref = luaL_ref(L, LUA_REGISTRYINDEX);
+  lua_getuservalue(L, 1);
+  lua_setuservalue(L, -2); /* child uses the same table of its father */
   lua_pushstring(L, base);
   lua_pushstring(L, systemId);
   lua_pushstring(L, publicId);
@@ -391,7 +394,7 @@
   luaL_checktype(L, 1, LUA_TTABLE);
   checkcallbacks(L);
   lua_pushvalue(L, 1);
-  xpu->tableref = luaL_ref(L, LUA_REGISTRYINDEX);
+  lua_setuservalue(L, -2);
   XML_SetUserData(p, xpu);
   if (hasfield(L, StartCdataKey) || hasfield(L, EndCdataKey))
     XML_SetCdataSectionHandler(p, f_StartCdata, f_EndCdataKey);
@@ -457,8 +460,8 @@
 
 
 static int getcallbacks (lua_State *L) {
-  lxp_userdata *xpu = checkparser(L, 1);
-  lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref);
+  checkparser(L, 1);
+  lua_getuservalue(L, 1);
   return 1;
 }
 
@@ -471,11 +474,11 @@
   xpu->state = XPSok;
   xpu->b = &b;
   lua_settop(L, 2);
-  lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref); /*lua_getref(L, xpu->tableref);*/  /* to be used by handlers */
+  getcallbacks(L);
   status = XML_Parse(xpu->parser, s, (int)len, s == NULL);
   if (xpu->state == XPSstring) dischargestring(xpu);
   if (xpu->state == XPSerror) {  /* callback error? */
-    lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->tableref);  /* get original msg. */
+    lua_rawgeti(L, LUA_REGISTRYINDEX, xpu->errorref);  /* get original msg. */
     lua_error(L);
   }
   if (s == NULL) xpu->state = XPSfinished;

mercurial