Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
luajson/lua/json/encode/array.lua
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
110 lines (97 sloc)
2.71 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --[[ | |
| Licensed according to the included 'LICENSE' document | |
| Author: Thomas Harning Jr <harningt@gmail.com> | |
| ]] | |
| local jsonutil = require("json.util") | |
| local type = type | |
| local pairs = pairs | |
| local assert = assert | |
| local table = require("table") | |
| local math = require("math") | |
| local table_concat = table.concat | |
| local math_floor, math_modf = math.floor, math.modf | |
| local jsonutil = require("json.util") | |
| local util_IsArray = jsonutil.IsArray | |
| local _ENV = nil | |
| local defaultOptions = { | |
| isArray = util_IsArray | |
| } | |
| local modeOptions = {} | |
| local function mergeOptions(options, mode) | |
| jsonutil.doOptionMerge(options, false, 'array', defaultOptions, mode and modeOptions[mode]) | |
| end | |
| --[[ | |
| Utility function to determine whether a table is an array or not. | |
| Criteria for it being an array: | |
| * ExternalIsArray returns true (or false directly reports not-array) | |
| * If the table has an 'n' value that is an integer >= 1 then it | |
| is an array... may result in false positives (should check some values | |
| before it) | |
| * It is a contiguous list of values with zero string-based keys | |
| ]] | |
| local function isArray(val, options) | |
| local externalIsArray = options and options.isArray | |
| if externalIsArray then | |
| local ret = externalIsArray(val) | |
| if ret == true or ret == false then | |
| return ret | |
| end | |
| end | |
| -- Use the 'n' element if it's a number | |
| if type(val.n) == 'number' and math_floor(val.n) == val.n and val.n >= 1 then | |
| return true | |
| end | |
| local len = #val | |
| for k,v in pairs(val) do | |
| if type(k) ~= 'number' then | |
| return false | |
| end | |
| local _, decim = math_modf(k) | |
| if not (decim == 0 and 1<=k) then | |
| return false | |
| end | |
| if k > len then -- Use Lua's length as absolute determiner | |
| return false | |
| end | |
| end | |
| return true | |
| end | |
| --[[ | |
| Cleanup function to unmark a value as in the encoding process and return | |
| trailing results | |
| ]] | |
| local function unmarkAfterEncode(tab, state, ...) | |
| state.already_encoded[tab] = nil | |
| return ... | |
| end | |
| local function getEncoder(options) | |
| options = options and jsonutil.merge({}, defaultOptions, options) or defaultOptions | |
| local function encodeArray(tab, state) | |
| if not isArray(tab, options) then | |
| return false | |
| end | |
| -- Make sure this value hasn't been encoded yet | |
| state.check_unique(tab) | |
| local encode = state.encode | |
| local compositeEncoder = state.outputEncoder.composite | |
| local valueEncoder = [[ | |
| for i = 1, (composite.n or #composite) do | |
| local val = composite[i] | |
| PUTINNER(i ~= 1) | |
| val = encode(val, state) | |
| val = val or '' | |
| if val then | |
| PUTVALUE(val) | |
| end | |
| end | |
| ]] | |
| return unmarkAfterEncode(tab, state, compositeEncoder(valueEncoder, '[', ']', ',', tab, encode, state)) | |
| end | |
| return { table = encodeArray } | |
| end | |
| local array = { | |
| mergeOptions = mergeOptions, | |
| isArray = isArray, | |
| getEncoder = getEncoder | |
| } | |
| return array |