123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- 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
|