lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Also I have written a small PHP serializer for Lua, but it is my first
Lua extension in C, so I am not sure the code is perfect, I would
appreciate if others could have a look and tell me if there is
anything wrong. I am using it with Tokyo Tyrant in order to make Lua
speak with PHP in without too much burden. It doesn't unserialize
because I don't need this yet...

#include <stdio.h>
#include <string.h>
#include <lauxlib.h>

static void l_phpserz_serialize_value(lua_State *L, int pos, luaL_Buffer *B) {
  switch (lua_type(L, pos)) {
  case LUA_TNIL:
		luaL_addstring(B, "N;");
    break;
  case LUA_TNUMBER: {
    const char *num;
    lua_pushvalue(L, pos);
    num = lua_tostring(L, -1);
		if (strcmp(num, "-inf") == 0) {
			luaL_addstring(B, "d:-INF;");
		}
		else if (strcmp(num, "inf") == 0) {
			luaL_addstring(B, "d:INF;");
		}
		else if (strchr(num, '.') != NULL) {
      luaL_addlstring(B, "d:", 2);
			luaL_addstring(B, num);
      luaL_addlstring(B, ";", 1);
		}
		else {
      luaL_addlstring(B, "i:", 2);
			luaL_addstring(B, num);
      luaL_addlstring(B, ";", 1);
		}
		lua_pop(L, 1);
    break;
  }
	case LUA_TBOOLEAN:
		if (lua_toboolean(L, pos)) {
			luaL_addstring(B, "b:1;");
		}
		else {
			luaL_addstring(B, "b:0;");
		}
		break;
	case LUA_TSTRING: {
    size_t len;
		const char *str;
    const char *num;
		lua_pushvalue(L, pos); // work on a copy of the string
		str = lua_tolstring(L, -1, &len);
    luaL_addlstring(B, "s:", 2);
    lua_pushnumber(L, len);
    num = lua_tostring(L, -1);
	  luaL_addstring(B, num);
    luaL_addlstring(B, ":\"", 2);
	  luaL_addlstring(B, str, len);
    luaL_addlstring(B, "\";", 2);
		break;
  }
  case LUA_TTABLE: {
    const char *num;
    const char *str;
    int counter = 0;
	  luaL_Buffer TB;
	  luaL_buffinit(L, &TB);
    luaL_addlstring(B, "a:", 2);

    /* table is in the stack at index 'pos' */
    lua_pushnil(L);  /* first key */
    while (lua_next(L, pos) != 0) {
			/* push key-value pair to stack base */
			lua_insert(L, 1);
			lua_insert(L, 1);

	    l_phpserz_serialize_value(L, 1, &TB);
	    l_phpserz_serialize_value(L, 2, &TB);
			/* restore key to stack top */
			lua_pushvalue(L, 1);
			lua_remove(L, 1);
			/* pop value */
			lua_remove(L, 1);
      counter++;
    }
    lua_pushnumber(L, counter);
    num = lua_tostring(L, -1);
	  luaL_addstring(B, num);
    luaL_addlstring(B, ":{", 2);
	  luaL_pushresult(&TB);
    str = lua_tostring(L, -1);
    luaL_addstring(B, str);
    luaL_addlstring(B, "}", 1);
    break;
  }
  default:
		lua_pushstring(L, "Cannot serialize data to php");
		lua_error(L);
  }
}

static int l_phpserz_serialize(lua_State *L) {
	luaL_Buffer B;
	luaL_checkany(L, -1);
	luaL_buffinit(L, &B);
	l_phpserz_serialize_value(L, lua_gettop(L), &B);
	luaL_pushresult(&B);
	return 1;
}

static const struct luaL_Reg phpserzlib[] = {
	{ "serialize", l_phpserz_serialize },
	{ NULL, NULL }
};

int luaopen_phpserz(lua_State *L) {
	luaL_register(L, "phpserz", phpserzlib);
	return 1;
}

This could have been done in Lua directly but I took it as an exercise :)


-- 
Bertrand Mansion
Mamasam