From fd5d3707dcb9ab82657ca44a618f0ef4e0b5c550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Drahos=CC=8C?= Date: Tue, 5 Mar 2013 15:13:51 +0100 Subject: [PATCH] Imported from 2.2 rock --- dkjson-2.2-1.rockspec | 30 ++ dkjson.lua | 791 ++++++++++++++++++++++++++++++++++++++++++ jsontest.lua | 426 +++++++++++++++++++++++ speedtest.lua | 131 +++++++ versions.txt | 61 ++++ 5 files changed, 1439 insertions(+) create mode 100644 dkjson-2.2-1.rockspec create mode 100644 dkjson.lua create mode 100644 jsontest.lua create mode 100644 speedtest.lua create mode 100644 versions.txt diff --git a/dkjson-2.2-1.rockspec b/dkjson-2.2-1.rockspec new file mode 100644 index 0000000..040e7e1 --- /dev/null +++ b/dkjson-2.2-1.rockspec @@ -0,0 +1,30 @@ +package = "dkjson" +version = "2.2-1" +source = { + url = "http://chiselapp.com/user/dhkolf/repository/dkjson/tarball/dkjson-2.2.tar.gz?uuid=release_2_2", + file = "dkjson-2.2.tar.gz" +} +description = { + summary = "David Kolf's JSON module for Lua", + detailed = [[ +dkjson is a module for encoding and decoding JSON data. It supports UTF-8. + +JSON (JavaScript Object Notation) is a format for serializing data based +on the syntax for JavaScript data structures. + +dkjson is written in Lua without any dependencies, but +when LPeg is available dkjson uses it to speed up decoding. +]], + homepage = "http://chiselapp.com/user/dhkolf/repository/dkjson/", + license = "MIT/X11" +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + dkjson = "dkjson.lua" + } +} + diff --git a/dkjson.lua b/dkjson.lua new file mode 100644 index 0000000..e57e17c --- /dev/null +++ b/dkjson.lua @@ -0,0 +1,791 @@ + -- Module options: + local always_try_using_lpeg = true + + --[==[ + +David Kolf's JSON module for Lua 5.1/5.2 +======================================== + +*Version 2.2* + +This module writes no global values, not even the module table. +Import it using + + json = require ("dkjson") + +Exported functions and values: + +`json.encode (object [, state])` +-------------------------------- + +Create a string representing the object. `Object` can be a table, +a string, a number, a boolean, `nil`, `json.null` or any object with +a function `__tojson` in its metatable. A table can only use strings +and numbers as keys and its values have to be valid objects as +well. It raises an error for any invalid data types or reference +cycles. + +`state` is an optional table with the following fields: + + - `indent` + When `indent` (a boolean) is set, the created string will contain + newlines and indentations. Otherwise it will be one long line. + - `keyorder` + `keyorder` is an array to specify the ordering of keys in the + encoded output. If an object has keys which are not in this array + they are written after the sorted keys. + - `level` + This is the initial level of indentation used when `indent` is + set. For each level two spaces are added. When absent it is set + to 0. + - `buffer` + `buffer` is an array to store the strings for the result so they + can be concatenated at once. When it isn't given, the encode + function will create it temporary and will return the + concatenated result. + - `bufferlen` + When `bufferlen` is set, it has to be the index of the last + element of `buffer`. + - `tables` + `tables` is a set to detect reference cycles. It is created + temporary when absent. Every table that is currently processed + is used as key, the value is `true`. + +When `state.buffer` was set, the return value will be `true` on +success. Without `state.buffer` the return value will be a string. + +`json.decode (string [, position [, null]])` +-------------------------------------------- + +Decode `string` starting at `position` or at 1 if `position` was +omitted. + +`null` is an optional value to be returned for null values. The +default is `nil`, but you could set it to `json.null` or any other +value. + +The return values are the object or `nil`, the position of the next +character that doesn't belong to the object, and in case of errors +an error message. + +Two metatables are created. Every array or object that is decoded gets +a metatable with the `__jsontype` field set to either `array` or +`object`. If you want to provide your own metatables use the syntax + + json.decode (string, position, null, objectmeta, arraymeta) + +To prevent the assigning of metatables pass `nil`: + + json.decode (string, position, null, nil) + +`.__jsonorder` +------------------------- + +`__jsonorder` can overwrite the `keyorder` for a specific table. + +`.__jsontype` +------------------------ + +`__jsontype` can be either `"array"` or `"object"`. This value is only +checked for empty tables. (The default for empty tables is `"array"`). + +`.__tojson (self, state)` +------------------------------------ + +You can provide your own `__tojson` function in a metatable. In this +function you can either add directly to the buffer and return true, +or you can return a string. On errors nil and a message should be +returned. + +`json.null` +----------- + +You can use this value for setting explicit `null` values. + +`json.version` +-------------- + +Set to `"dkjson 2.2"`. + +`json.quotestring (string)` +--------------------------- + +Quote a UTF-8 string and escape critical characters using JSON +escape sequences. This function is only necessary when you build +your own `__tojson` functions. + +`json.addnewline (state)` +------------------------- + +When `state.indent` is set, add a newline to `state.buffer` and spaces +according to `state.level`. + +LPeg support +------------ + +When the local configuration variable `always_try_using_lpeg` is set, +this module tries to load LPeg to replace the `decode` function. The +speed increase is significant. You can get the LPeg module at + . +When LPeg couldn't be loaded, the pure Lua functions stay active. + +In case you don't want this module to require LPeg on its own, +disable the option `always_try_using_lpeg` in the options section at +the top of the module. + +In this case you can later load LPeg support using + +### `json.use_lpeg ()` + +Require the LPeg module and replace the functions `quotestring` and +and `decode` with functions that use LPeg patterns. +This function returns the module table, so you can load the module +using: + + json = require "dkjson".use_lpeg() + +Alternatively you can use `pcall` so the JSON module still works when +LPeg isn't found. + + json = require "dkjson" + pcall (json.use_lpeg) + +### `json.using_lpeg` + +This variable is set to `true` when LPeg was loaded successfully. + +--------------------------------------------------------------------- + +Contact +------- + +You can contact the author by sending an e-mail to 'kolf' at the +e-mail provider 'gmx.de'. + +--------------------------------------------------------------------- + +*Copyright (C) 2010, 2011, 2012 David Heiko Kolf* + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + + diff --git a/jsontest.lua b/jsontest.lua new file mode 100644 index 0000000..3031390 --- /dev/null +++ b/jsontest.lua @@ -0,0 +1,426 @@ +local encode, decode, dkencode, dkdecode + + +local test_module, opt = ... -- command line argument +--local test_module = 'cmj-json' +--local test_module = 'dkjson' +--local test_module = 'dkjson-nopeg' +--local test_module = 'fleece' +--local test_module = 'jf-json' +--locel test_module = 'lua-yajl' +--local test_module = 'mp-cjson' +--local test_module = 'nm-json' +--local test_module = 'sb-json' +--local test_module = 'th-json' + +--local opt = "esc" -- Test which characters in the BMP get escaped and whether this is correct +--local opt = "esc_full" -- Full range from 0 to 0x10ffff +--local opt = "esc_asc" -- Just 0 to 127 + +--local opt = "refcycle" -- What happens when a reference cycle gets encoded? + +if test_module == 'dkjson-nopeg' then + test_module = 'dkjson' + package.preload["lpeg"] = function () error "lpeg disabled" end + package.loaded["lpeg"] = nil + lpeg = nil +end + +do + -- http://chiselapp.com/user/dhkolf/repository/dkjson/ + local dkjson = require "dkjson" + dkencode = dkjson.encode + dkdecode = dkjson.decode +end + +if test_module == 'cmj-json' then + -- http://json.luaforge.net/ + local json = require "cmjjson" -- renamed, the original file was just 'json' + encode = json.encode + decode = json.decode +elseif test_module == 'dkjson' then + -- http://chiselapp.com/user/dhkolf/repository/dkjson/ + encode = dkencode + decode = dkdecode +elseif test_module == 'fleece' then + -- http://www.eonblast.com/fleece/ + local fleece = require "fleece" + encode = function(x) return fleece.json(x, "E4") end +elseif test_module == 'jf-json' then + -- http://regex.info/blog/lua/json + local json = require "jfjson" -- renamed, the original file was just 'JSON' + encode = function(x) return json:encode(x) end + decode = function(x) return json:decode(x) end +elseif test_module == 'lua-yajl' then + -- http://github.com/brimworks/lua-yajl + local yajl = require ("yajl") + encode = yajl.to_string + decode = yajl.to_value +elseif test_module == 'mp-cjson' then + -- http://www.kyne.com.au/~mark/software/lua-cjson.php + local json = require "cjson" + encode = json.encode + decode = json.decode +elseif test_module == 'nm-json' then + -- http://luaforge.net/projects/luajsonlib/ + local json = require "LuaJSON" + encode = json.encode or json.stringify + decode = json.decode or json.parse +elseif test_module == 'sb-json' then + -- http://www.chipmunkav.com/downloads/Json.lua + local json = require "sbjson" -- renamed, the original file was just 'Json' + encode = json.Encode + decode = json.Decode +elseif test_module == 'th-json' then + -- http://luaforge.net/projects/luajson/ + local json = require "json" + encode = json.encode + decode = json.decode +else + print "No module specified" + return +end + +if not encode then + print ("No encode method") +else + local x, r + + local function test (x, s) + return string.match(x, "^%s*%[%s*%\"" .. s .. "%\"%s*%]%s*$") + end + + x = encode{ "'" } + if not test(x, "%'") then + print("\"'\" isn't encoded correctly:", x) + end + + x = encode{ "\011" } + if not test(x, "%\\u000[bB]") then + print("\\u000b isn't encoded correctly:", x) + end + + x = encode{ "\000" } + if not test(x, "%\\u0000") then + print("\\u0000 isn't encoded correctly") + end + + r,x = pcall (encode, { [1000] = "x" }) + if not r then + print ("encoding a sparse array (#=0) raises an error:", x) + else + if #x > 30 then + print ("sparse array (#=0) encoded as:", x:sub(1,15).." <...> "..x:sub(-15,-1), "#"..#x) + else + print ("sparse array (#=0) encoded as:", x) + end + end + + r,x = pcall (encode, { [1] = "a", [1000] = "x" }) + if not r then + print ("encoding a sparse array (#=1) raises an error:", x) + else + if #x > 30 then + print ("sparse array (#=1) encoded as:", x:sub(1,15).." <...> "..x:sub(-15,-1), "#str="..#x) + else + print ("sparse array (#=1) encoded as:", x) + end + end + + r,x = pcall (encode, { [1] = "a", [5] = "c", ["x"] = "x" }) + if not r then + print ("encoding a mixed table raises an error:", x) + else + print ("mixed table encoded as:", x) + end + + r, x = pcall(encode, { math.huge*0 }) -- NaN + if not r then + print ("encoding NaN raises an error:", x) + else + r = dkdecode(x) + if not r then + print ("NaN isn't converted into valid JSON:", x) + elseif type(r[1]) == "number" and r[1] == r[1] then -- a number, but not NaN + print ("NaN is converted into a valid number:", x) + else + print ("NaN is converted to:", x) + end + end + + if test_module == 'fleece' then + print ("Fleece (0.3.1) is known to freeze on +/-Inf") + else + r, x = pcall(encode, { math.huge }) -- +Inf + if not r then + print ("encoding +Inf raises an error:", x) + else + r = dkdecode(x) + if not r then + print ("+Inf isn't converted into valid JSON:", x) + else + print ("+Inf is converted to:", x) + end + end + + r, x = pcall(encode, { -math.huge }) -- -Inf + if not r then + print ("encoding -Inf raises an error:", x) + else + r = dkdecode(x) + if not r then + print ("-Inf isn't converted into valid JSON:", x) + else + print ("-Inf is converted to:", x) + end + end + end +end + +if not decode then + print ("No decode method") +else + local x, r + + x = decode[=[ ["\u0000"] ]=] + if x[1] ~= "\000" then + print ("\\u0000 isn't decoded correctly") + end + + x = decode[=[ ["\u20AC"] ]=] + if x[1] ~= "\226\130\172" then + print ("\\u20AC isn't decoded correctly") + end + + x = decode[=[ ["\uD834\uDD1E"] ]=] + if x[1] ~= "\240\157\132\158" then + print ("\\uD834\\uDD1E isn't decoded correctly") + end + + r, x = pcall(decode, [=[ +{"x":{"x":{"x":{"x":{"x": {"x":{"x":{"x":{"x":{"x": {"x":{"x":{"x":{"x":{"x": +{"x":{"x":{"x":{"x":{"x": {"x":{"x":{"x":{"x":{"x": {"x":{"x":{"x":{"x":{"x": +{"x":{"x":{"x":{"x":{"x": {"x":{"x":{"x":{"x":{"x": {"x":{"x":{"x":{"x":{"x": +{"x":{"x":{"x":{"x":{"x": {"x":{"x":{"x":{"x":{"x": {"x":{"x":{"x":{"x":{"x": +"deep down" + } } } } } } } } } } } } } } } + } } } } } } } } } } } } } } } + } } } } } } } } } } } } } } } + } } } } } } } } } } } } } } } +]=]) + + if not r then + print ("decoding a deep nested table raises an error:", x) + else + local i = 0 + while type(x) == 'table' do + i = i + 1 + x = x.x + end + if i ~= 60 or x ~= "deep down" then + print ("deep nested table isn't decoded correctly") + end + end + + if false and test_module == 'cmj-json' then + -- unfortunatly the version can't be read + print ("decoding a big array takes ages (or forever?) on cmj-json prior to version 0.9.5") + else + r, x = pcall(decode, "["..("0,"):rep(100000).."0]") + if not r then + print ("decoding a big array raises an error:", x) + else + if type(x) ~= 'table' or #x ~= 100001 then + print ("big array isn't decoded correctly") + end + end + end + + r, x = pcall(decode, "{}") + if not r then + print ("decoding an empty object raises an error:", x) + end + + r, x = pcall(decode, "[]") + if not r then + print ("decoding an empty array raises an error:", x) + end + + r, x = pcall(decode, "[1e+2]") + if not r then + print ("decoding a number with exponential notation raises an error:", x) + elseif x[1] ~= 1e+2 then + print ("1e+2 decoded incorrectly:", r[1]) + end + + -- special tests for dkjson: + if test_module == 'dkjson' then + x = dkdecode[=[ [{"x":0}] ]=] + if getmetatable(x).__jsontype ~= 'array' then + print (".__jsontype ~= array") + end + if getmetatable(x[1]).__jsontype ~= 'object' then + print (".__jsontype ~= object") + end + + local x,p,m = dkdecode" invalid " + if p ~= 2 or type(m) ~= 'string' or not m:find("at line 1, column 2$") then + print (("Invalid location: position=%d, message=%q"):format(p,m)) + end + local x,p,m = dkdecode" \n invalid " + if p ~= 4 or type(m) ~= 'string' or not m:find("at line 2, column 2$") then + print (("Invalid location: position=%d, message=%q"):format(p,m)) + end + end +end + +if encode and opt == "refcycle" then + local a = {} + a.a = a + print ("Trying a reference cycle...") + encode(a) +end + +if encode and (opt or ""):sub(1,3) == "esc" then + +local strchar, strbyte, strformat = string.char, string.byte, string.format +local floor = math.floor + +local function unichar (value) + if value < 0 then + return nil + elseif value <= 0x007f then + return strchar (value) + elseif value <= 0x07ff then + return strchar (0xc0 + floor(value/0x40), + 0x80 + (floor(value) % 0x40)) + elseif value <= 0xffff then + return strchar (0xe0 + floor(value/0x1000), + 0x80 + (floor(value/0x40) % 0x40), + 0x80 + (floor(value) % 0x40)) + elseif value <= 0x10ffff then + return strchar (0xf0 + floor(value/0x40000), + 0x80 + (floor(value/0x1000) % 0x40), + 0x80 + (floor(value/0x40) % 0x40), + 0x80 + (floor(value) % 0x40)) + else + return nil + end +end + +local escapecodes = { + ["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f", + ["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t", ["/"] = "\\/" +} + +local function escapeutf8 (uchar) + local a, b, c, d = strbyte (uchar, 1, 4) + a, b, c, d = a or 0, b or 0, c or 0, d or 0 + if a <= 0x7f then + value = a + elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then + value = (a - 0xc0) * 0x40 + b - 0x80 + elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then + value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80 + elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then + value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80 + else + return "" + end + if value <= 0xffff then + return strformat ("\\u%.4x", value) + elseif value <= 0x10ffff then + -- encode as UTF-16 surrogate pair + value = value - 0x10000 + local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400) + return strformat ("\\u%.4x\\u%.4x", highsur, lowsur) + else + return "" + end +end + + local x,xe + + local t = {} + local esc = {} + local escerr = {} + local range + if opt == "esc_full" then range = 0x10ffff + elseif opt == "esc_asc" then range = 0x7f + else range = 0xffff end + + for i = 0,range do + t[1] = unichar(i) + xe = encode(t) + x = string.match(xe, "^%s*%[%s*%\"(.*)%\"%s*%]%s*$") + if type(x) ~= 'string' then + escerr[i] = xe + elseif string.lower(x) == escapeutf8(t[1]) then + esc[i] = 'u' + elseif x == escapecodes[t[1]] then + esc[i] = 'c' + elseif x:sub(1,1) == "\\" then + --print ("Invalid escape code for "..i..":", x) + escerr[i] = xe + end + end + do + local i = 0 + while i <= range do + local first + while i <= range and not esc[i] do i = i + 1 end + if not esc[i] then break end + first = i + while esc[i] do i = i + 1 end + if i-1 > first then + print ("Escaped from "..first.." to "..i-1) + else + if first >= 32 and first <= 127 then + print ("Escaped "..first.." ("..string.char(first)..")") + else + print ("Escaped "..first) + end + end + end + end + do + local i = 0 + while i <= range do + local first + while i <= range and not escerr[i] do i = i + 1 end + if not escerr[i] then break end + first = i + while escerr[i] do i = i + 1 end + if i-1 > first then + print ("Errors while escaping from "..first.." to "..i-1) + else + print ("Errors while escaping "..first) + end + end + end + +end + +-- Copyright (C) 2011 David Heiko Kolf +-- +-- Permission is hereby granted, free of charge, to any person obtaining +-- a copy of this software and associated documentation files (the +-- "Software"), to deal in the Software without restriction, including +-- without limitation the rights to use, copy, modify, merge, publish, +-- distribute, sublicense, and/or sell copies of the Software, and to +-- permit persons to whom the Software is furnished to do so, subject to +-- the following conditions: +-- +-- The above copyright notice and this permission notice shall be +-- included in all copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +-- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +-- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +-- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +-- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +-- SOFTWARE. + + diff --git a/speedtest.lua b/speedtest.lua new file mode 100644 index 0000000..69a8be5 --- /dev/null +++ b/speedtest.lua @@ -0,0 +1,131 @@ +local encode, decode + +local test_module = ... -- command line argument +--local test_module = 'cmj-json' +--local test_module = 'dkjson' +--local test_module = 'dkjson-nopeg' +--local test_module = 'fleece' +--local test_module = 'jf-json' +--locel test_module = 'lua-yajl' +--local test_module = 'mp-cjson' +--local test_module = 'nm-json' +--local test_module = 'sb-json' +--local test_module = 'th-json' + + +if test_module == 'cmj-json' then + -- http://json.luaforge.net/ + local json = require "cmjjson" -- renamed, the original file was just 'json' + encode = json.encode + decode = json.decode +elseif test_module == 'dkjson' then + -- http://chiselapp.com/user/dhkolf/repository/dkjson/ + local dkjson = require "dkjson" + encode = dkjson.encode + decode = dkjson.decode +elseif test_module == 'dkjson-nopeg' then + package.preload["lpeg"] = function () error "lpeg disabled" end + package.loaded["lpeg"] = nil + lpeg = nil + local dkjson = require "dkjson" + encode = dkjson.encode + decode = dkjson.decode +elseif test_module == 'fleece' then + -- http://www.eonblast.com/fleece/ + local fleece = require "fleece" + encode = function(x) return fleece.json(x, "E4") end +elseif test_module == 'jf-json' then + -- http://regex.info/blog/lua/json + local json = require "jfjson" -- renamed, the original file was just 'JSON' + encode = function(x) return json:encode(x) end + decode = function(x) return json:decode(x) end +elseif test_module == 'lua-yajl' then + -- http://github.com/brimworks/lua-yajl + local yajl = require ("yajl") + encode = yajl.to_string + decode = yajl.to_value +elseif test_module == 'mp-cjson' then + -- http://www.kyne.com.au/~mark/software/lua-cjson.php + local json = require "cjson" + encode = json.encode + decode = json.decode +elseif test_module == 'nm-json' then + -- http://luaforge.net/projects/luajsonlib/ + local json = require "LuaJSON" + encode = json.encode or json.stringify + decode = json.decode or json.parse +elseif test_module == 'sb-json' then + -- http://www.chipmunkav.com/downloads/Json.lua + local json = require "sbjson" -- renamed, the original file was just 'Json' + encode = json.Encode + decode = json.Decode +elseif test_module == 'th-json' then + -- http://luaforge.net/projects/luajson/ + local json = require "json" + encode = json.encode + decode = json.decode +else + print "No module specified" + return +end + +-- example data taken from +-- http://de.wikipedia.org/wiki/JavaScript_Object_Notation + +local str = [[ +{ + "Herausgeber": "Xema", + "Nummer": "1234-5678-9012-3456", + "Deckung": 26, + "Währung": "EUR", + "Inhaber": { + "Name": "Mustermann", + "Vorname": "Max", + "männlich": true, + "Depot": {}, + "Hobbys": [ "Reiten", "Golfen", "Lesen" ], + "Alter": 42, + "Kinder": [0], + "Partner": null + } +} +]] + +local tbl = { + Herausgeber= "Xema", + Nummer= "1234-5678-9012-3456", + Deckung= 2e+6, + ["Währung"]= "EUR", + Inhaber= { + Name= "Mustermann", + Vorname= "Max", + ["männlich"]= true, + Depot= {}, + Hobbys= { "Reiten", "Golfen", "Lesen" }, + Alter= 42, + Kinder= {}, + Partner= nil + --Partner= json.null + } +} + +local t1, t2 + +if decode then + t1 = os.clock () + for i = 1,100000 do + decode (str) + end + t2 = os.clock () + print ("Decoding:", t2 - t1) +end + +if encode then + t1 = os.clock () + for i = 1,100000 do + encode (tbl) + end + t2 = os.clock () + print ("Encoding:", t2 - t1) +end + diff --git a/versions.txt b/versions.txt new file mode 100644 index 0000000..52d8fa0 --- /dev/null +++ b/versions.txt @@ -0,0 +1,61 @@ +Version 2.2 (2012-04-28) +=========== + +Changes since version 2.1: + + * __jsontype is only used for empty tables. + * It is possible to decode tables without assigning metatables. + * Locations for error messages were off by one in the first line. + * There is no LPeg version of json.quotestring anymore. + +Version 2.1 (2011-07-08) +=========== + +Changes since version 2.0: + + * Changed the documentation to Markdown format. + * LPeg is now parsing only a single value at a time to avoid running + out of Lua stack for big arrays and objects. + * Read __tojson, __jsontype and __jsonorder even from blocked metatables + through the debug module. + * Fixed decoding single numbers (only affected the non-LPeg mode). + * Corrected the range of escaped Unicode control characters. + +Version 1.1 (2011-07-08) +=========== + +Changes since version 1.0: + + * The values NaN/+Inf/-Inf are recognised and encoded as "null" like in + the original JavaScript implementation. + * Read __tojson even from blocked metatables through the debug module. + * Fixed decoding single numbers. + * Corrected the range of escaped Unicode control characters. + +Version 2.0 (2011-05-31) +=========== + +Changes since version 1.0: + + * Optional LPeg support. + * Invalid input data for encoding raises errors instead of returning nil + and the error message. (Invalid data for encoding is usually a + programming error. Raising an error removes the work of explicitly + checking the result). + * The metatable field __jsontype can control whether a Lua table is + encoded as a JSON array or object. (Mainly useful for empty tables). + * When decoding, two metatables are created. One is used to mark the arrays + while the other one is used for the objects. (The metatables are + created once for each decoding operation to make sandboxing possible. + However, you can specify your own metatables as arguments). + * There are no spaces added any longer when encoding. + * It is possible to explicitly sort keys for encoding by providing an array with key + names to the option "keyorder" or the metatable field __jsonorder. + * The values NaN/+Inf/-Inf are recognised and encoded as "null" like in + the original JavaScript implementation. + +Version 1.0 +=========== + +Initial version, released 2010-08-28. +