-- 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