IMPORTANT: due to a drive failure, as of 13-Mar-2021, the Mercurial repository had to be re-mirrored, which changed every commit SHA. The old SHAs and trees are backed up in the vault branches. Please migrate to the new branches as soon as you can.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
prosody/util/array.lua

130 lines
2.7 KiB

-- Prosody IM
-- Copyright (C) 2008-2009 Matthew Wild
-- Copyright (C) 2008-2009 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local t_insert, t_sort, t_remove, t_concat
= table.insert, table.sort, table.remove, table.concat;
local array = {};
local array_base = {};
local array_methods = {};
local array_mt = { __index = array_methods, __tostring = function (array) return array:concat(", "); end };
local function new_array(_, t)
return setmetatable(t or {}, array_mt);
end
function array_mt.__add(a1, a2)
local res = new_array();
return res:append(a1):append(a2);
end
setmetatable(array, { __call = new_array });
function array_base.map(outa, ina, func)
for k,v in ipairs(ina) do
outa[k] = func(v);
end
return outa;
end
function array_base.filter(outa, ina, func)
local inplace, start_length = ina == outa, #ina;
local write = 1;
for read=1,start_length do
local v = ina[read];
if func(v) then
outa[write] = v;
write = write + 1;
end
end
if inplace and write < start_length then
for i=write,start_length do
outa[i] = nil;
end
end
return outa;
end
function array_base.sort(outa, ina, ...)
if ina ~= outa then
outa:append(ina);
end
t_sort(outa, ...);
return outa;
end
--- These methods only mutate
function array_methods:random()
return self[math.random(1,#self)];
end
function array_methods:shuffle(outa, ina)
local len = #self;
for i=1,#self do
local r = math.random(i,len);
self[i], self[r] = self[r], self[i];
end
return self;
end
function array_methods:reverse()
local len = #self-1;
for i=len,1,-1 do
self:push(self[i]);
self:pop(i);
end
return self;
end
function array_methods:append(array)
local len,len2 = #self, #array;
for i=1,len2 do
self[len+i] = array[i];
end
return self;
end
array_methods.push = table.insert;
array_methods.pop = table.remove;
array_methods.concat = table.concat;
array_methods.length = function (t) return #t; end
--- These methods always create a new array
function array.collect(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 setmetatable(t, array_mt);
end
---
-- Setup methods from array_base
for method, f in pairs(array_base) do
local method = method; -- Yes, this is necessary :)
local base_method = f;
-- Setup global array method which makes new array
array[method] = function (old_a, ...)
local a = new_array();
return base_method(a, old_a, ...);
end
-- Setup per-array (mutating) method
array_methods[method] = function (self, ...)
return base_method(self, self, ...);
end
end
_G.array = array;
module("array");
return array;