Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
lua-nucleo/lua-nucleo/tstr.lua
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
116 lines (101 sloc)
3.33 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -------------------------------------------------------------------------------- | |
| --- Visualization of non-recursive tables. | |
| -- @module lua-nucleo.tstr | |
| -- This file is a part of lua-nucleo library | |
| -- @copyright lua-nucleo authors (see file `COPYRIGHT` for the license) | |
| -------------------------------------------------------------------------------- | |
| local pairs, ipairs, type, tostring = pairs, ipairs, type, tostring | |
| local table_concat = table.concat | |
| local string_match, string_format = string.match, string.format | |
| local lua_keywords = import 'lua-nucleo/language.lua' { 'lua_keywords' } | |
| local serialize_number = import 'lua-nucleo/string.lua' { 'serialize_number' } | |
| local tstr, tstr_cat | |
| do | |
| local function impl(t, cat, visited) | |
| local t_type = type(t) | |
| if t_type == "table" then | |
| if not visited[t] then | |
| visited[t] = true | |
| cat("{") | |
| -- Serialize numeric indices | |
| local next_i = 0 | |
| while t[next_i + 1] ~= nil and next_i < #t do | |
| next_i = next_i + 1 | |
| if next_i > 1 then -- TODO: Move condition out of the loop | |
| cat(",") | |
| end | |
| impl(t[next_i], cat, visited) | |
| end | |
| next_i = next_i + 1 | |
| -- Serialize hash part | |
| -- Skipping comma only at first element if there is no numeric part. | |
| local need_comma = (next_i > 1) | |
| for k, v in pairs(t) do | |
| local k_type = type(k) | |
| if k_type == "string" then | |
| if need_comma then | |
| cat(",") | |
| end | |
| need_comma = true | |
| -- TODO: Need "%q" analogue, which would put quotes | |
| -- only if string does not match regexp below | |
| if not lua_keywords[k] and string_match(k, "^[%a_][%a%d_]*$") then | |
| cat(k) cat("=") | |
| else | |
| cat(string_format("[%q]=", k)) | |
| end | |
| impl(v, cat, visited) | |
| else | |
| if | |
| k_type ~= "number" or -- non-string non-number | |
| k >= next_i or k < 1 or -- integer key in hash part of the table | |
| k % 1 ~= 0 -- non-integer key | |
| then | |
| if need_comma then | |
| cat(",") | |
| end | |
| need_comma = true | |
| cat("[") | |
| impl(k, cat, visited) | |
| cat("]=") | |
| impl(v, cat, visited) | |
| end | |
| end | |
| end | |
| cat("}") | |
| visited[t] = nil | |
| else | |
| -- Note this loses information on recursive tables | |
| cat('"table (recursive)"') | |
| end | |
| elseif t_type == "number" then | |
| cat(serialize_number(t)) | |
| elseif t_type == "boolean" then | |
| cat(tostring(t)) | |
| elseif t == nil then | |
| cat("nil") | |
| else | |
| -- Note this converts non-serializable types to strings | |
| cat(string_format("%q", tostring(t))) | |
| end | |
| end | |
| -- This function is optimized for logging. | |
| -- Unless you are serializing "simple" tables, | |
| -- do not use this function for serialization. | |
| -- This function intentionally loses information on nested recursive tables | |
| -- and on non-serializable types like functions, threads and userdata. | |
| tstr_cat = function(cat, t) | |
| impl(t, cat, {}) | |
| end | |
| tstr = function(t) | |
| local buf = {} | |
| local cat = function(v) buf[#buf + 1] = v end | |
| impl(t, cat, {}) | |
| return table_concat(buf) | |
| end | |
| end | |
| return | |
| { | |
| tstr = tstr; | |
| tstr_cat = tstr_cat; | |
| } |