efl/src/bindings/lua/eina/list.lua

308 lines
10 KiB
Lua

-- EFL LuaJIT bindings: Eina (list module)
-- For use with Elua
local ffi = require("ffi")
local iterator = require("eina.iterator")
local accessor = require("eina.accessor")
ffi.cdef [[
typedef unsigned char Eina_Bool;
typedef struct _Eina_List Eina_List;
typedef struct _Eina_List_Accounting Eina_List_Accounting;
typedef struct _Eina_List_T {
void *data;
Eina_List *next;
Eina_List *prev;
struct {
Eina_List *last;
unsigned int count;
} *accounting;
} Eina_List_T;
/* Eina_List *eina_list_append(Eina_List *list, const void *data);
Eina_List *eina_list_prepend(Eina_List *list, const void *data);
Eina_List *eina_list_append_relative(Eina_List *list, const void *data, const void *relative);
Eina_List *eina_list_append_relative_list(Eina_List *list, const void *data, Eina_List *relative);
Eina_List *eina_list_prepend_relative(Eina_List *list, const void *data, const void *relative);
Eina_List *eina_list_prepend_relative_list(Eina_List *list, const void *data, Eina_List *relative);
Eina_List *eina_list_sorted_insert(Eina_List *list, Eina_Compare_Cb func, const void *data);
Eina_List *eina_list_remove(Eina_List *list, const void *data);
Eina_List *eina_list_remove_list(Eina_List *list, Eina_List *remove_list);
Eina_List *eina_list_promote_list(Eina_List *list, Eina_List *move_list);
Eina_List *eina_list_demote_list(Eina_List *list, Eina_List *move_list);
void *eina_list_data_find(const Eina_List *list, const void *data);
Eina_List *eina_list_data_find_list(const Eina_List *list, const void *data);
Eina_Bool eina_list_move(Eina_List **to, Eina_List **from, void *data);
Eina_Bool eina_list_move_list(Eina_List **to, Eina_List **from, Eina_List *data);
Eina_List *eina_list_free(Eina_List *list);
*/
void *eina_list_nth(const Eina_List *list, unsigned int n);
Eina_List *eina_list_nth_list(const Eina_List *list, unsigned int n);
/* Eina_List *eina_list_reverse(Eina_List *list);
Eina_List *eina_list_reverse_clone(const Eina_List *list);
Eina_List *eina_list_clone(const Eina_List *list);
Eina_List *eina_list_sort(Eina_List *list, unsigned int limit, Eina_Compare_Cb func);
Eina_List *eina_list_shuffle(Eina_List *list, Eina_Random_Cb func);
Eina_List *eina_list_merge(Eina_List *left, Eina_List *right);
Eina_List *eina_list_sorted_merge(Eina_List *left, Eina_List *right, Eina_Compare_Cb func);
Eina_List *eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right);
Eina_List *eina_list_search_sorted_near_list(const Eina_List *list, Eina_Compare_Cb func, const void *data, int *result_cmp);
Eina_List *eina_list_search_sorted_list(const Eina_List *list, Eina_Compare_Cb func, const void *data);
void *eina_list_search_sorted(const Eina_List *list, Eina_Compare_Cb func, const void *data);
Eina_List *eina_list_search_unsorted_list(const Eina_List *list, Eina_Compare_Cb func, const void *data);
void *eina_list_search_unsorted(const Eina_List *list, Eina_Compare_Cb func, const void *data);
*/
Eina_Iterator *eina_list_iterator_new(const Eina_List *list);
Eina_Iterator *eina_list_iterator_reversed_new(const Eina_List *list);
Eina_Accessor *eina_list_accessor_new(const Eina_List *list);
]]
local cutil = require("cutil")
local util = require("util")
local M = {}
local eina
local init = function()
eina = util.lib_load("eina")
end
local shutdown = function()
util.lib_unload("eina")
end
cutil.init_module(init, shutdown)
local Iterator = iterator.Iterator
local dgetmt = debug.getmetatable
local List_Iterator = Iterator:clone {
__ctor = function(self, selfmt, list)
if not list or list == ffi.nullptr then
return Iterator.__ctor(self, selfmt, nil)
end
selfmt.__list = list
return Iterator.__ctor(self, selfmt,
eina.eina_list_iterator_new(dgetmt(list).__list))
end,
next = function(self)
local v = Iterator.next(self)
if not v then return nil end
return dgetmt(self).__list:data_get(v)
end
}
local List_Reverse_Iterator = Iterator:clone {
__ctor = function(self, selfmt, list)
if not list or list == ffi.nullptr then
return Iterator.__ctor(self, selfmt, nil)
end
selfmt.__list = list
return Iterator.__ctor(self, selfmt,
eina.eina_list_iterator_reversed_new(dgetmt(list).__list))
end,
next = function(self)
local v = Iterator.next(self)
if not v then return nil end
return self.__list:data_get(v)
end
}
local Accessor = accessor.Accessor
local List_Accessor = Accessor:clone {
__ctor = function(self, selfmt, list)
if not list or list == ffi.nullptr then
return Accessor.__ctor(self, selfmt, nil)
end
selfmt.__list = list
return Accessor.__ctor(self, selfmt,
eina.eina_list_accessor_new(dgetmt(list).__list))
end,
data_get = function(self, pos)
local v = Accessor.data_get(self, pos)
if not v then return nil end
return self.__list:data_get(v)
end
}
local get_list_t = function(list)
return ffi.cast("Eina_List_T*", list)
end
local List = ffi.metatype("Eina_List", {
__len = function(self)
return get_list_t(self).accounting.count
end,
__index = {
data_get = function(self, ptr)
if ptr ~= nil then return ptr end
local v = get_list_t(self).data
if v == ffi.nullptr then return nil end
return v
end,
nth = function(self, n)
local v = eina.eina_list_nth(self, n - 1)
if v == ffi.nullptr then return nil end
return self:data_get(v)
end,
nth_list = function(self, n)
local v = eina.eina_list_nth_list(self, n - 1)
if v == ffi.nullptr then return nil end
return v
end,
last = function(self)
local v = get_list_t(self).accounting.last
if v == ffi.nullptr then return nil end
return v
end,
next = function(self)
local v = get_list_t(self).next
if v == ffi.nullptr then return nil end
return v
end,
prev = function(self)
local v = get_list_t(self).prev
if v == ffi.nullptr then return nil end
return v
end
}
})
local List_Base = util.Readonly_Object:clone {
__ctor = function(self, selfmt, list, freefunc)
if list and freefunc then
list = ffi.gc(list, freefunc)
selfmt.__free = freefunc
end
if not list or list == ffi.nullptr then return end
selfmt.__eq = function(self, other)
return selfmt.__list == dgetmt(other).__list
end
selfmt.__len = self.count
selfmt.__list = list
end,
free = function(self)
self = dgetmt(self)
local ffunc, l = self.__free, self.__list
if not ffunc or not l or l == ffi.nullptr then return end
ffunc(ffi.gc(self.__list, nil))
end,
count = function(self)
self = dgetmt(self)
local l = self.__list
if not l or l == ffi.nullptr then return 0 end
return #l
end,
nth = function(self, n)
self = dgetmt(self)
local l = self.__list
if not l or l == ffi.nullptr then return nil end
return l:nth()
end,
nth_list = function(self, n)
self = dgetmt(self)
local l = self.__list
if not l or l == ffi.nullptr then return nil end
return self.__index(l:nth_list())
end,
last = function(self, n)
self = dgetmt(self)
local l = self.__list
if not l or l == ffi.nullptr then return nil end
return self.__index(l:last())
end,
next = function(self, n)
self = dgetmt(self)
local l = self.__list
if not l or l == ffi.nullptr then return nil end
return self.__index(l:next())
end,
prev = function(self, n)
self = dgetmt(self)
local l = self.__list
if not l or l == ffi.nullptr then return nil end
return self.__index(l:prev())
end,
data_get = function(self, ptr)
self = dgetmt(self)
local l = self.__list
if not l or l == ffi.nullptr then return nil end
return l:data_get(ptr)
end,
to_array = function(self)
local l = dgetmt(self).__list
if not l or l == ffi.nullptr then return {}, 0 end
local n = 0
local r = {}
while l ~= nil do
n = n + 1
local d = l:data_get()
if d ~= nil then
r[n] = self:data_get(d)
end
l = l:next()
end
return r, n
end,
iterator = function(self)
return List_Iterator(self)
end,
reverse_iterator = function(self)
return List_Reverse_Iterator(self)
end,
accessor = function(self)
return List_Accessor(self)
end
}
M.List_Base = List_Base
M.Ptr_List = List_Base:clone {
__ctor = function(self, selfmt, ptrtype, list, freefunc)
List_Base.__ctor(self, selfmt, list, freefunc)
selfmt.ptrtype = ptrtype
end,
data_get = function(self, ptr)
ptr = List_Base.data_get(self, ptr)
if not ptr then return nil end
return ffi.cast(dgetmt(self).ptrtype, ptr)
end
}
M.String_List = List_Base:clone {
data_get = function(self, ptr)
ptr = List_Base.data_get(self, ptr)
if not ptr or ptr == ffi.nullptr then return nil end
return ffi.string(ptr)
end
}
return M