Changeset

4894:c874dc4ccbd7

util.multitable: Add :iter() method to iterate over results at a fixed depth (parameters are equivalent to :search())
author Matthew Wild <mwild1@gmail.com>
date Sat, 19 May 2012 04:12:41 +0100
parents 4893:98ff89ab5d1d
children 4895:36df30395c44
files util/multitable.lua
diffstat 1 files changed, 38 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/util/multitable.lua	Fri May 18 23:53:02 2012 +0100
+++ b/util/multitable.lua	Sat May 19 04:12:41 2012 +0100
@@ -6,12 +6,9 @@
 -- COPYING file in the source package for more information.
 --
 
-
-
 local select = select;
-local t_insert = table.insert;
-local pairs = pairs;
-local next = next;
+local t_insert, t_remove = table.insert, table.remove;
+local unpack, pairs, next, type = unpack, pairs, next, type;
 
 module "multitable"
 
@@ -129,6 +126,41 @@
 	return results;
 end
 
+function iter(self, ...)
+	local query = { ... };
+	local maxdepth = select("#", ...);
+	local stack = { self.data };
+	local keys = { };
+	local function it(self)
+		local depth = #stack;
+		local key = next(stack[depth], keys[depth]);
+		if key == nil then -- Go up the stack
+			t_remove(stack);
+			t_remove(keys);
+			if depth > 1 then
+				return it(self);
+			end
+			return; -- The end
+		else
+			keys[depth] = key;
+		end
+		local value = stack[depth][key];
+		if depth == maxdepth then -- Result
+			local result = {}; -- Collect keys forming path to result
+			for i = 1, depth do
+				result[i] = keys[i];
+			end
+			return unpack(result, 1, depth);
+		else
+			if (query[depth] == nil or key == query[depth]) and type(value) == "table" then -- Descend
+				t_insert(stack, value);
+			end
+			return it(self);
+		end
+	end;
+	return it, self;
+end
+
 function new()
 	return {
 		data = {};
@@ -138,6 +170,7 @@
 		remove = remove;
 		search = search;
 		search_add = search_add;
+		iter = iter;
 	};
 end