1
0

json.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. -- Copyright 2008 Steven Barth <steven@midlink.org>
  2. -- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
  3. -- Licensed to the public under the Apache License 2.0.
  4. local nixio = require "nixio"
  5. local util = require "luci.util"
  6. local table = require "table"
  7. local string = require "string"
  8. local coroutine = require "coroutine"
  9. local assert = assert
  10. local tonumber = tonumber
  11. local tostring = tostring
  12. local error = error
  13. local type = type
  14. local pairs = pairs
  15. local ipairs = ipairs
  16. local next = next
  17. local pcall = pcall
  18. local band = nixio.bit.band
  19. local bor = nixio.bit.bor
  20. local rshift = nixio.bit.rshift
  21. local char = string.char
  22. local getmetatable = getmetatable
  23. module "luci.json"
  24. function decode(json, ...)
  25. local a = ActiveDecoder(function() return nil end, ...)
  26. a.chunk = json
  27. local s, obj = pcall(a.get, a)
  28. return s and obj or nil
  29. end
  30. function encode(obj, ...)
  31. local out = {}
  32. local e = Encoder(obj, 1, ...):source()
  33. local chnk, err
  34. repeat
  35. chnk, err = e()
  36. out[#out+1] = chnk
  37. until not chnk
  38. return not err and table.concat(out) or nil
  39. end
  40. function null()
  41. return null
  42. end
  43. Encoder = util.class()
  44. function Encoder.__init__(self, data, buffersize, fastescape)
  45. self.data = data
  46. self.buffersize = buffersize or 512
  47. self.buffer = ""
  48. self.fastescape = fastescape
  49. getmetatable(self).__call = Encoder.source
  50. end
  51. function Encoder.source(self)
  52. local source = coroutine.create(self.dispatch)
  53. return function()
  54. local res, data = coroutine.resume(source, self, self.data, true)
  55. if res then
  56. return data
  57. else
  58. return nil, data
  59. end
  60. end
  61. end
  62. function Encoder.dispatch(self, data, start)
  63. local parser = self.parsers[type(data)]
  64. parser(self, data)
  65. if start then
  66. if #self.buffer > 0 then
  67. coroutine.yield(self.buffer)
  68. end
  69. coroutine.yield()
  70. end
  71. end
  72. function Encoder.put(self, chunk)
  73. if self.buffersize < 2 then
  74. coroutine.yield(chunk)
  75. else
  76. if #self.buffer + #chunk > self.buffersize then
  77. local written = 0
  78. local fbuffer = self.buffersize - #self.buffer
  79. coroutine.yield(self.buffer .. chunk:sub(written + 1, fbuffer))
  80. written = fbuffer
  81. while #chunk - written > self.buffersize do
  82. fbuffer = written + self.buffersize
  83. coroutine.yield(chunk:sub(written + 1, fbuffer))
  84. written = fbuffer
  85. end
  86. self.buffer = chunk:sub(written + 1)
  87. else
  88. self.buffer = self.buffer .. chunk
  89. end
  90. end
  91. end
  92. function Encoder.parse_nil(self)
  93. self:put("null")
  94. end
  95. function Encoder.parse_bool(self, obj)
  96. self:put(obj and "true" or "false")
  97. end
  98. function Encoder.parse_number(self, obj)
  99. self:put(tostring(obj))
  100. end
  101. function Encoder.parse_string(self, obj)
  102. if self.fastescape then
  103. self:put('"' .. obj:gsub('\\', '\\\\'):gsub('"', '\\"') .. '"')
  104. else
  105. self:put('"' ..
  106. obj:gsub('[%c\\"]',
  107. function(char)
  108. return '\\u00%02x' % char:byte()
  109. end
  110. )
  111. .. '"')
  112. end
  113. end
  114. function Encoder.parse_iter(self, obj)
  115. if obj == null then
  116. return self:put("null")
  117. end
  118. if type(obj) == "table" and (#obj == 0 and next(obj)) then
  119. self:put("{")
  120. local first = true
  121. for key, entry in pairs(obj) do
  122. if key ~= null then
  123. first = first or self:put(",")
  124. first = first and false
  125. self:parse_string(tostring(key))
  126. self:put(":")
  127. self:dispatch(entry)
  128. end
  129. end
  130. self:put("}")
  131. else
  132. self:put("[")
  133. local first = true
  134. if type(obj) == "table" then
  135. for i=1, #obj do
  136. first = first or self:put(",")
  137. first = first and nil
  138. self:dispatch(obj[i])
  139. end
  140. else
  141. for entry in obj do
  142. first = first or self:put(",")
  143. first = first and nil
  144. self:dispatch(entry)
  145. end
  146. end
  147. self:put("]")
  148. end
  149. end
  150. Encoder.parsers = {
  151. ['nil'] = Encoder.parse_nil,
  152. ['table'] = Encoder.parse_iter,
  153. ['number'] = Encoder.parse_number,
  154. ['string'] = Encoder.parse_string,
  155. ['boolean'] = Encoder.parse_bool,
  156. ['function'] = Encoder.parse_iter
  157. }
  158. Decoder = util.class()
  159. function Decoder.__init__(self, customnull)
  160. self.cnull = customnull
  161. getmetatable(self).__call = Decoder.sink
  162. end
  163. function Decoder.sink(self)
  164. local sink = coroutine.create(self.dispatch)
  165. return function(...)
  166. return coroutine.resume(sink, self, ...)
  167. end
  168. end
  169. function Decoder.get(self)
  170. return self.data
  171. end
  172. function Decoder.dispatch(self, chunk, src_err, strict)
  173. local robject, object
  174. local oset = false
  175. while chunk do
  176. while chunk and #chunk < 1 do
  177. chunk = self:fetch()
  178. end
  179. assert(not strict or chunk, "Unexpected EOS")
  180. if not chunk then break end
  181. local char = chunk:sub(1, 1)
  182. local parser = self.parsers[char]
  183. or (char:match("%s") and self.parse_space)
  184. or (char:match("[0-9-]") and self.parse_number)
  185. or error("Unexpected char '%s'" % char)
  186. chunk, robject = parser(self, chunk)
  187. if parser ~= self.parse_space then
  188. assert(not oset, "Scope violation: Too many objects")
  189. object = robject
  190. oset = true
  191. if strict then
  192. return chunk, object
  193. end
  194. end
  195. end
  196. assert(not src_err, src_err)
  197. assert(oset, "Unexpected EOS")
  198. self.data = object
  199. end
  200. function Decoder.fetch(self)
  201. local tself, chunk, src_err = coroutine.yield()
  202. assert(chunk or not src_err, src_err)
  203. return chunk
  204. end
  205. function Decoder.fetch_atleast(self, chunk, bytes)
  206. while #chunk < bytes do
  207. local nchunk = self:fetch()
  208. assert(nchunk, "Unexpected EOS")
  209. chunk = chunk .. nchunk
  210. end
  211. return chunk
  212. end
  213. function Decoder.fetch_until(self, chunk, pattern)
  214. local start = chunk:find(pattern)
  215. while not start do
  216. local nchunk = self:fetch()
  217. assert(nchunk, "Unexpected EOS")
  218. chunk = chunk .. nchunk
  219. start = chunk:find(pattern)
  220. end
  221. return chunk, start
  222. end
  223. function Decoder.parse_space(self, chunk)
  224. local start = chunk:find("[^%s]")
  225. while not start do
  226. chunk = self:fetch()
  227. if not chunk then
  228. return nil
  229. end
  230. start = chunk:find("[^%s]")
  231. end
  232. return chunk:sub(start)
  233. end
  234. function Decoder.parse_literal(self, chunk, literal, value)
  235. chunk = self:fetch_atleast(chunk, #literal)
  236. assert(chunk:sub(1, #literal) == literal, "Invalid character sequence")
  237. return chunk:sub(#literal + 1), value
  238. end
  239. function Decoder.parse_null(self, chunk)
  240. return self:parse_literal(chunk, "null", self.cnull and null)
  241. end
  242. function Decoder.parse_true(self, chunk)
  243. return self:parse_literal(chunk, "true", true)
  244. end
  245. function Decoder.parse_false(self, chunk)
  246. return self:parse_literal(chunk, "false", false)
  247. end
  248. function Decoder.parse_number(self, chunk)
  249. local chunk, start = self:fetch_until(chunk, "[^0-9eE.+-]")
  250. local number = tonumber(chunk:sub(1, start - 1))
  251. assert(number, "Invalid number specification")
  252. return chunk:sub(start), number
  253. end
  254. function Decoder.parse_string(self, chunk)
  255. local str = ""
  256. local object = nil
  257. assert(chunk:sub(1, 1) == '"', 'Expected "')
  258. chunk = chunk:sub(2)
  259. while true do
  260. local spos = chunk:find('[\\"]')
  261. if spos then
  262. str = str .. chunk:sub(1, spos - 1)
  263. local char = chunk:sub(spos, spos)
  264. if char == '"' then -- String end
  265. chunk = chunk:sub(spos + 1)
  266. break
  267. elseif char == "\\" then -- Escape sequence
  268. chunk, object = self:parse_escape(chunk:sub(spos))
  269. str = str .. object
  270. end
  271. else
  272. str = str .. chunk
  273. chunk = self:fetch()
  274. assert(chunk, "Unexpected EOS while parsing a string")
  275. end
  276. end
  277. return chunk, str
  278. end
  279. function Decoder.utf8_encode(self, s1, s2)
  280. local n = s1 * 256 + s2
  281. if n >= 0 and n <= 0x7F then
  282. return char(n)
  283. elseif n >= 0 and n <= 0x7FF then
  284. return char(
  285. bor(band(rshift(n, 6), 0x1F), 0xC0),
  286. bor(band(n, 0x3F), 0x80)
  287. )
  288. elseif n >= 0 and n <= 0xFFFF then
  289. return char(
  290. bor(band(rshift(n, 12), 0x0F), 0xE0),
  291. bor(band(rshift(n, 6), 0x3F), 0x80),
  292. bor(band(n, 0x3F), 0x80)
  293. )
  294. elseif n >= 0 and n <= 0x10FFFF then
  295. return char(
  296. bor(band(rshift(n, 18), 0x07), 0xF0),
  297. bor(band(rshift(n, 12), 0x3F), 0x80),
  298. bor(band(rshift(n, 6), 0x3F), 0x80),
  299. bor(band(n, 0x3F), 0x80)
  300. )
  301. else
  302. return "?"
  303. end
  304. end
  305. function Decoder.parse_escape(self, chunk)
  306. local str = ""
  307. chunk = self:fetch_atleast(chunk:sub(2), 1)
  308. local char = chunk:sub(1, 1)
  309. chunk = chunk:sub(2)
  310. if char == '"' then
  311. return chunk, '"'
  312. elseif char == "\\" then
  313. return chunk, "\\"
  314. elseif char == "u" then
  315. chunk = self:fetch_atleast(chunk, 4)
  316. local s1, s2 = chunk:sub(1, 2), chunk:sub(3, 4)
  317. s1, s2 = tonumber(s1, 16), tonumber(s2, 16)
  318. assert(s1 and s2, "Invalid Unicode character")
  319. return chunk:sub(5), self:utf8_encode(s1, s2)
  320. elseif char == "/" then
  321. return chunk, "/"
  322. elseif char == "b" then
  323. return chunk, "\b"
  324. elseif char == "f" then
  325. return chunk, "\f"
  326. elseif char == "n" then
  327. return chunk, "\n"
  328. elseif char == "r" then
  329. return chunk, "\r"
  330. elseif char == "t" then
  331. return chunk, "\t"
  332. else
  333. error("Unexpected escaping sequence '\\%s'" % char)
  334. end
  335. end
  336. function Decoder.parse_array(self, chunk)
  337. chunk = chunk:sub(2)
  338. local array = {}
  339. local nextp = 1
  340. local chunk, object = self:parse_delimiter(chunk, "%]")
  341. if object then
  342. return chunk, array
  343. end
  344. repeat
  345. chunk, object = self:dispatch(chunk, nil, true)
  346. table.insert(array, nextp, object)
  347. nextp = nextp + 1
  348. chunk, object = self:parse_delimiter(chunk, ",%]")
  349. assert(object, "Delimiter expected")
  350. until object == "]"
  351. return chunk, array
  352. end
  353. function Decoder.parse_object(self, chunk)
  354. chunk = chunk:sub(2)
  355. local array = {}
  356. local name
  357. local chunk, object = self:parse_delimiter(chunk, "}")
  358. if object then
  359. return chunk, array
  360. end
  361. repeat
  362. chunk = self:parse_space(chunk)
  363. assert(chunk, "Unexpected EOS")
  364. chunk, name = self:parse_string(chunk)
  365. chunk, object = self:parse_delimiter(chunk, ":")
  366. assert(object, "Separator expected")
  367. chunk, object = self:dispatch(chunk, nil, true)
  368. array[name] = object
  369. chunk, object = self:parse_delimiter(chunk, ",}")
  370. assert(object, "Delimiter expected")
  371. until object == "}"
  372. return chunk, array
  373. end
  374. function Decoder.parse_delimiter(self, chunk, delimiter)
  375. while true do
  376. chunk = self:fetch_atleast(chunk, 1)
  377. local char = chunk:sub(1, 1)
  378. if char:match("%s") then
  379. chunk = self:parse_space(chunk)
  380. assert(chunk, "Unexpected EOS")
  381. elseif char:match("[%s]" % delimiter) then
  382. return chunk:sub(2), char
  383. else
  384. return chunk, nil
  385. end
  386. end
  387. end
  388. Decoder.parsers = {
  389. ['"'] = Decoder.parse_string,
  390. ['t'] = Decoder.parse_true,
  391. ['f'] = Decoder.parse_false,
  392. ['n'] = Decoder.parse_null,
  393. ['['] = Decoder.parse_array,
  394. ['{'] = Decoder.parse_object
  395. }
  396. ActiveDecoder = util.class(Decoder)
  397. function ActiveDecoder.__init__(self, source, customnull)
  398. Decoder.__init__(self, customnull)
  399. self.source = source
  400. self.chunk = nil
  401. getmetatable(self).__call = self.get
  402. end
  403. function ActiveDecoder.get(self)
  404. local chunk, src_err, object
  405. if not self.chunk then
  406. chunk, src_err = self.source()
  407. else
  408. chunk = self.chunk
  409. end
  410. self.chunk, object = self:dispatch(chunk, src_err, true)
  411. return object
  412. end
  413. function ActiveDecoder.fetch(self)
  414. local chunk, src_err = self.source()
  415. assert(chunk or not src_err, src_err)
  416. return chunk
  417. end