json.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  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. first = first or self:put(",")
  123. first = first and false
  124. self:parse_string(tostring(key))
  125. self:put(":")
  126. self:dispatch(entry)
  127. end
  128. self:put("}")
  129. else
  130. self:put("[")
  131. local first = true
  132. if type(obj) == "table" then
  133. for i=1, #obj do
  134. first = first or self:put(",")
  135. first = first and nil
  136. self:dispatch(obj[i])
  137. end
  138. else
  139. for entry in obj do
  140. first = first or self:put(",")
  141. first = first and nil
  142. self:dispatch(entry)
  143. end
  144. end
  145. self:put("]")
  146. end
  147. end
  148. Encoder.parsers = {
  149. ['nil'] = Encoder.parse_nil,
  150. ['table'] = Encoder.parse_iter,
  151. ['number'] = Encoder.parse_number,
  152. ['string'] = Encoder.parse_string,
  153. ['boolean'] = Encoder.parse_bool,
  154. ['function'] = Encoder.parse_iter
  155. }
  156. Decoder = util.class()
  157. function Decoder.__init__(self, customnull)
  158. self.cnull = customnull
  159. getmetatable(self).__call = Decoder.sink
  160. end
  161. function Decoder.sink(self)
  162. local sink = coroutine.create(self.dispatch)
  163. return function(...)
  164. return coroutine.resume(sink, self, ...)
  165. end
  166. end
  167. function Decoder.get(self)
  168. return self.data
  169. end
  170. function Decoder.dispatch(self, chunk, src_err, strict)
  171. local robject, object
  172. local oset = false
  173. while chunk do
  174. while chunk and #chunk < 1 do
  175. chunk = self:fetch()
  176. end
  177. assert(not strict or chunk, "Unexpected EOS")
  178. if not chunk then break end
  179. local char = chunk:sub(1, 1)
  180. local parser = self.parsers[char]
  181. or (char:match("%s") and self.parse_space)
  182. or (char:match("[0-9-]") and self.parse_number)
  183. or error("Unexpected char '%s'" % char)
  184. chunk, robject = parser(self, chunk)
  185. if parser ~= self.parse_space then
  186. assert(not oset, "Scope violation: Too many objects")
  187. object = robject
  188. oset = true
  189. if strict then
  190. return chunk, object
  191. end
  192. end
  193. end
  194. assert(not src_err, src_err)
  195. assert(oset, "Unexpected EOS")
  196. self.data = object
  197. end
  198. function Decoder.fetch(self)
  199. local tself, chunk, src_err = coroutine.yield()
  200. assert(chunk or not src_err, src_err)
  201. return chunk
  202. end
  203. function Decoder.fetch_atleast(self, chunk, bytes)
  204. while #chunk < bytes do
  205. local nchunk = self:fetch()
  206. assert(nchunk, "Unexpected EOS")
  207. chunk = chunk .. nchunk
  208. end
  209. return chunk
  210. end
  211. function Decoder.fetch_until(self, chunk, pattern)
  212. local start = chunk:find(pattern)
  213. while not start do
  214. local nchunk = self:fetch()
  215. assert(nchunk, "Unexpected EOS")
  216. chunk = chunk .. nchunk
  217. start = chunk:find(pattern)
  218. end
  219. return chunk, start
  220. end
  221. function Decoder.parse_space(self, chunk)
  222. local start = chunk:find("[^%s]")
  223. while not start do
  224. chunk = self:fetch()
  225. if not chunk then
  226. return nil
  227. end
  228. start = chunk:find("[^%s]")
  229. end
  230. return chunk:sub(start)
  231. end
  232. function Decoder.parse_literal(self, chunk, literal, value)
  233. chunk = self:fetch_atleast(chunk, #literal)
  234. assert(chunk:sub(1, #literal) == literal, "Invalid character sequence")
  235. return chunk:sub(#literal + 1), value
  236. end
  237. function Decoder.parse_null(self, chunk)
  238. return self:parse_literal(chunk, "null", self.cnull and null)
  239. end
  240. function Decoder.parse_true(self, chunk)
  241. return self:parse_literal(chunk, "true", true)
  242. end
  243. function Decoder.parse_false(self, chunk)
  244. return self:parse_literal(chunk, "false", false)
  245. end
  246. function Decoder.parse_number(self, chunk)
  247. local chunk, start = self:fetch_until(chunk, "[^0-9eE.+-]")
  248. local number = tonumber(chunk:sub(1, start - 1))
  249. assert(number, "Invalid number specification")
  250. return chunk:sub(start), number
  251. end
  252. function Decoder.parse_string(self, chunk)
  253. local str = ""
  254. local object = nil
  255. assert(chunk:sub(1, 1) == '"', 'Expected "')
  256. chunk = chunk:sub(2)
  257. while true do
  258. local spos = chunk:find('[\\"]')
  259. if spos then
  260. str = str .. chunk:sub(1, spos - 1)
  261. local char = chunk:sub(spos, spos)
  262. if char == '"' then -- String end
  263. chunk = chunk:sub(spos + 1)
  264. break
  265. elseif char == "\\" then -- Escape sequence
  266. chunk, object = self:parse_escape(chunk:sub(spos))
  267. str = str .. object
  268. end
  269. else
  270. str = str .. chunk
  271. chunk = self:fetch()
  272. assert(chunk, "Unexpected EOS while parsing a string")
  273. end
  274. end
  275. return chunk, str
  276. end
  277. function Decoder.utf8_encode(self, s1, s2)
  278. local n = s1 * 256 + s2
  279. if n >= 0 and n <= 0x7F then
  280. return char(n)
  281. elseif n >= 0 and n <= 0x7FF then
  282. return char(
  283. bor(band(rshift(n, 6), 0x1F), 0xC0),
  284. bor(band(n, 0x3F), 0x80)
  285. )
  286. elseif n >= 0 and n <= 0xFFFF then
  287. return char(
  288. bor(band(rshift(n, 12), 0x0F), 0xE0),
  289. bor(band(rshift(n, 6), 0x3F), 0x80),
  290. bor(band(n, 0x3F), 0x80)
  291. )
  292. elseif n >= 0 and n <= 0x10FFFF then
  293. return char(
  294. bor(band(rshift(n, 18), 0x07), 0xF0),
  295. bor(band(rshift(n, 12), 0x3F), 0x80),
  296. bor(band(rshift(n, 6), 0x3F), 0x80),
  297. bor(band(n, 0x3F), 0x80)
  298. )
  299. else
  300. return "?"
  301. end
  302. end
  303. function Decoder.parse_escape(self, chunk)
  304. local str = ""
  305. chunk = self:fetch_atleast(chunk:sub(2), 1)
  306. local char = chunk:sub(1, 1)
  307. chunk = chunk:sub(2)
  308. if char == '"' then
  309. return chunk, '"'
  310. elseif char == "\\" then
  311. return chunk, "\\"
  312. elseif char == "u" then
  313. chunk = self:fetch_atleast(chunk, 4)
  314. local s1, s2 = chunk:sub(1, 2), chunk:sub(3, 4)
  315. s1, s2 = tonumber(s1, 16), tonumber(s2, 16)
  316. assert(s1 and s2, "Invalid Unicode character")
  317. return chunk:sub(5), self:utf8_encode(s1, s2)
  318. elseif char == "/" then
  319. return chunk, "/"
  320. elseif char == "b" then
  321. return chunk, "\b"
  322. elseif char == "f" then
  323. return chunk, "\f"
  324. elseif char == "n" then
  325. return chunk, "\n"
  326. elseif char == "r" then
  327. return chunk, "\r"
  328. elseif char == "t" then
  329. return chunk, "\t"
  330. else
  331. error("Unexpected escaping sequence '\\%s'" % char)
  332. end
  333. end
  334. function Decoder.parse_array(self, chunk)
  335. chunk = chunk:sub(2)
  336. local array = {}
  337. local nextp = 1
  338. local chunk, object = self:parse_delimiter(chunk, "%]")
  339. if object then
  340. return chunk, array
  341. end
  342. repeat
  343. chunk, object = self:dispatch(chunk, nil, true)
  344. table.insert(array, nextp, object)
  345. nextp = nextp + 1
  346. chunk, object = self:parse_delimiter(chunk, ",%]")
  347. assert(object, "Delimiter expected")
  348. until object == "]"
  349. return chunk, array
  350. end
  351. function Decoder.parse_object(self, chunk)
  352. chunk = chunk:sub(2)
  353. local array = {}
  354. local name
  355. local chunk, object = self:parse_delimiter(chunk, "}")
  356. if object then
  357. return chunk, array
  358. end
  359. repeat
  360. chunk = self:parse_space(chunk)
  361. assert(chunk, "Unexpected EOS")
  362. chunk, name = self:parse_string(chunk)
  363. chunk, object = self:parse_delimiter(chunk, ":")
  364. assert(object, "Separator expected")
  365. chunk, object = self:dispatch(chunk, nil, true)
  366. array[name] = object
  367. chunk, object = self:parse_delimiter(chunk, ",}")
  368. assert(object, "Delimiter expected")
  369. until object == "}"
  370. return chunk, array
  371. end
  372. function Decoder.parse_delimiter(self, chunk, delimiter)
  373. while true do
  374. chunk = self:fetch_atleast(chunk, 1)
  375. local char = chunk:sub(1, 1)
  376. if char:match("%s") then
  377. chunk = self:parse_space(chunk)
  378. assert(chunk, "Unexpected EOS")
  379. elseif char:match("[%s]" % delimiter) then
  380. return chunk:sub(2), char
  381. else
  382. return chunk, nil
  383. end
  384. end
  385. end
  386. Decoder.parsers = {
  387. ['"'] = Decoder.parse_string,
  388. ['t'] = Decoder.parse_true,
  389. ['f'] = Decoder.parse_false,
  390. ['n'] = Decoder.parse_null,
  391. ['['] = Decoder.parse_array,
  392. ['{'] = Decoder.parse_object
  393. }
  394. ActiveDecoder = util.class(Decoder)
  395. function ActiveDecoder.__init__(self, source, customnull)
  396. Decoder.__init__(self, customnull)
  397. self.source = source
  398. self.chunk = nil
  399. getmetatable(self).__call = self.get
  400. end
  401. function ActiveDecoder.get(self)
  402. local chunk, src_err, object
  403. if not self.chunk then
  404. chunk, src_err = self.source()
  405. else
  406. chunk = self.chunk
  407. end
  408. self.chunk, object = self:dispatch(chunk, src_err, true)
  409. return object
  410. end
  411. function ActiveDecoder.fetch(self)
  412. local chunk, src_err = self.source()
  413. assert(chunk or not src_err, src_err)
  414. return chunk
  415. end