File: strings.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 (88 lines) | stat: -rw-r--r-- 2,528 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
--[[
	Licensed according to the included 'LICENSE' document
	Author: Thomas Harning Jr <harningt@gmail.com>
]]
local string_char = require("string").char
local pairs = pairs

local jsonutil = require("json.util")
local util_merge = jsonutil.merge

local _ENV = nil

local normalEncodingMap = {
	['"'] = '\\"',
	['\\'] = '\\\\',
	['/'] = '\\/',
	['\b'] = '\\b',
	['\f'] = '\\f',
	['\n'] = '\\n',
	['\r'] = '\\r',
	['\t'] = '\\t',
	['\v'] = '\\v' -- not in official spec, on report, removing
}

local xEncodingMap = {}
for char, encoded in pairs(normalEncodingMap) do
	xEncodingMap[char] = encoded
end

-- Pre-encode the control characters to speed up encoding...
-- NOTE: UTF-8 may not work out right w/ JavaScript
-- JavaScript uses 2 bytes after a \u... yet UTF-8 is a
-- byte-stream encoding, not pairs of bytes (it does encode
-- some letters > 1 byte, but base case is 1)
for i = 0, 255 do
	local c = string_char(i)
	if c:match('[%z\1-\031\128-\255]') and not normalEncodingMap[c] then
		-- WARN: UTF8 specializes values >= 0x80 as parts of sequences...
		--       without \x encoding, do not allow encoding > 7F
		normalEncodingMap[c] = ('\\u%.4X'):format(i)
		xEncodingMap[c] = ('\\x%.2X'):format(i)
	end
end

local defaultOptions = {
	xEncode = false, -- Encode single-bytes as \xXX
	processor = nil, -- Simple processor for the string prior to quoting
	-- / is not required to be quoted but it helps with certain decoding
	-- Required encoded characters, " \, and 00-1F  (0 - 31)
	encodeSet = '\\"/%z\1-\031',
	encodeSetAppend = nil -- Chars to append to the default set
}

local modeOptions = {}

local function mergeOptions(options, mode)
	jsonutil.doOptionMerge(options, false, 'strings', defaultOptions, mode and modeOptions[mode])
end

local function getEncoder(options)
	options = options and util_merge({}, defaultOptions, options) or defaultOptions
	local encodeSet = options.encodeSet
	if options.encodeSetAppend then
		encodeSet = encodeSet .. options.encodeSetAppend
	end
	local encodingMap = options.xEncode and xEncodingMap or normalEncodingMap
	local encodeString
	if options.processor then
		local processor = options.processor
		encodeString = function(s, state)
			return '"' .. processor(s:gsub('[' .. encodeSet .. ']', encodingMap)) .. '"'
		end
	else
		encodeString = function(s, state)
			return '"' .. s:gsub('[' .. encodeSet .. ']', encodingMap) .. '"'
		end
	end
	return {
		string = encodeString
	}
end

local strings = {
	mergeOptions = mergeOptions,
	getEncoder = getEncoder
}

return strings