aboutsummaryrefslogtreecommitdiffstats
path: root/util/iterators.lua
diff options
context:
space:
mode:
Diffstat (limited to 'util/iterators.lua')
-rw-r--r--util/iterators.lua159
1 files changed, 159 insertions, 0 deletions
diff --git a/util/iterators.lua b/util/iterators.lua
new file mode 100644
index 00000000..1f6aacb8
--- /dev/null
+++ b/util/iterators.lua
@@ -0,0 +1,159 @@
+-- Prosody IM
+-- Copyright (C) 2008-2010 Matthew Wild
+-- Copyright (C) 2008-2010 Waqas Hussain
+--
+-- This project is MIT/X11 licensed. Please see the
+-- COPYING file in the source package for more information.
+--
+
+--[[ Iterators ]]--
+
+local it = {};
+
+-- Reverse an iterator
+function it.reverse(f, s, var)
+ local results = {};
+
+ -- First call the normal iterator
+ while true do
+ local ret = { f(s, var) };
+ var = ret[1];
+ if var == nil then break; end
+ table.insert(results, 1, ret);
+ end
+
+ -- Then return our reverse one
+ local i,max = 0, #results;
+ return function (results)
+ if i<max then
+ i = i + 1;
+ return unpack(results[i]);
+ end
+ end, results;
+end
+
+-- Iterate only over keys in a table
+local function _keys_it(t, key)
+ return (next(t, key));
+end
+function it.keys(t)
+ return _keys_it, t;
+end
+
+-- Iterate only over values in a table
+function it.values(t)
+ local key, val;
+ return function (t)
+ key, val = next(t, key);
+ return val;
+ end, t;
+end
+
+-- Given an iterator, iterate only over unique items
+function it.unique(f, s, var)
+ local set = {};
+
+ return function ()
+ while true do
+ local ret = { f(s, var) };
+ var = ret[1];
+ if var == nil then break; end
+ if not set[var] then
+ set[var] = true;
+ return var;
+ end
+ end
+ end;
+end
+
+--[[ Return the number of items an iterator returns ]]--
+function it.count(f, s, var)
+ local x = 0;
+
+ while true do
+ local ret = { f(s, var) };
+ var = ret[1];
+ if var == nil then break; end
+ x = x + 1;
+ end
+
+ return x;
+end
+
+-- Return the first n items an iterator returns
+function it.head(n, f, s, var)
+ local c = 0;
+ return function (s, var)
+ if c >= n then
+ return nil;
+ end
+ c = c + 1;
+ return f(s, var);
+ end, s;
+end
+
+-- Skip the first n items an iterator returns
+function it.skip(n, f, s, var)
+ for i=1,n do
+ var = f(s, var);
+ end
+ return f, s, var;
+end
+
+-- Return the last n items an iterator returns
+function it.tail(n, f, s, var)
+ local results, count = {}, 0;
+ while true do
+ local ret = { f(s, var) };
+ var = ret[1];
+ if var == nil then break; end
+ results[(count%n)+1] = ret;
+ count = count + 1;
+ end
+
+ if n > count then n = count; end
+
+ local pos = 0;
+ return function ()
+ pos = pos + 1;
+ if pos > n then return nil; end
+ return unpack(results[((count-1+pos)%n)+1]);
+ end
+ --return reverse(head(n, reverse(f, s, var)));
+end
+
+local function _ripairs_iter(t, key) if key > 1 then return key-1, t[key-1]; end end
+function it.ripairs(t)
+ return _ripairs_iter, t, #t+1;
+end
+
+local function _range_iter(max, curr) if curr < max then return curr + 1; end end
+function it.range(x, y)
+ if not y then x, y = 1, x; end -- Default to 1..x if y not given
+ return _range_iter, y, x-1;
+end
+
+-- Convert the values returned by an iterator to an array
+function it.to_array(f, s, var)
+ local t, var = {};
+ while true do
+ var = f(s, var);
+ if var == nil then break; end
+ table.insert(t, var);
+ end
+ return t;
+end
+
+-- Treat the return of an iterator as key,value pairs,
+-- and build a table
+function it.to_table(f, s, var)
+ local t, var2 = {};
+ while true do
+ var, var2 = f(s, var);
+ if var == nil then break; end
+ t[var] = var2;
+ end
+ return t;
+end
+
+return it;