diff options
author | Rob Kendrick (humdrum) <rjek@rjek.com> | 2013-11-06 16:13:17 +0000 |
---|---|---|
committer | Rob Kendrick (humdrum) <rjek@rjek.com> | 2013-11-06 16:13:17 +0000 |
commit | cbb83bbca88eb1795a82f5e53848ef1d7416d1dc (patch) | |
tree | a332314f43de697c849a26e4a0b4b5cc82e27e54 | |
parent | 783952fa4ea3b8144bb7c11ec08a891f756330f9 (diff) | |
download | luxio-cbb83bbca88eb1795a82f5e53848ef1d7416d1dc.tar.bz2 |
iconv
-rw-r--r-- | luxio.c | 96 |
1 files changed, 88 insertions, 8 deletions
@@ -41,6 +41,7 @@ #include <limits.h> #include <signal.h> #include <syslog.h> +#include <iconv.h> #ifdef HAVE_SENDFILE # include <sys/sendfile.h> @@ -912,7 +913,7 @@ luxio_symlink(lua_State *L) /* POSIX.1-2001, Unknown location */ lua_pushinteger(L, symlink(oldpath, newpath)); lua_pushinteger(L, errno); - + return 2; } @@ -1813,12 +1814,12 @@ static int luxio__mq_tostring(lua_State *L) { char buf[NAME_MAX + 64]; - + struct luxio_mq_data *m = luaL_checkudata(L, 1, LUXIO_MQ_METATABLE_NAME); - + sprintf(buf, "<mq %p %s>", (void *)(intptr_t)m->mq, m->name); - + lua_pushstring(L, buf); return 1; } @@ -1850,7 +1851,7 @@ luxio_mq_open(lua_State *L) /* 15.2.1 */ if (mq == (mqd_t)-1) { lua_pushnumber(L, -1); lua_pushinteger(L, errno); - + return 2; } @@ -2856,7 +2857,7 @@ luxio_timeval_tostring(lua_State *L) snprintf(buffer, LUXIO_TIME_BUFLEN, "timeval: %ld.%06ld", (long)a->tv_sec, (long)a->tv_usec); - + lua_pushstring(L, buffer); return 1; @@ -3018,7 +3019,7 @@ luxio_openlog(lua_State *L) int option = luaL_checkint(L, 2); int facility = luaL_checkint(L, 3); - /* openlog doesn't make its own copy of ident + /* openlog doesn't make its own copy of ident * and lua could garbage collect ident * so take a copy of ident */ @@ -3074,6 +3075,80 @@ luxio_LOG_MASK(lua_State *L) return 1; } +static int +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); + + if (r == (iconv_t)-1) { + lua_pushnumber(L, -1); + lua_pushnumber(L, errno); + return 2; + } else { + lua_pushlightuserdata(L, (void *)r); + return 1; + } +} + +static int +luxio_iconv_close(lua_State *L) +{ + iconv_t c = (iconv_t)lua_touserdata(L, 1); + + if (iconv_close(c) == -1) { + lua_pushnumber(L, -1); + } else { + lua_pushnumber(L, 0); + } + + lua_pushnumber(L, errno); + return 2; +} + +#define ICONV_BUF_SIZE 256 + +static int +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); + size_t ibleft; + char *inbuf = (char* )luaL_checklstring(L, 2, &ibleft); + char outbufs[ICONV_BUF_SIZE]; + char *outbuf = outbufs; + size_t obleft = ICONV_BUF_SIZE; + size_t ret = -1; + + luaL_Buffer b; + luaL_buffinit(L, &b); + + do { + ret = iconv(cd, &inbuf, &ibleft, &outbuf, &obleft); + if (ret == (size_t)(-1)) { + luaL_addlstring(&b, outbufs, ICONV_BUF_SIZE - obleft); + + if (errno == E2BIG) { + obleft = ICONV_BUF_SIZE; + outbuf = outbufs; + } else { + lua_pushnumber(L, -1); + lua_pushnumber(L, errno); + luaL_pushresult(&b); + return 3; + } + } + } while (ret == (size_t)-1); + + luaL_addlstring(&b, outbufs, ICONV_BUF_SIZE - obleft); + luaL_pushresult(&b); + return 1; +} + +#undefine ICONV_BUF_SIZE + static const struct luaL_Reg luxio_functions[] = { { "open", luxio_open }, @@ -3233,13 +3308,18 @@ luxio_functions[] = { { "mq_send", luxio_mq_send }, { "mq_receive", luxio_mq_receive }, { "mq_setattr", luxio_mq_setattr }, - { "mq_getattr", luxio_mq_getattr }, + { "mq_getattr", luxio_mq_getattr }, #endif { "openlog", luxio_openlog }, { "syslog", luxio_syslog }, { "closelog", luxio_closelog }, { "setlogmask", luxio_setlogmask }, { "LOG_MASK", luxio_LOG_MASK }, + + { "iconv_open", luxio_iconv_open }, + { "iconv_close", luxio_iconv_close }, + { "iconv", luxio_iconv }, + { NULL, NULL } }; |