2013/yue/60595411.lua

392 lines
8.1 KiB
Lua

local t = { }
local assert = assert
local Null
Null = function()
return Null
end
local StringBuilder = {
buffer = { }
}
StringBuilder.New = function(self)
local o = setmetatable({ }, self)
self.__index = self
o.buffer = { }
return o
end
StringBuilder.Append = function(self, s)
do
local _obj_0 = self.buffer
_obj_0[#_obj_0 + 1] = s
end
end
StringBuilder.ToString = function(self)
return table.concat(self.buffer)
end
local JsonWriter = {
backslashes = {
["\b"] = "\\b",
["\t"] = "\\t",
["\n"] = "\\n",
["\f"] = "\\f",
["\r"] = "\\r",
['"'] = '\\"',
["\\"] = "\\\\",
["/"] = "\\/"
}
}
JsonWriter.New = function(self)
local o = setmetatable({ }, self)
o.writer = StringBuilder:New()
self.__index = self
return o
end
JsonWriter.Append = function(self, s)
return self.writer:Append(s)
end
JsonWriter.ToString = function(self)
return self.writer:ToString()
end
JsonWriter.Write = function(self, o)
local _exp_0 = type(o)
if "nil" == _exp_0 then
return self:WriteNil()
elseif "boolean" == _exp_0 or "number" == _exp_0 then
return self:WriteString(o)
elseif "string" == _exp_0 then
return self:ParseString(o)
elseif "table" == _exp_0 then
return self:WriteTable(o)
elseif "function" == _exp_0 then
return self:WriteFunction(o)
elseif "thread" == _exp_0 or "userdata" == _exp_0 then
return self:WriteError(o)
end
end
JsonWriter.WriteNil = function(self)
return self:Append("null")
end
JsonWriter.WriteString = function(self, o)
return self:Append(tostring(o))
end
JsonWriter.ParseString = function(self, s)
self:Append('"')
self:Append(string.gsub(s, '[%z%c\\"/]', function(n)
local c = self.backslashes[n]
if c then
return c
end
return string.format("\\u%.4X", string.byte(n))
end))
return self:Append('"')
end
JsonWriter.IsArray = function(self, t)
local count = 0
local isindex
isindex = function(k)
if type(k) == "number" and k > 0 and math.floor(k) == k then
return true
end
return false
end
for k, _ in pairs(t) do
if not isindex(k) then
return false, "{", "}"
else
count = math.max(count, k)
end
end
return true, "[", "]", count
end
JsonWriter.WriteTable = function(self, t)
local ba, st, et, n = self:IsArray(t)
self:Append(st)
if ba then
for i = 1, n do
self:Write(t[i])
if i < n then
self:Append(",")
end
end
else
local first = true
for k, v in pairs(t) do
if not first then
self:Append(",")
end
first = false
self:ParseString(k)
self:Append(":")
self:Write(v)
end
end
return self:Append(et)
end
JsonWriter.WriteError = function(self, o)
return error(string.format("Encoding of %s unsupported", tostring(o)))
end
JsonWriter.WriteFunction = function(self, o)
if o == Null then
return self:WriteNil()
else
return self:WriteError(o)
end
end
local StringReader = {
s = "",
i = 0
}
StringReader.New = function(self, s)
local o = setmetatable({ }, self)
self.__index = self
o.s = s or o.s
return o
end
StringReader.Peek = function(self)
local i = self.i + 1
if i <= #self.s then
return string.sub(self.s, i, i)
end
return nil
end
StringReader.Next = function(self)
self.i = self.i + 1
if self.i <= #self.s then
return string.sub(self.s, self.i, self.i)
end
return nil
end
StringReader.All = function(self)
return self.s
end
local JsonReader = {
escapes = {
["t"] = "\t",
["n"] = "\n",
["f"] = "\f",
["r"] = "\r",
["b"] = "\b"
}
}
JsonReader.New = function(self, s)
local o = setmetatable({ }, self)
o.reader = StringReader:New(s)
self.__index = self
return o
end
JsonReader.Read = function(self)
self:SkipWhiteSpace()
local peek = self:Peek()
if not (peek ~= nil) then
return error(string.format("Nil string: '%s'", self:All()))
elseif peek == "{" then
return self:ReadObject()
elseif peek == "[" then
return self:ReadArray()
elseif peek == '"' then
return self:ReadString()
elseif string.find(peek, "[%+%-%d]") then
return self:ReadNumber()
elseif peek == "t" then
return self:ReadTrue()
elseif peek == "f" then
return self:ReadFalse()
elseif peek == "n" then
return self:ReadNull()
elseif peek == "/" then
self:ReadComment()
return self:Read()
else
return nil
end
end
JsonReader.ReadTrue = function(self)
self:TestReservedWord({
"t",
"r",
"u",
"e"
})
return true
end
JsonReader.ReadFalse = function(self)
self:TestReservedWord({
"f",
"a",
"l",
"s",
"e"
})
return false
end
JsonReader.ReadNull = function(self)
self:TestReservedWord({
"n",
"u",
"l",
"l"
})
return nil
end
JsonReader.TestReservedWord = function(self, t)
for _, v in ipairs(t) do
if self:Next() ~= v then
error(string.format("Error reading '%s': %s", table.concat(t), self:All()))
end
end
end
JsonReader.ReadNumber = function(self)
local result = self:Next()
local peek = self:Peek()
while (peek ~= nil) and string.find(peek, "[%+%-%d%.eE]") do
result = result .. self:Next()
peek = self:Peek()
end
result = tonumber(result)
if not (result ~= nil) then
return error(string.format("Invalid number: '%s'", result))
else
return result
end
end
JsonReader.ReadString = function(self)
local result = ""
assert(self:Next() == '"')
while self:Peek() ~= '"' do
local ch = self:Next()
if ch == "\\" then
ch = self:Next()
if self.escapes[ch] then
ch = self.escapes[ch]
end
end
result = result .. ch
end
assert(self:Next() == '"')
local fromunicode
fromunicode = function(m)
return string.char(tonumber(m, 16))
end
return string.gsub(result, "u%x%x(%x%x)", fromunicode)
end
JsonReader.ReadComment = function(self)
assert(self:Next() == "/")
local second = self:Next()
if second == "/" then
return self:ReadSingleLineComment()
elseif second == "*" then
return self:ReadBlockComment()
else
return error(string.format("Invalid comment: %s", self:All()))
end
end
JsonReader.ReadBlockComment = function(self)
local done = false
while not done do
local ch = self:Next()
if ch == "*" and self:Peek() == "/" then
done = true
end
if not done and ch == "/" and self:Peek() == "*" then
error(string.format("Invalid comment: %s, '/*' illegal.", self:All()))
end
end
return self:Next()
end
JsonReader.ReadSingleLineComment = function(self)
local ch = self:Next()
while ch ~= "\r" and ch ~= "\n" do
ch = self:Next()
end
end
JsonReader.ReadArray = function(self)
local result = { }
assert(self:Next() == "[")
local done = false
if self:Peek() == "]" then
done = true
end
while not done do
local item = self:Read()
result[#result + 1] = item
self:SkipWhiteSpace()
if self:Peek() == "]" then
done = true
end
if not done then
local ch = self:Next()
if ch ~= "," then
error(string.format("Invalid array: '%s' due to: '%s'", self:All(), ch))
end
end
end
assert("]" == self:Next())
return result
end
JsonReader.ReadObject = function(self)
local result = { }
assert(self:Next() == "{")
local done = false
if self:Peek() == "}" then
done = true
end
while not done do
local key = self:Read()
if type(key) ~= "string" then
error(string.format("Invalid non-string object key: %s", key))
end
self:SkipWhiteSpace()
local ch = self:Next()
if ch ~= ":" then
error(string.format("Invalid object: '%s' due to: '%s'", self:All(), ch))
end
self:SkipWhiteSpace()
local val = self:Read()
result[key] = val
self:SkipWhiteSpace()
if self:Peek() == "}" then
done = true
end
if not done then
ch = self:Next()
if ch ~= "," then
error(string.format("Invalid array: '%s' near: '%s'", self:All(), ch))
end
end
end
assert(self:Next() == "}")
return result
end
JsonReader.SkipWhiteSpace = function(self)
local p = self:Peek()
while (p ~= nil) and string.find(p, "[%s/]") do
if p == "/" then
self:ReadComment()
else
self:Next()
end
p = self:Peek()
end
end
JsonReader.Peek = function(self)
return self.reader:Peek()
end
JsonReader.Next = function(self)
return self.reader:Next()
end
JsonReader.All = function(self)
return self.reader:All()
end
local Encode
Encode = function(o)
local _with_0 = JsonWriter:New()
_with_0:Write(o)
_with_0:ToString()
return _with_0
end
local Decode
Decode = function(s)
local _with_0 = JsonReader:New(s)
_with_0:Read()
return _with_0
end