summaryrefslogtreecommitdiff
path: root/luxio.c
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2016-09-05 22:15:51 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2016-09-05 22:15:51 +0100
commitd6e186bad3aa0641091dd37d361be02ce7001a3c (patch)
treef356f4c9aa95ced5fed3aa02f2133273d8c6539a /luxio.c
parent64c2eac157d1f60f759b1976c9df084e197e6877 (diff)
downloadluxio-d6e186bad3aa0641091dd37d361be02ce7001a3c.tar.bz2
Ensure iconv contexts get cleaned up, also test it
Diffstat (limited to 'luxio.c')
-rw-r--r--luxio.c65
1 files changed, 58 insertions, 7 deletions
diff --git a/luxio.c b/luxio.c
index 043716f..c1566cd 100644
--- a/luxio.c
+++ b/luxio.c
@@ -3703,6 +3703,51 @@ luxio_LOG_MASK(lua_State *L)
return 1;
}
+/*** Character set conversion.
+@section iconv
+*/
+
+#define LUXIO_ICONV_METATABLE "luxio.iconv"
+
+static int
+luxio__iconv_gc(lua_State *L)
+{
+ iconv_t *ic = (iconv_t*)(lua_touserdata(L, 1));
+ if (*ic != NULL && *ic != (iconv_t)(-1)) {
+ iconv_close(*ic);
+ *ic = NULL;
+ }
+ return 0;
+}
+
+static int
+luxio__iconv_tostring(lua_State *L)
+{
+ iconv_t *ic = (iconv_t*)(lua_touserdata(L, 1));
+ lua_pushfstring(L, "<iconv %p>", *ic);
+ return 1;
+}
+
+static iconv_t*
+luxio__create_iconv(lua_State *L)
+{
+ iconv_t *r = lua_newuserdata(L, sizeof(iconv_t));
+ int create = luaL_newmetatable(L, LUXIO_ICONV_METATABLE);
+
+ if (create != 0) {
+ lua_pushcfunction(L, luxio__iconv_gc);
+ lua_setfield(L, -2, "__gc");
+ lua_pushcfunction(L, luxio__iconv_tostring);
+ lua_setfield(L, -2, "__tostring");
+ }
+
+ *r = NULL;
+
+ lua_setmetatable(L, -2);
+
+ return r;
+}
+
/*** Allocate descriptor for character set conversion.
@tparam string tocode
@tparam string fromcode
@@ -3715,16 +3760,18 @@ luxio_iconv_open(lua_State *L)
{
const char *tocode = luaL_checkstring(L, 1);
const char *fromcode = luaL_checkstring(L, 2);
- iconv_t r = iconv_open(tocode, fromcode);
+ iconv_t *r = luxio__create_iconv(L);
- if (r == (iconv_t)-1) {
+ *r = iconv_open(tocode, fromcode);
+
+ if (*r == (iconv_t)-1) {
lua_pushnumber(L, -1);
lua_pushnumber(L, errno);
return 2;
- } else {
- lua_pushlightuserdata(L, (void *)r);
- return 1;
}
+
+ /* On the top of the stack is the iconv userdata */
+ return 1;
}
/*** Close a previously-allocated iconv descriptor.
@@ -3736,7 +3783,10 @@ luxio_iconv_open(lua_State *L)
static int
luxio_iconv_close(lua_State *L)
{
- iconv_t c = (iconv_t)lua_touserdata(L, 1);
+ iconv_t *_c = (iconv_t*)lua_touserdata(L, 1);
+ iconv_t c = *_c;
+
+ *_c = NULL;
if (iconv_close(c) == -1) {
lua_pushnumber(L, -1);
@@ -3763,7 +3813,8 @@ luxio_iconv(lua_State *L)
{
/* based on Alexandre Erwin Ittner <alexandre@ittner.com.br>'s code */
/* either returns completed string, or -1, errno, partial result */
- iconv_t cd = (iconv_t)lua_touserdata(L, 1);
+ iconv_t *_cd = (iconv_t*)lua_touserdata(L, 1);
+ iconv_t cd = *_cd;
size_t ibleft;
char *inbuf = (char* )luaL_checklstring(L, 2, &ibleft);
char outbufs[ICONV_BUF_SIZE];