snapshot_utils.lua 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. local function trim(s)
  2. return (s:gsub("^%s*(.-)%s*$", "%1"))
  3. end
  4. local function cleanup_key_value(input)
  5. local ret = {}
  6. for k, v in pairs(input) do
  7. local key = tostring(k)
  8. local clean_key = key:gmatch("userdata: 0x(%w+)")()
  9. local val_type
  10. if v:find("^table") then
  11. val_type = "table"
  12. elseif v:find("^func:") then
  13. val_type = "func"
  14. elseif v:find("^thread:") then
  15. val_type = "thread"
  16. else
  17. val_type = "userdata"
  18. end
  19. local parent = v:match("0x(%w+) :")
  20. local _, finish = v:find("0x(%w+) : ")
  21. local extra = v:sub(finish + 1, #v)
  22. local val_key = extra:match("(%w+) :")
  23. local trim_extra = trim(extra)
  24. if not val_key then
  25. val_key = trim_extra
  26. end
  27. ret[clean_key] = {
  28. val_type = val_type,
  29. parent = parent,
  30. extra = trim_extra,
  31. key = val_key,
  32. }
  33. end
  34. return ret
  35. end
  36. local function reduce(input_diff)
  37. local a_set = {}
  38. local b_set = {}
  39. local step = 0
  40. -- 先收入叶节点
  41. for self_addr, info in pairs(input_diff) do
  42. local flag = true
  43. for _, node in pairs(input_diff) do
  44. if node.parent == self_addr then
  45. flag = false
  46. break
  47. end
  48. end
  49. if flag then
  50. a_set[self_addr] = info
  51. end
  52. end
  53. step = step + 1
  54. local MAX_DEPTH = 32
  55. local dirty
  56. while step < MAX_DEPTH do
  57. dirty = false
  58. -- 遍历叶节点,将parent拉进来
  59. for self_addr, info in pairs(a_set) do
  60. local key = info.key
  61. local parent = info.parent
  62. local parent_node = input_diff[parent]
  63. if parent_node then
  64. if not b_set[parent] then
  65. b_set[parent] = parent_node
  66. end
  67. parent_node[key] = info
  68. step = step + 1
  69. dirty = true
  70. else
  71. b_set[self_addr] = info
  72. end
  73. a_set[self_addr] = nil
  74. end
  75. -- 遍历节点,将祖父节点拉进来
  76. for self_addr, info in pairs(b_set) do
  77. local key = info.key
  78. local parent = info.parent
  79. local parent_node = input_diff[parent]
  80. if parent_node then
  81. if not a_set[parent] then
  82. a_set[parent] = parent_node
  83. end
  84. parent_node[key] = info
  85. step = step + 1
  86. dirty = true
  87. else
  88. a_set[self_addr] = info
  89. end
  90. b_set[self_addr] = nil
  91. end
  92. if not dirty then
  93. break
  94. end
  95. end
  96. return a_set
  97. end
  98. local unwanted_key = {
  99. --extra = 1,
  100. --key = 1,
  101. parent = 1,
  102. }
  103. local function cleanup_forest(input)
  104. local cache = {[input] = "."}
  105. local function _clean(forest)
  106. if cache[forest] then
  107. return
  108. end
  109. for k, v in pairs(forest) do
  110. if unwanted_key[k] then
  111. forest[k] = nil
  112. else
  113. if type(v) == "table" then
  114. cleanup_forest(v)
  115. end
  116. end
  117. end
  118. end
  119. return _clean(input)
  120. end
  121. local M = {}
  122. function M.construct_indentation(input_diff)
  123. local clean_diff = cleanup_key_value(input_diff)
  124. local forest = reduce(clean_diff)
  125. cleanup_forest(forest)
  126. return forest
  127. end
  128. return M