diff options
Diffstat (limited to 'Tools/lua-snapshot/snapshot_utils.lua')
-rw-r--r-- | Tools/lua-snapshot/snapshot_utils.lua | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/Tools/lua-snapshot/snapshot_utils.lua b/Tools/lua-snapshot/snapshot_utils.lua new file mode 100644 index 0000000..a041ba3 --- /dev/null +++ b/Tools/lua-snapshot/snapshot_utils.lua @@ -0,0 +1,133 @@ +local function trim(s) + return (s:gsub("^%s*(.-)%s*$", "%1")) +end + +local function cleanup_key_value(input) + local ret = {} + for k, v in pairs(input) do + local key = tostring(k) + local clean_key = key:gmatch("userdata: 0x(%w+)")() + local val_type + if v:find("^table") then + val_type = "table" + elseif v:find("^func:") then + val_type = "func" + elseif v:find("^thread:") then + val_type = "thread" + else + val_type = "userdata" + end + local parent = v:match("0x(%w+) :") + local _, finish = v:find("0x(%w+) : ") + local extra = v:sub(finish + 1, #v) + local val_key = extra:match("(%w+) :") + local trim_extra = trim(extra) + if not val_key then + val_key = trim_extra + end + ret[clean_key] = { + val_type = val_type, + parent = parent, + extra = trim_extra, + key = val_key, + } + end + return ret +end + +local function reduce(input_diff) + local a_set = {} + local b_set = {} + local step = 0 + -- 先收入叶节点 + for self_addr, info in pairs(input_diff) do + local flag = true + for _, node in pairs(input_diff) do + if node.parent == self_addr then + flag = false + break + end + end + if flag then + a_set[self_addr] = info + end + end + step = step + 1 + local MAX_DEPTH = 32 + local dirty + while step < MAX_DEPTH do + dirty = false + -- 遍历叶节点,将parent拉进来 + for self_addr, info in pairs(a_set) do + local key = info.key + local parent = info.parent + local parent_node = input_diff[parent] + if parent_node then + if not b_set[parent] then + b_set[parent] = parent_node + end + parent_node[key] = info + step = step + 1 + dirty = true + else + b_set[self_addr] = info + end + a_set[self_addr] = nil + end + -- 遍历节点,将祖父节点拉进来 + for self_addr, info in pairs(b_set) do + local key = info.key + local parent = info.parent + local parent_node = input_diff[parent] + if parent_node then + if not a_set[parent] then + a_set[parent] = parent_node + end + parent_node[key] = info + step = step + 1 + dirty = true + else + a_set[self_addr] = info + end + b_set[self_addr] = nil + end + if not dirty then + break + end + end + return a_set +end + +local unwanted_key = { + --extra = 1, + --key = 1, + parent = 1, +} +local function cleanup_forest(input) + local cache = {[input] = "."} + local function _clean(forest) + if cache[forest] then + return + end + for k, v in pairs(forest) do + if unwanted_key[k] then + forest[k] = nil + else + if type(v) == "table" then + cleanup_forest(v) + end + end + end + end + return _clean(input) +end + +local M = {} +function M.construct_indentation(input_diff) + local clean_diff = cleanup_key_value(input_diff) + local forest = reduce(clean_diff) + cleanup_forest(forest) + return forest +end + +return M |