summaryrefslogtreecommitdiff
path: root/Tools/lua-snapshot/snapshot_utils.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/lua-snapshot/snapshot_utils.lua')
-rw-r--r--Tools/lua-snapshot/snapshot_utils.lua133
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