Lua: Descending Table Traversal Round 2: Iterator Object


/ Published in: Lua
Save to your folder(s)



Copy this code and paste it in your HTML
  1. traverse = {}
  2. function traverse:new(tname)
  3. local o = {}
  4. o.names = {}
  5. o.queue = {}
  6. o.cur = {
  7. tbl = nil,
  8. path = nil,
  9. state = nil,
  10. }
  11.  
  12. local mt = {}
  13. function mt:__call(tn)
  14. return o:iter(tn)
  15. end
  16. mt.__index = self
  17. setmetatable(o, mt)
  18.  
  19. if tname then
  20. o:enqueue(tname)
  21. end
  22. return o
  23. end
  24. function traverse:next()
  25. local v
  26. local names, queue, cur = self.names, self.queue, self.cur
  27.  
  28. local function _poptbl()
  29. if cur.tbl then
  30. names[cur.tbl] = nil
  31. end
  32. cur.tbl = table.remove(queue, 1)
  33. cur.path = names[cur.tbl]
  34. cur.state = nil
  35. end
  36.  
  37. repeat
  38. -- Find something to return to the user...
  39. if not cur.state then
  40. -- Pop a new table off the stack
  41. _poptbl()
  42. if not cur.tbl then
  43. -- No more tables to process
  44. return nil
  45. end
  46. end
  47. cur.state,v = next(cur.tbl, cur.state)
  48. until cur.state
  49.  
  50. if type(v) == "table" then
  51. local path = cur.path.."."..cur.state
  52. names[v] = path
  53. table.insert(queue, v)
  54. end
  55. return cur.path,cur.tbl,cur.state,v
  56. end
  57. function traverse:iter(tname)
  58. if tname then
  59. self:enqueue(tname)
  60. end
  61. return function(...) return self:next(unpack(arg)) end, nil, nil
  62. end
  63. function traverse:enqueue(tname)
  64. local v = _G[tname]
  65. table.insert(self.queue, v)
  66. self.names[v] = tname
  67. end
  68. function traverse:reset()
  69. self.names = {}
  70. self.queue = {}
  71. end
  72. local traverse_mt = {
  73. __call = function(self, tname)
  74. if tname then
  75. return self:new(tname):iter()
  76. else
  77. return self:new()
  78. end
  79. end
  80. }
  81. setmetatable(traverse, traverse_mt)
  82. foo = {a={},b={},c={"bar"},d={e={},f={"moo"}},1,2,3,4,5}
  83. bar = {"alpha", "beta", "theta", omega = {}}
  84.  
  85. local mytraverser = traverse()
  86. mytraverser:enqueue("bar")
  87. mytraverser:enqueue("foo")
  88. for p,t,k,v in mytraverser() do
  89. --for p,t,k,v in traverse('foo') do
  90. print(string.format("%s[%s] = %s",tostring(p),tostring(k),tostring(v)))
  91. end
  92. bar[1] = alpha
  93. bar[2] = beta
  94. bar[3] = theta
  95. bar[omega] = table: 0x510650
  96. foo[1] = 1
  97. foo[2] = 2
  98. foo[3] = 3
  99. foo[4] = 4
  100. foo[5] = 5
  101. foo[a] = table: 0x5102d0
  102. foo[c] = table: 0x510370
  103. foo[b] = table: 0x510320
  104. foo[d] = table: 0x5103c0
  105. foo.c[1] = bar
  106. foo.d[e] = table: 0x5104c0
  107. foo.d[f] = table: 0x510510
  108. foo.d.f[1] = moo

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.