PageRenderTime 10ms CodeModel.GetById 2ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

/Table.lua

http://ro-rail.googlecode.com/
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