-- copytable.lua

--[[

Table copying functions. 

See: http://www.gammon.com.au/forum/?id=8042

Ideas by Shaun Biggs, David Haley, Nick Gammon

Date: 21st July 2007

This is intended to copy tables (make a real copy, rather than just the table
reference).

You can do a deep or shallow copy.

Shallow: Simply copies the keys and values. 
If a value is a table, you will get the same table as in the original.

Deep: Copies keys and values recursively.
If a value is a table, makes a copy of that table, and so on.

Restrictions: Items must be "safe" to copy (eg. not file IO userdata). 
If doing a deep copy, a table may not appear inside itself.

Example:

t1 = {
  m = { a = 1, b = 2 },
  n = { c = 3, d = 4 },
  }

require "copytable"  -- load this file

t2 = copytable.shallow (t1)  -- shallow copy
t3 = copytable.deep (t1)  -- copies sub tables as well

--]]

module (..., package.seeall)

function deep (t, done)
  assert (type (t) == "table", "You must specify a table to copy")

  local result = {}
  done = done or {}

  assert (not done [t], "table is defined within itself")

  done [t] = true -- we will disallow recopying table t

  for k, v in pairs (t) do
    if type (v) == "table"  then
      result [k] = deep (v, done)
    else
      result [k] = v
    end -- if table or not
  end -- for each table element

  done [t] = nil -- table t can be copied again

  -- copy the metatable
  return setmetatable (result, getmetatable (t))

end -- function deep

function shallow (t)
  assert (type (t) == "table", "You must specify a table to copy")
    
  local result = {}

  for k, v in pairs (t) do
    result [k] = v
  end -- for each table element

  -- copy the metatable
  return setmetatable (result, getmetatable (t))

end  -- function shallow
