diff options
Diffstat (limited to 'luxio.c')
-rw-r--r-- | luxio.c | 65 |
1 files changed, 58 insertions, 7 deletions
@@ -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]; |