File: array.lua

package info (click to toggle)
lua-json 1.3.4-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 688 kB
  • sloc: makefile: 71; php: 3
file content (110 lines) | stat: -rw-r--r-- 2,770 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
--[[
	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