Module:IP: Difference between revisions

From the Croc Wiki, the Croc encyclopedia
Jump to navigationJump to search
Content added Content deleted
(implement Subnet (very rushed; will check and refactor!))
(use __index plus a unique key to access any IPAddress object's internal data)
Line 10: Line 10:
local V4 = 'IPv4'
local V4 = 'IPv4'
local V6 = 'IPv6'
local V6 = 'IPv6'

--------------------------------------------------------------------------------
-- TODO Remove items from these notes when satisfied they are ok.

-- IPAddress does not need mt:__le(obj) as Lua evaluates (a <= b) as (not (b < a))
-- and that is correct for IP addresses.

-- IPAddress obj:getIP() needs thought.
-- At first, it looked like the representation of the IP (the numbers).
-- But perhaps it is intended to be a string as in the testcases.
-- Is it really just a copy of the input string?
-- What if the input is " 1.2.3.4 " (with leading and trailing spaces which
-- the code ignores)?
-- Also, tostring(ip) for an IPv6 address will return the normalized string
-- which might be different from the input. Example:
-- input "1:02:003:0004:0:0:0:0" is "1:2:3:4::" after normalization.

-- Should obj:getIPParts() be removed?
-- Instead, move the metamethods into IPAddress.new(ip) so they can
-- access the data upvalue?
-- Hmmm, that would work only for self, not for the other object.
-- Is there a way of keeping data private but accessing it from metamethods?
-- If getIPParts is kept, perhaps it should be changed to "getParts" or similar
-- as "IP" is redundant in an IPAddress class.


------------------------------------------------------------------------
------------------------------------------------------------------------
Line 263: Line 239:


do
do
local dataKey = {} -- A unique key to access objects' internal data.
local uniqueId = {}

-- Initialize metatable
-- Static private methods
local mt = {}
local function ipEquals(ip1, ip2)
local lhs = ip1[dataKey].parts
local rhs = ip2[dataKey].parts
if lhs.n == rhs.n then
for i = 1, lhs.n do
if lhs[i] ~= rhs[i] then
return false
end
end
return true
end
return false
end

local function ipLessThan(ip1, ip2)
local lhs = ip1[dataKey].parts
local rhs = ip2[dataKey].parts
if lhs.n == rhs.n then
for i = 1, lhs.n do
if lhs[i] ~= rhs[i] then
return lhs[i] < rhs[i]
end
end
return false
end
return lhs.n < rhs.n
end


-- Constructor
-- Constructor
function IPAddress.new(ip, parts)
function IPAddress.new(ip, parts)
checkType('IPAddress.new', 1, ip, 'string')


-- Set up structure
-- Set up structure
local obj = setmetatable({}, mt)
local obj = {}
local data = {}
local data = {}

-- Set initial values
if not (ipv4Address(data, ip) or ipv6Address(data, ip)) then
error('invalid IP', 2)
end
data.version = data.parts.n == 2 and V4 or V6


-- Public methods
-- Public methods
Line 322: Line 332:
end
end


-- Set initial values
-- Metamethods
return setmetatable(obj, {
if ip == uniqueId then
data.parts = parts
__eq = ipEquals,
__lt = ipLessThan,
else
__index = function (self, key)
checkType('IPAddress.new', 1, ip, 'string')
if not (ipv4Address(data, ip) or ipv6Address(data, ip)) then
if key == dataKey then
return data
error('invalid IP', 2)
end
end
data.version = data.parts.n == 2 and V4 or V6

return obj
end

-- Metamethods
function mt:__concat(obj)
return tostring(self) .. tostring(obj)
end

function mt:__eq(obj)
local lhs, rhs = self:getIPParts(), obj:getIPParts()
if lhs.n == rhs.n then
for i = 1, lhs.n do
if lhs[i] ~= rhs[i] then
return false
end
end
end
end,
__concat = function (self, obj)
return true
return tostring(self) .. tostring(obj)
end
end,
return false
__tostring = function (self)
end
return ipString(self:getIPParts())

end,
function mt:__lt(obj)
})
local lhs, rhs = self:getIPParts(), obj:getIPParts()
if lhs.n == rhs.n then
for i = 1, lhs.n do
if lhs[i] ~= rhs[i] then
return lhs[i] < rhs[i]
end
end
return false
end
return lhs.n < rhs.n
end

function mt:__tostring()
return ipString(self:getIPParts())
end
end
end
end