summaryrefslogtreecommitdiff
path: root/luxio.c
diff options
context:
space:
mode:
Diffstat (limited to 'luxio.c')
-rw-r--r--luxio.c96
1 files changed, 88 insertions, 8 deletions
diff --git a/luxio.c b/luxio.c
index 61ac0d6..d3f79b2 100644
--- a/luxio.c
+++ b/luxio.c
@@ -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 }
};