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 = |
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 |
||
-- |
-- Metamethods |
||
return setmetatable(obj, { |
|||
if ip == uniqueId then |
|||
__eq = ipEquals, |
|||
__lt = ipLessThan, |
|||
else |
|||
__index = function (self, key) |
|||
checkType('IPAddress.new', 1, ip, 'string') |
|||
if |
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 |