aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Pulford <mark@kyne.com.au>2011-12-30 17:48:12 +1030
committerMark Pulford <mark@kyne.com.au>2011-12-30 17:48:12 +1030
commit85bf3b798f6d52c374c35f7fbe47df132891d3b2 (patch)
tree39b0da8e6d6536cdd90038547a985559102962de
parent2416b145073211b840781da6abf4b6d97f4657a6 (diff)
downloadlua-cjson-85bf3b798f6d52c374c35f7fbe47df132891d3b2.tar.gz
lua-cjson-85bf3b798f6d52c374c35f7fbe47df132891d3b2.tar.bz2
lua-cjson-85bf3b798f6d52c374c35f7fbe47df132891d3b2.zip
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.
-rw-r--r--Makefile3
-rw-r--r--lua_cjson.c73
-rw-r--r--manual.txt61
-rwxr-xr-xtests/bench.lua2
-rw-r--r--tests/common.lua6
-rwxr-xr-xtests/decode.lua4
-rwxr-xr-xtests/encode.lua4
-rwxr-xr-xtests/test.lua16
8 files changed, 122 insertions, 47 deletions
diff --git a/Makefile b/Makefile
index fb63d99..c9343f9 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,8 @@ LUA_VERSION = 5.1
2 2
3## Available defines for CJSON_CFLAGS 3## Available defines for CJSON_CFLAGS
4# 4#
5# USE_INTERNAL_ISINF: Workaround for Solaris platforms missing isinf(). 5# USE_INTERNAL_ISINF: Workaround for Solaris platforms missing isinf().
6# DISABLE_CJSON_GLOBAL: Do not store module is "cjson" global
6 7
7## Build defaults 8## Build defaults
8PREFIX = /usr/local 9PREFIX = /usr/local
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 @@
45#include "strbuf.h" 45#include "strbuf.h"
46#include "fpconv.h" 46#include "fpconv.h"
47 47
48#ifndef CJSON_MODNAME
49#define CJSON_MODNAME "cjson"
50#endif
51
48#ifndef CJSON_VERSION 52#ifndef CJSON_VERSION
49#define CJSON_VERSION "1.0devel" 53#define CJSON_VERSION "1.0devel"
50#endif 54#endif
@@ -175,22 +179,16 @@ static const char *char2escape[256] = {
175 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 179 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
176}; 180};
177 181
178static int json_config_key;
179
180/* ===== CONFIGURATION ===== */ 182/* ===== CONFIGURATION ===== */
181 183
182static json_config_t *json_fetch_config(lua_State *l) 184static json_config_t *json_fetch_config(lua_State *l)
183{ 185{
184 json_config_t *cfg; 186 json_config_t *cfg;
185 187
186 lua_pushlightuserdata(l, &json_config_key); 188 cfg = lua_touserdata(l, lua_upvalueindex(1));
187 lua_gettable(l, LUA_REGISTRYINDEX);
188 cfg = lua_touserdata(l, -1);
189 if (!cfg) 189 if (!cfg)
190 luaL_error(l, "BUG: Unable to fetch CJSON configuration"); 190 luaL_error(l, "BUG: Unable to fetch CJSON configuration");
191 191
192 lua_pop(l, 1);
193
194 return cfg; 192 return cfg;
195} 193}
196 194
@@ -1246,7 +1244,27 @@ static int json_decode(lua_State *l)
1246 1244
1247/* ===== INITIALISATION ===== */ 1245/* ===== INITIALISATION ===== */
1248 1246
1249int luaopen_cjson(lua_State *l) 1247#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502
1248/* Compatibility for Lua 5.1.
1249 *
1250 * luaL_setfuncs() is used to create a module table where the functions have
1251 * json_config_t as their first upvalue. Code borrowed from Lua 5.2 source. */
1252static void luaL_setfuncs (lua_State *l, const luaL_Reg *reg, int nup)
1253{
1254 int i;
1255
1256 luaL_checkstack(l, nup, "too many upvalues");
1257 for (; reg->name != NULL; reg++) { /* fill the table with given functions */
1258 for (i = 0; i < nup; i++) /* copy upvalues to the top */
1259 lua_pushvalue(l, -nup);
1260 lua_pushcclosure(l, reg->func, nup); /* closure with those upvalues */
1261 lua_setfield(l, -(nup + 2), reg->name);
1262 }
1263 lua_pop(l, nup); /* remove upvalues */
1264}
1265#endif
1266
1267static int lua_cjson_new(lua_State *l)
1250{ 1268{
1251 luaL_Reg reg[] = { 1269 luaL_Reg reg[] = {
1252 { "encode", json_encode }, 1270 { "encode", json_encode },
@@ -1257,28 +1275,51 @@ int luaopen_cjson(lua_State *l)
1257 { "encode_keep_buffer", json_cfg_encode_keep_buffer }, 1275 { "encode_keep_buffer", json_cfg_encode_keep_buffer },
1258 { "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers }, 1276 { "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers },
1259 { "update_locale", json_update_locale }, 1277 { "update_locale", json_update_locale },
1278 { "new", lua_cjson_new },
1260 { NULL, NULL } 1279 { NULL, NULL }
1261 }; 1280 };
1262 1281
1263 /* Update the current locale for g_fmt/strtod */ 1282 /* Update the current locale for g_fmt/strtod.
1283 * Using different locales per-thread is not supported. */
1264 fpconv_update_locale(); 1284 fpconv_update_locale();
1265 1285
1266 /* Use json_config_key as a pointer. 1286 /* cjson module table */
1267 * It's faster than using a config string, and more unique */ 1287 lua_newtable(l);
1268 lua_pushlightuserdata(l, &json_config_key);
1269 json_create_config(l);
1270 lua_settable(l, LUA_REGISTRYINDEX);
1271 1288
1272 luaL_register(l, "cjson", reg); 1289 /* Register functions with config data as upvalue */
1290 json_create_config(l);
1291 luaL_setfuncs(l, reg, 1);
1273 1292
1274 /* Set cjson.null */ 1293 /* Set cjson.null */
1275 lua_pushlightuserdata(l, NULL); 1294 lua_pushlightuserdata(l, NULL);
1276 lua_setfield(l, -2, "null"); 1295 lua_setfield(l, -2, "null");
1277 1296
1278 /* Set cjson.version */ 1297 /* Set module name / version fields */
1298 lua_pushliteral(l, CJSON_MODNAME);
1299 lua_setfield(l, -2, "_NAME");
1300 lua_pushliteral(l, CJSON_VERSION);
1301 lua_setfield(l, -2, "_VERSION");
1279 lua_pushliteral(l, CJSON_VERSION); 1302 lua_pushliteral(l, CJSON_VERSION);
1280 lua_setfield(l, -2, "version"); 1303 lua_setfield(l, -2, "version");
1281 1304
1305 return 1;
1306}
1307
1308int luaopen_cjson(lua_State *l)
1309{
1310 lua_cjson_new(l);
1311
1312#if !defined(DISABLE_CJSON_GLOBAL) && (!defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502)
1313 /* Register a global "cjson" table to maintain compatibility with earlier
1314 * versions of Lua CJSON which used luaL_register() under Lua 5.1.
1315 *
1316 * From Lua 5.2 onwards, Lua CJSON does not automatically register a global
1317 * table.
1318 */
1319 lua_pushvalue(l, -1);
1320 lua_setglobal(l, CJSON_MODNAME);
1321#endif
1322
1282 /* Return cjson table */ 1323 /* Return cjson table */
1283 return 1; 1324 return 1;
1284} 1325}
diff --git a/manual.txt b/manual.txt
index a3e12cf..810d3d1 100644
--- a/manual.txt
+++ b/manual.txt
@@ -16,8 +16,6 @@ Lua CJSON provides fast JSON parsing and encoding support for Lua.
16 16
17.Caveats 17.Caveats
18- UTF-16 and UTF-32 are not supported. 18- UTF-16 and UTF-32 are not supported.
19- Multi-threading within a single Lua state is not supported
20 (+lua_lock+ / +lua_unlock+).
21 19
22Lua CJSON is covered by the MIT license. Review the file +LICENSE+ for 20Lua CJSON is covered by the MIT license. Review the file +LICENSE+ for
23details. 21details.
@@ -32,7 +30,7 @@ comments.
32Installation Methods 30Installation Methods
33-------------------- 31--------------------
34 32
35Lua CJSON requires either http://www.lua.org[Lua] or 33Lua CJSON requires either http://www.lua.org[Lua] 5.1, Lua 5.2, or
36http://www.luajit.org[LuaJIT] to build. 34http://www.luajit.org[LuaJIT] to build.
37 35
38There are 4 build methods available: 36There are 4 build methods available:
@@ -44,11 +42,13 @@ RPM:: Linux
44LuaRocks:: Unix, Windows 42LuaRocks:: Unix, Windows
45 43
46 44
47Build options (#define) 45Build Options (#define)
48~~~~~~~~~~~~~~~~~~~~~~~ 46~~~~~~~~~~~~~~~~~~~~~~~
49 47
50[horizontal] 48[horizontal]
51USE_INTERNAL_ISINF:: Workaround for Solaris platforms missing isinf(). 49USE_INTERNAL_ISINF:: Workaround for Solaris platforms missing isinf().
50DISABLE_CJSON_GLOBAL:: Do not store module table in global "cjson"
51 variable.
52 52
53 53
54Make 54Make
@@ -125,9 +125,9 @@ Synopsis
125 125
126[source,lua] 126[source,lua]
127------------ 127------------
128require "cjson" 128-- Module initalisation methods
129-- Or:
130local cjson = require "cjson" 129local cjson = require "cjson"
130local cjson2 = cjson.new()
131 131
132-- Translate Lua value to/from JSON 132-- Translate Lua value to/from JSON
133text = cjson.encode(value) 133text = cjson.encode(value)
@@ -141,6 +141,34 @@ keep = cjson.encode_keep_buffer([keep])
141------------ 141------------
142 142
143 143
144Module Instantiation
145~~~~~~~~~~~~~~~~~~~~
146
147[source,lua]
148------------
149local cjson = require "cjson"
150local cjson2 = cjson.new()
151------------
152
153Lua CJSON can be loaded via +require+. A global +cjson+ table is
154registered under Lua 5.1 to maintain backward compatibility. Lua CJSON
155does not register a global table under Lua 5.2 since this practice is
156discouraged.
157
158+cjson.new+ can be used to instantiate an independent copy of the Lua
159CJSON module. The new module has a separate persistent encoding
160buffer, and default settings.
161
162Lua CJSON can support Lua implementations using multiple pre-emptive
163threads within a single Lua state provided the persistent encoding
164buffer is not shared. This can be achieved by one of the following
165methods:
166
167- Disabling the persistent encoding buffer with +encode_keep_buffer+.
168- Ensuring only a single thread calls +encode+ at a time.
169- Using a separate +cjson+ instantiation per pre-emptive thread.
170
171
144decode 172decode
145~~~~~~ 173~~~~~~
146 174
@@ -423,6 +451,18 @@ Disabled for decoding:: All numbers supported by +strtod+(3) will be parsed.
423API (Variables) 451API (Variables)
424--------------- 452---------------
425 453
454_NAME
455~~~~~
456
457The name of the Lua CJSON module (+"cjson"+).
458
459
460_VERSION
461~~~~~~~~
462
463The version number of the Lua CJSON module (Eg, +"1.0devel"+).
464
465
426null 466null
427~~~~ 467~~~~
428 468
@@ -430,13 +470,6 @@ Lua CJSON decodes JSON +null+ as a Lua +lightuserdata+ NULL pointer.
430+cjson.null+ is provided for comparison. 470+cjson.null+ is provided for comparison.
431 471
432 472
433version
434~~~~~~~
435
436The version number of the Lua CJSON module in use can be found in
437+cjson.version+.
438
439
440[sect1] 473[sect1]
441References 474References
442---------- 475----------
@@ -445,4 +478,4 @@ References
445- http://www.json.org/[JSON website] 478- http://www.json.org/[JSON website]
446 479
447 480
448// vi:tw=70: 481// vi:ft=asciidoc tw=70:
diff --git a/tests/bench.lua b/tests/bench.lua
index fdd0bb0..c81213d 100755
--- a/tests/bench.lua
+++ b/tests/bench.lua
@@ -72,7 +72,7 @@ function bench_file(filename)
72 return benchmark(tests, 0.1, 5) 72 return benchmark(tests, 0.1, 5)
73end 73end
74 74
75cjson.encode_keep_buffer(true) 75json.encode_keep_buffer(true)
76 76
77for i = 1, #arg do 77for i = 1, #arg do
78 local results = bench_file(arg[i]) 78 local results = bench_file(arg[i])
diff --git a/tests/common.lua b/tests/common.lua
index f3dc6f7..7472a10 100644
--- a/tests/common.lua
+++ b/tests/common.lua
@@ -1,4 +1,4 @@
1require "cjson" 1local json = require "cjson"
2 2
3-- Misc routines to assist with CJSON testing 3-- Misc routines to assist with CJSON testing
4-- 4--
@@ -77,8 +77,8 @@ function serialise_value(value, indent, depth)
77 if indent == nil then indent = "" end 77 if indent == nil then indent = "" end
78 if depth == nil then depth = 0 end 78 if depth == nil then depth = 0 end
79 79
80 if value == cjson.null then 80 if value == json.null then
81 return "cjson.null" 81 return "json.null"
82 elseif type(value) == "string" then 82 elseif type(value) == "string" then
83 return string.format("%q", value) 83 return string.format("%q", value)
84 elseif type(value) == "nil" or type(value) == "number" or 84 elseif type(value) == "nil" or type(value) == "number" or
diff --git a/tests/decode.lua b/tests/decode.lua
index cac29e6..89354cd 100755
--- a/tests/decode.lua
+++ b/tests/decode.lua
@@ -7,8 +7,8 @@
7-- ./decode.lua test.json 7-- ./decode.lua test.json
8 8
9require "common" 9require "common"
10require "cjson" 10local json = require "cjson"
11 11
12local json_text = file_load(arg[1]) 12local json_text = file_load(arg[1])
13local t = cjson.decode(json_text) 13local t = json.decode(json_text)
14print(serialise_value(t)) 14print(serialise_value(t))
diff --git a/tests/encode.lua b/tests/encode.lua
index f13787c..a8d749a 100755
--- a/tests/encode.lua
+++ b/tests/encode.lua
@@ -7,7 +7,7 @@
7-- ./encode.lua lua_data.lua 7-- ./encode.lua lua_data.lua
8 8
9require "common" 9require "common"
10require "cjson" 10local json = require "cjson"
11 11
12function get_lua_table(file) 12function get_lua_table(file)
13 local func = loadstring("data = " .. file_load(file)) 13 local func = loadstring("data = " .. file_load(file))
@@ -23,6 +23,6 @@ function get_lua_table(file)
23end 23end
24 24
25local t = get_lua_table(arg[1]) 25local t = get_lua_table(arg[1])
26print(cjson.encode(t)) 26print(json.encode(t))
27 27
28-- vi:ai et sw=4 ts=4: 28-- vi:ai et sw=4 ts=4:
diff --git a/tests/test.lua b/tests/test.lua
index bdae6ea..99ac73a 100755
--- a/tests/test.lua
+++ b/tests/test.lua
@@ -112,8 +112,8 @@ local decode_numeric_tests = {
112 112
113local encode_table_tests = { 113local encode_table_tests = {
114 function() 114 function()
115 cjson.encode_sparse_array(true, 2, 3) 115 json.encode_sparse_array(true, 2, 3)
116 cjson.encode_max_depth(5) 116 json.encode_max_depth(5)
117 return "Setting sparse array (true, 2, 3) / max depth (5)" 117 return "Setting sparse array (true, 2, 3) / max depth (5)"
118 end, 118 end,
119 { json.encode, { { [3] = "sparse test" } }, 119 { json.encode, { { [3] = "sparse test" } },
@@ -211,19 +211,19 @@ local escape_tests = {
211local locale_tests = { 211local locale_tests = {
212 function () 212 function ()
213 os.setlocale("cs_CZ") 213 os.setlocale("cs_CZ")
214 cjson.update_locale() 214 json.update_locale()
215 return "Setting locale to cs_CZ (comma separator)" 215 return "Setting locale to cs_CZ (comma separator)"
216 end, 216 end,
217 { json.encode, { 1.5 }, true, { '1.5' } }, 217 { json.encode, { 1.5 }, true, { '1.5' } },
218 { json.decode, { "[ 10, \"test\" ]" }, true, { { 10, "test" } } }, 218 { json.decode, { "[ 10, \"test\" ]" }, true, { { 10, "test" } } },
219 function () 219 function ()
220 os.setlocale("C") 220 os.setlocale("C")
221 cjson.update_locale() 221 json.update_locale()
222 return "Reverting locale to POSIX" 222 return "Reverting locale to POSIX"
223 end 223 end
224} 224}
225 225
226print(string.format("Testing Lua CJSON version %s\n", cjson.version)) 226print(string.format("Testing Lua CJSON version %s\n", json.version))
227 227
228run_test_group("decode simple value", decode_simple_tests) 228run_test_group("decode simple value", decode_simple_tests)
229run_test_group("encode simple value", encode_simple_tests) 229run_test_group("encode simple value", encode_simple_tests)
@@ -232,7 +232,7 @@ run_test_group("decode numeric", decode_numeric_tests)
232-- INCLUDE: 232-- INCLUDE:
233-- - Sparse array exception.. 233-- - Sparse array exception..
234-- - .. 234-- - ..
235-- cjson.encode_sparse_array(true, 2, 3) 235-- json.encode_sparse_array(true, 2, 3)
236 236
237run_test_group("encode table", encode_table_tests) 237run_test_group("encode table", encode_table_tests)
238run_test_group("decode error", decode_error_tests) 238run_test_group("decode error", decode_error_tests)
@@ -240,8 +240,8 @@ run_test_group("encode error", encode_error_tests)
240run_test_group("escape", escape_tests) 240run_test_group("escape", escape_tests)
241run_test_group("locale", locale_tests) 241run_test_group("locale", locale_tests)
242 242
243cjson.refuse_invalid_numbers(false) 243json.refuse_invalid_numbers(false)
244cjson.encode_max_depth(20) 244json.encode_max_depth(20)
245for i = 1, #arg do 245for i = 1, #arg do
246 run_test("decode cycle " .. arg[i], test_decode_cycle, { arg[i] }, 246 run_test("decode cycle " .. arg[i], test_decode_cycle, { arg[i] },
247 true, { true }) 247 true, { true })