summaryrefslogtreecommitdiff
path: root/src/bindings/luajit/eina/iterator.lua
blob: dc5d0da8b2c302686bcc47f067960e4b8e1c82ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
-- EFL LuaJIT bindings: Eina (iterator module)
-- For use with Elua

local ffi = require("ffi")
local C = ffi.C

ffi.cdef [[
    typedef struct _Eina_Iterator Eina_Iterator;
    typedef unsigned char Eina_Bool;

    void      eina_iterator_free         (Eina_Iterator *iterator);
    Eina_Bool eina_iterator_next         (Eina_Iterator *iterator, void **data);
    Eina_Bool eina_iterator_lock         (Eina_Iterator *iterator);
    Eina_Bool eina_iterator_unlock       (Eina_Iterator *iterator);
    void     *eina_iterator_container_get(Eina_Iterator *iterator);
]]

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

ffi.metatype("Eina_Iterator", {
    __index = {
        free = function(self) eina.eina_iterator_free(ffi.gc(self, nil)) end,
        next = function(self)
            local data = ffi.new("void*[1]")
            local r = eina.eina_iterator_next(self, data)
            if r == 0 then return nil end
            return data[0]
        end,
        lock   = function(self) return eina.eina_iterator_lock  (self) ~= 0 end,
        unlock = function(self) return eina.eina_iterator_unlock(self) ~= 0 end,
        container_get = function(self)
            local v = eina.eina_iterator_container_get(self)
            if v == nil then return nil end
            return v
        end
    }
})

cutil.init_module(init, shutdown)

local dgetmt = debug.getmetatable

M.Iterator = util.Readonly_Object:clone {
    __ctor = function(self, selfmt, iter)
        -- prevent null stuff
        if iter == nil then iter = nil end
        if iter then ffi.gc(iter, iter.free) end
        selfmt.__eq = function(self, other)
            return selfmt.__iterator == dgetmt(other).__iterator
        end
        selfmt.__call = function(self)
            return self:next()
        end
        selfmt.__iterator = iter
    end,

    free = function(self)
        self = dgetmt(self)
        if not self.__iterator then return end
        self.__iterator:free()
        self.__iterator = nil
    end,

    next = function(self)
        self = dgetmt(self)
        if not self.__iterator then return nil end
        return self.__iterator:next()
    end,

    lock = function(self)
        self = dgetmt(self)
        if not self.__iterator then return false end
        return self.__iterator:lock()
    end,

    unlock = function(self)
        self = dgetmt(self)
        if not self.__iterator then return false end
        return self.__iterator:unlock()
    end,

    container_get = function(self)
        self = dgetmt(self)
        if not self.__iterator then return nil end
        return self.__iterator:container_get()
    end,

    to_array = function(self)
        local ret = {}
        for v in self do
            ret[#ret + 1] = v
        end
        return ret
    end
}

local Iterator = M.Iterator

M.Ptr_Iterator = Iterator:clone {
    __ctor = function(self, selfmt, ptrtype, iter)
        Iterator.__ctor(self, selfmt, iter)
        selfmt.ptrtype = ptrtype
    end,

    next = function(self)
        local  v = Iterator.next(self)
        if not v then return nil end
        return ffi.cast(dgetmt(self).ptrtype, v)
    end
}

M.String_Iterator = Iterator:clone {
    next = function(self)
        local  v = Iterator.next(self)
        if not v then return nil end
        return ffi.string(v)
    end
}

return M