#### /Table.lua

Lua | 327 lines | 182 code | 55 blank | 90 comment | 38 complexity | 1529c4d8e868b71a0da8e282ae3f0acb MD5 | raw file
```  1-- Various Table Classes
2
3
4-- Table
5do
6  Table = { }
7
8  -- Private key to track the number of entries in the table
9  local key_n = {}
10
11  -- Metatable to make tables inherit from Table
12  local metatable = {
13    __index = Table,
14  }
15
16  -- Create a new table
17  function Table.New(self)
18    local ret = {
19      [key_n] = 0,
20    }
21    setmetatable(ret,metatable)
22
23    return ret
24  end
25
26  -- Get table size
27  function Table.GetN(t)
28    -- See if the table has an "n" element
29    if t[key_n] == nil then
30      -- If it doesn't, count until we find nil
31      local i = 0
32      while t[i+1] ~= nil do i=i+1 end
33      t[key_n] = i
34    end
35
36    return t[key_n]
37  end
38  Table.Size = Table.GetN
39
40  -- Set the table size
41  function Table.SetN(t,size)
42    -- Get the table size
43    local len = Table.GetN(t)
44
45    -- Check if we're reducing the size
46    if size < len then
47      -- Remove all elements after size
48      for i=len,size+1,-1 do
49        t[i]=nil
50      end
51    end
52
53    -- Set n
54    t[key_n]=size
55
56    return t
57  end
58
59  -- Add an element to a table
60  function Table.Insert(t,pos,item)
61    -- Check if we were given 3 arguments
62    if item == nil then
63      -- Nope, only 2, 2nd one is the item
64      item = pos
65      pos = nil
66    end
67
68    -- Get the number of items we're adding
69    local num = 1
70    if type(item) == "table" and item[key_n] ~= nil then
71      num = Table.GetN(item)
72    end
73
74    -- Save the number of items in t
75    local tEnd = Table.GetN(t)
76
77    -- Increase number of items
78    t[key_n] = Table.GetN(t) + num
79
80    -- Check if we have a position
81    if pos == nil then
82      -- Set pos to the end
83      pos = tEnd + 1
84    end
85
86    -- Shift everything forward
87    local i
88    for i=t[key_n],pos+num,-1 do
89      t[i]=t[i-num]
90    end
91
92    -- Insert the item(s)
93    if type(item) == "table" and item[key_n] ~= nil then
94      -- Loop through the table to be merged
95      for i=1,Table.GetN(item) do
96        -- Merge them in
97        t[pos+i-1]=item[i]
98      end
99    else
100      t[pos]=item
101    end
102
103    return t
104  end
105
106  -- Add an element to the end of a table
107  function Table.Append(t,item)
108    -- Just the same as insert without specifying position
109    return Table.Insert(t,item,nil)
110  end
111
112  -- Remove an element from a table
113  function Table.Remove(t,pos,num)
114    -- Check if we have num
115    if num == nil or num < 0 then
116      num = 1
117    elseif num == 0 then
118      return
119    end
120
121    -- Check if the item exists
122    if Table.GetN(t) < pos then
123      return
124    end
125
126    -- Shift everything forward
127    for i=pos,t[key_n]-num do
128      t[i]=t[i+num]
129      t[i+num]=nil
130    end
131
132    -- Remove the previous elements
133    t[key_n]=t[key_n]-num
134
135    return t
136  end
137
138--[[
139  -- Remove elements from the table, based on a function evaluating their values
140  function Table.sieveValues(t,f,reversed)
141    -- Make sure we have a sieving function
142    if type(f) ~= "function" then
143      return t
144    end
145
146    -- Make sure reversed is a boolean
147    if type(reversed) ~= "boolean" then
148      reversed = false
149    end
150
151    -- Loop through each element in the table
152    local i,max = 1,Table.getn(t)
153    while i <= max do
154      -- Check if the element should be ignored
155      local ret = f(t[i])
156      if type(ret) ~= "boolean" then
157        ret = false
158      end
159      if ret ~= reversed then
160        -- Element should be removed
161        Table.remove(t,i)
162
163        -- Reduce the max
164        max = Table.getn(t)
165      else
166        -- Element should stay
167        i = i + 1
168      end
169    end
170
171    return t
172  end
173--]]
174
175  -- Shallow copy a table (just create a new one)
176  function Table.ShallowCopy(t,into,overwrite)
177    local copy = into or {}
178
179    -- Loop through all elements of the table
180    for k,v in t do
181      if copy[k] == nil or overwrite then
182        copy[k] = v
183      end
184    end
185
186    -- Set the same metatable
187    local mt = getmetatable(t)
188    if type(mt) == "table" then
189      setmetatable(copy,mt)
190    end
191
192    return copy
193  end
194
195  -- Deep copy a table (subtables are also copied to new ones)
196  do
197    local function do_deep_copy(v,saved)
198      if not saved[v] then
199        local t = type(v)
200        if t == "table" then
201          -- Deep copy the table
202          saved[v] = Table.DeepCopy(v,nil,nil,saved)
203        else
204          -- Everything else
205          saved[v] = v
206        end
207      end
208      return saved[v]
209    end
210
211    function Table.DeepCopy(t,copy,overwrite,saved)
212      -- Create a saved table
213      saved = saved or setmetatable({},{__mode="k",})
214
215      -- Check if this table has already been copied
216      if saved[t] then
217        return saved[t]
218      end
219
220      -- Create a copy table
221      local copy = copy or {}
222
223      -- Add this table to the saved list
224      saved[t] = copy
225
226      -- Loop through all elements of the table
227      for k,v in pairs(t) do
228        local new_k = do_deep_copy(k,saved)
229
230        if copy[new_k] == nil or overwrite then
231          copy[new_k] = do_deep_copy(v,saved)
232        end
233      end
234
235      -- Check for a metatable
236      local mt = getmetatable(t)
237      if type(mt) == "table" then
238        local deep_mt = getmetatable(copy)
239        setmetatable(copy,Table.DeepCopy(mt,deep_mt,overwrite,saved))
240      end
241
242      -- Return the copy
243      return copy
244    end
245  end
246end
247
248-- List
249do
250  -- List based on code from http://www.lua.org/pil/11.4.html
251
252  List = {}
253
254  local metatable = {
255    __index = List
256  }
257
258  function List.New()
259    local ret = { first = 0, last = -1 }
260    setmetatable(ret,metatable)
261
262    return ret
263  end
264
265  function List.PushLeft (list, value)
266    list.first = list.first - 1
267    list[list.first] = value;
268  end
269
270  function List.PushRight (list, value)
271    list.last = list.last + 1
272    list[list.last] = value
273  end
274
275  function List.PopLeft (list)
276    if list.first > list.last then
277      return nil
278    end
279    local value = list[list.first]
280    list[list.first] = nil         -- to allow garbage collection
281    list.first = list.first + 1
282    return value
283  end
284
285  function List.PopRight (list)
286    if list.first > list.last then
287      return nil
288    end
289    local value = list[list.last]
290    list[list.last] = nil
291    list.last = list.last - 1
292    return value
293  end
294
295  function List.Clear (list)
296    for i=list.first,list.last do
297      list[i] = nil
298    end
299
300    list.first = 0
301    list.last = -1
302  end
303
304  function List.Size (list)
305    return list.last - list.first + 1
306  end
307end
308
309-- Function to selectively return values from pairs based on index name
310function FindPairs(t,pattern,init,plain)
311  -- Get the results from pairs
312  local iter,t,first = pairs(t)
313
314  -- Return a custom function with the table and first item from pairs()
315  return function(t,idx)
316    -- Loop through the values from iter()
317    local value
318    repeat
319      -- Get the next index and skill from pairs()'s iterator
320      idx,value = iter(t,idx)
321    -- Loop until no pairs left or an index matches the pattern
322    until idx == nil or string.find(tostring(idx),pattern,init,plain) ~= nil
323
324    -- Return the next index and value
325    return idx,value
326  end,t,first
327end
```