1--[[
2	Licensed according to the included 'LICENSE' document
3	Author: Thomas Harning Jr <harningt@gmail.com>
4]]
5local pairs = pairs
6local assert = assert
7
8local type = type
9local tostring = tostring
10
11local table_concat = require("table").concat
12local jsonutil = require("json.util")
13
14local _ENV = nil
15
16local defaultOptions = {
17}
18
19local modeOptions = {}
20
21local function mergeOptions(options, mode)
22	jsonutil.doOptionMerge(options, false, 'object', defaultOptions, mode and modeOptions[mode])
23end
24
25--[[
26	Cleanup function to unmark a value as in the encoding process and return
27	trailing results
28]]
29local function unmarkAfterEncode(tab, state, ...)
30	state.already_encoded[tab] = nil
31	return ...
32end
33--[[
34	Encode a table as a JSON Object ( keys = strings, values = anything else )
35]]
36local function encodeTable(tab, options, state)
37	-- Make sure this value hasn't been encoded yet
38	state.check_unique(tab)
39	local encode = state.encode
40	local compositeEncoder = state.outputEncoder.composite
41	local valueEncoder = [[
42	local first = true
43	for k, v in pairs(composite) do
44		local ti = type(k)
45		assert(ti == 'string' or ti == 'number' or ti == 'boolean', "Invalid object index type: " .. ti)
46		local name = encode(tostring(k), state, true)
47		if first then
48			first = false
49		else
50			name = ',' .. name
51		end
52		PUTVALUE(name .. ':')
53		local val = encode(v, state)
54		val = val or ''
55		if val then
56			PUTVALUE(val)
57		end
58	end
59	]]
60	return unmarkAfterEncode(tab, state, compositeEncoder(valueEncoder, '{', '}', nil, tab, encode, state))
61end
62
63local function getEncoder(options)
64	options = options and jsonutil.merge({}, defaultOptions, options) or defaultOptions
65	return {
66		table = function(tab, state)
67			return encodeTable(tab, options, state)
68		end
69	}
70end
71
72local object = {
73	mergeOptions = mergeOptions,
74	getEncoder = getEncoder
75}
76
77return object
78