Close
    Search Search

    Módulo: JSON

      Módulo: JSON

      A documentação para este módulo pode ser criada no Módulo: JSON / doc


      - - json.lua - - Copyright (c) 2018 rxi - - A permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma cópia - deste software e dos arquivos de documentação associados (o "Software" ), para negociar - o Software sem restrições, incluindo, sem limitação, os direitos de - usar, copiar, modificar, mesclar, publicar, distribuir, sublicenciar e / ou vender cópias - do Software e permitir que as pessoas para quem o Software é fornecido - assim, sujeito às seguintes condições: - - O aviso de copyright acima e este aviso de permissão devem ser incluídos em todas as cópias ou partes substanciais do Software. - - O SOFTWARE É FORNECIDO "COMO ESTÁ", SEM QUALQUER TIPO DE GARANTIA, EXPRESSA OU - IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO ÀS GARANTIAS DE COMERCIALIZAÇÃO, - ADEQUAÇÃO A UM DETERMINADO FIM E NÃO VIOLAÇÃO. EM NENHUMA HIPÓTESE OS - AUTORES OU TITULARES DOS DIREITOS AUTORAIS SERÃO RESPONSÁVEIS POR QUALQUER RECLAMAÇÃO, DANOS OU OUTROS - RESPONSABILIDADE, SEJA EM AÇÃO DE CONTRATO, DELITO OU DE OUTRA FORMA, DECORRENTE DE, - FORA DE OU EM CONEXÃO COM O SOFTWARE OU USO OU OUTRAS NEGOCIAÇÕES NO - SOFTWARE. - json local = {_version = "0.1.1"} ------------------------------------ ------------------------------------------- - Codificar ---- -------------------------------------------------- ------------------------- codificação local local escape_char_map = {[""] = "\", ["" "] =" "", ["b"] = " b", ["f"] = " f", ["n"] = " n", ["r"] = " r", ["t "] =" t ",} local escape_char_map_inv = {[" / "] =" / "} para k, v em pares (escape_char_map) faça escape_char_map_inv [v] = k fim da função local escape_char (c) retorne escape_char_map [ c] ou string.format (" u% 04x", c: byte ()) finalizar função local encode_nil (val) retornar "null" finalizar função local encode_table (val, pilha) local res = {} pilha = pilha ou { } -- Referencia circular? if stack [val] then error ("circular reference") end stack [val] = true if val [1] ~ = nil ou next (val) == nil then - Tratar como array - as chaves de verificação são válidas e não é local esparso n = 0 para k em pares (val) faça if type (k) ~ = "número" então erro ("tabela inválida: tipos de chave mista ou inválidos") end n = n + 1 end if n ~ = #val then error ("tabela inválida: array esparso") end - Codifica para i, v em ipairs (val) do table.insert (res, encode (v, stack)) end stack [val] = nil return "[ ".. table.concat (res, ",") .. "]" else - Tratar como um objeto para k, v em pares (val) fazer if type (k) ~ = "string" then error ("tabela inválida: tipos de chave mista ou inválida") end table.insert (res , codificar (k, pilha) .. ":" .. encode (v, stack)) end stack [val] = nil return "{" .. table.concat (res, ",") .. "}" fim fim função local encode_string (val) return '"' .. val: gsub ('[% z1-31 "]', escape_char) .. '"' fim da função local encode_number (val) - Verifique se há NaN, -inf e inf se val ~ = val ou val <= -math.huge ou val> = math.huge então erro (" valor numérico inesperado '". . tostring (val) .. "'") end return string.format ("%. 14g", val) end local type_func_map = {["nil"] = encode_nil, ["table"] = encode_table, ["string"] = encode_string, ["número "] = encode_number, [" boolean "] = tostring,} encode = function (val, stack) local t = type (val) local f = type_func_map [t] if f then return f (val, stack) end error (" tipo inesperado '".. t .. "'") end function json.encode (val) return (encode (val)) end ------------------------------ ------------------------------------------------- - - Decodificar ------------------------------------------------ ------------------------------- local parse local function create_set (...) local res = {} para i = 1 , select ("#", ...) do res [select (i, ...)] = true end return res end local space_chars = create_set ("", "t", "r", "n") local delim_chars = create_set ("", "t", "r", "n", "]", "}", ",") escape_chars local = create_set ("", "/", '"'," b "," f "," n "," r "," t "," u ") literais locais = create_set (" true "," false "," null ") local literal_map = {[" true "] = true , ["false"] = false, ["null"] = nil,} função local next_char (str, idx, set, negate) para i = idx, #str do if set [str: sub (i, i)] ~ = negar e então retornar i end end return #str + 1 end local function decode_error (str, idx, msg) local line_count = 1 local col_count = 1 para i = 1, idx - 1 do col_count = col_count + 1 se str: sub (i, i) == "n" o n line_count = line_count + 1 col_count = 1 end end error (string.format ("% s na linha% d col% d", msg, line_count, col_count)) end função local codepoint_to_utf8 (n) - http: // scripts .sil.org / cms / scripts / page.php? site_id = nrsi & id = iws-apêndicea local f = math.floor se n <= 0x7f então retorna string.char (n) elseif n <= 0x7ff então retorna string.char ( f (n / 64) + 192, n% 64 + 128) elseif n <= 0xffff então retorna string.char (f (n / 4096) + 224, f (n% 4096/64) + 128, n% 64 + 128) elseif n <= 0x10ffff então retorna string.char (f (n / 262144) + 240, f (n% 262144/4096) + 128, f (n% 4096/64) + 128, n% 64 + 128) end error (string.format ("invalid unicode codepoint '% x'", n)) end local function parse_unicode_escape (s) local n1 = tonumber (s: sub (3, 6), 16) local n2 = tonumber (s: sub (9, 12), 16) - Par substituto? se n2 retornar codepoint_to_utf8 ((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) else retornar codepoint_to_utf8 (n1) end end local função parse_string (str, i) local has_unicode_escape = false local has_surrogate_escape = false local has_escape = false local has_escape = false local has_escape local último para j = i + 1, #str faz local x = str: byte (j) se x <32 então decode_error (str, j, "caractere de controle na string") fim se último == 92 então - " "(caractere de escape) se x == 117 então -" u "(sequência de escape unicode) hex local = str: sub (j + 1, j + 5) se não hex: find ("% x% x% x% x ") então decode_error (str, j," escape unicode inválido na string ") end if hex: find (" ^ [dD] [89aAbB] ") then has_surrogate_escape = true else has_unicode_escape = true end else local c = string.char (x) se não escape_chars [c], então decode_error (str, j, "caractere de escape inválido '" .. c .. "'na string") end has_escape = true end last = nil elseif x == 34 then -' "'(final da string) local s = str: sub (i + 1, j - 1) se has_surrogate_escape então s = s: gsub (" u [dD] [89aAbB] .. u ....", parse_unicode_escape) end if has_unicode_escape then s = s: gsub (" u ....", parse_unicode_escape) end if has_escape then s = s: gsub (".", escape_char_map_inv) end return s, j + 1 else last = x end end decode_error (str, i, "aspas de fechamento esperadas para string") end local função parse_number (str, i) local x = next_char (str, i, delim_chars) local s = str: sub (i, x - 1) local n = tonumber (s) se não n, então decode_error (str, i, "número inválido '" .. s .. "'") end return n, x end função local parse_literal (str, i) local x = next_char (str, i, delim_chars) palavra local = str: sub (i, x - 1) se não literais [palavra] então decode_error (str, i, "literal inválido '" .. palavra .. "'") end return literal_map [palavra], x end local function parse_array (str, i) local res = {} local n = 1 i = i + 1 enquanto 1 faz local xi = next_char (str, i, space_chars, true ) - Vazio / fim da matriz? if str: sub (i, i) == "]" then i = i + 1 break end - Read token x, i = parse (str, i) res [n] = xn = n + 1 - Next token i = next_char (str, i, space_chars, true) local chr = str: sub (i, i) i = i + 1 se chr == "]" então interrompa o final se chr ~ = "," then decode_error (str, i, "esperado ']' ou ','") end end return res, i end local function parse_object (str, i) local res = {} i = i + 1 enquanto 1 faz a chave local, val i = next_char (str , i, space_chars, true) - Vazio / fim do objeto? if str: sub (i, i) == "}" then i = i + 1 break end - Read key if str: sub (i, i) ~ = '"' then decode_error (str, i," string esperada para a chave ") end key, i = parse (str, i) - Ler ':' delimitador i = next_char (str, i, space_chars, true) if str: sub (i, i) ~ =": "then decode_error (str, i, "esperado ':' após a chave") end i = next_char (str, i + 1, space_chars, true) - Ler o valor val, i = parse (str, i) - Definir res [chave] = val - Próximo token i = next_char (str, i, space_chars, true) local chr = str: sub (i, i) i = i + 1 se chr == "}" então interromper fim se chr ~ = ", "então decode_error (str, i," esperado '}' ou ',' ") end end return res, i end local char_func_map = {['"'] = parse_string, ["0"] = parse_number, ["1" ] = parse_number, ["2"] = parse_number, ["3"] = parse_number, ["4"] = parse_number, ["5"] = parse_number, ["6"] = parse_number, ["7"] = parse_number, ["8"] = parse_number, ["9"] = parse_number, ["-"] = parse_number, ["t"] = parse_literal, ["f"] = parse_literal, ["n"] = parse_l iteral, ["["] = parse_array, ["{"] = parse_object,} parse = function (str, idx) local chr = str: sub (idx, idx) local f = char_func_map [chr] se f então retornar f (str, idx) end decode_error (str, idx, "caráter inesperado '" .. chr .. "'") função final json.decode (str) if type (str) ~ = "string" then error ("argumento esperado do tipo string, obtido" ..


      Adicione um comentário do Módulo: JSON
      Comentário enviado com sucesso! Vamos analisá-lo nas próximas horas.