From 85bf3b798f6d52c374c35f7fbe47df132891d3b2 Mon Sep 17 00:00:00 2001 From: Mark Pulford Date: Fri, 30 Dec 2011 17:48:12 +1030 Subject: Add support for Lua 5.2 and cjson.new Update all Lua scripts to use new module init style everywhere: local json = require "cjson" Lua CJSON does not register a global table under Lua 5.2. The global table can be disabled under Lua 5.1 with DISABLE_CJSON_GLOBAL. Other changes: - Store CJSON configuration as an upvalue for each function. - Add "cjson.new" function to create another module table with a separate configuration. - Add _NAME and _VERSION variables. --- lua_cjson.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 16 deletions(-) (limited to 'lua_cjson.c') diff --git a/lua_cjson.c b/lua_cjson.c index 8e9b237..be5cdc2 100644 --- a/lua_cjson.c +++ b/lua_cjson.c @@ -45,6 +45,10 @@ #include "strbuf.h" #include "fpconv.h" +#ifndef CJSON_MODNAME +#define CJSON_MODNAME "cjson" +#endif + #ifndef CJSON_VERSION #define CJSON_VERSION "1.0devel" #endif @@ -175,22 +179,16 @@ static const char *char2escape[256] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; -static int json_config_key; - /* ===== CONFIGURATION ===== */ static json_config_t *json_fetch_config(lua_State *l) { json_config_t *cfg; - lua_pushlightuserdata(l, &json_config_key); - lua_gettable(l, LUA_REGISTRYINDEX); - cfg = lua_touserdata(l, -1); + cfg = lua_touserdata(l, lua_upvalueindex(1)); if (!cfg) luaL_error(l, "BUG: Unable to fetch CJSON configuration"); - lua_pop(l, 1); - return cfg; } @@ -1246,7 +1244,27 @@ static int json_decode(lua_State *l) /* ===== INITIALISATION ===== */ -int luaopen_cjson(lua_State *l) +#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502 +/* Compatibility for Lua 5.1. + * + * luaL_setfuncs() is used to create a module table where the functions have + * json_config_t as their first upvalue. Code borrowed from Lua 5.2 source. */ +static void luaL_setfuncs (lua_State *l, const luaL_Reg *reg, int nup) +{ + int i; + + luaL_checkstack(l, nup, "too many upvalues"); + for (; reg->name != NULL; reg++) { /* fill the table with given functions */ + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(l, -nup); + lua_pushcclosure(l, reg->func, nup); /* closure with those upvalues */ + lua_setfield(l, -(nup + 2), reg->name); + } + lua_pop(l, nup); /* remove upvalues */ +} +#endif + +static int lua_cjson_new(lua_State *l) { luaL_Reg reg[] = { { "encode", json_encode }, @@ -1257,28 +1275,51 @@ int luaopen_cjson(lua_State *l) { "encode_keep_buffer", json_cfg_encode_keep_buffer }, { "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers }, { "update_locale", json_update_locale }, + { "new", lua_cjson_new }, { NULL, NULL } }; - /* Update the current locale for g_fmt/strtod */ + /* Update the current locale for g_fmt/strtod. + * Using different locales per-thread is not supported. */ fpconv_update_locale(); - /* Use json_config_key as a pointer. - * It's faster than using a config string, and more unique */ - lua_pushlightuserdata(l, &json_config_key); - json_create_config(l); - lua_settable(l, LUA_REGISTRYINDEX); + /* cjson module table */ + lua_newtable(l); - luaL_register(l, "cjson", reg); + /* Register functions with config data as upvalue */ + json_create_config(l); + luaL_setfuncs(l, reg, 1); /* Set cjson.null */ lua_pushlightuserdata(l, NULL); lua_setfield(l, -2, "null"); - /* Set cjson.version */ + /* Set module name / version fields */ + lua_pushliteral(l, CJSON_MODNAME); + lua_setfield(l, -2, "_NAME"); + lua_pushliteral(l, CJSON_VERSION); + lua_setfield(l, -2, "_VERSION"); lua_pushliteral(l, CJSON_VERSION); lua_setfield(l, -2, "version"); + return 1; +} + +int luaopen_cjson(lua_State *l) +{ + lua_cjson_new(l); + +#if !defined(DISABLE_CJSON_GLOBAL) && (!defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502) + /* Register a global "cjson" table to maintain compatibility with earlier + * versions of Lua CJSON which used luaL_register() under Lua 5.1. + * + * From Lua 5.2 onwards, Lua CJSON does not automatically register a global + * table. + */ + lua_pushvalue(l, -1); + lua_setglobal(l, CJSON_MODNAME); +#endif + /* Return cjson table */ return 1; } -- cgit v1.2.3-55-g6feb