Module:IP: Difference between revisions

From the Croc Wiki, the Croc encyclopedia
Jump to navigationJump to search
try original format again
(try different format with underscores instead of private data)
(try original format again)
Line 165:
end
 
local function ipv4Address(data, ipStr)
--------------------------------------------------------------------------------
-- If ipStr is a valid IPv4 string, store its parts in data and
-- IPAddress class
-- return true. Otherwise, return false.
-- Represents a single IPv4 or IPv6 address.
-- This representation is for compatibility with IPv6 addresses.
--------------------------------------------------------------------------------
local octets = collection()
 
local s = ipStr:match('^%s*(.-)%s*$') .. '.'
local IPAddress = {}
for item in s:gmatch('(.-)%.') do
IPAddress.__index = IPAddress
octets:add(item)
 
end
do
if octets.n == 4 then
-- Private static methods
for i, s in ipairs(octets) do
local function parseIPv4(ipStr)
if s:match('^%d+$') then
-- If ipStr is a valid IPv4 string, return a collection of its parts.
local num = tonumber(s)
-- Otherwise, return nil.
if 0 <= num and num <= 255 then
-- This representation is for compatibility with IPv6 addresses.
if num > 0 and s:match('^0') then
local octets = collection()
-- A redundant leading zero is for an IP in octal.
local s = ipStr:match('^%s*(.-)%s*$') .. '.'
for item in s:gmatch('(.-)%.') do
octets:add(item)
end
if octets.n == 4 then
for i, s in ipairs(octets) do
if s:match('^%d+$') then
local num = tonumber(s)
if 0 <= num and num <= 255 then
if num > 0 and s:match('^0') then
-- A redundant leading zero is for an IP in octal.
return false
end
octets[i] = num
else
return false
end
octets[i] = num
else
return false
end
else
return false
end
local parts = collection()
for i = 1, 3, 2 do
parts:add(octets[i] * 256 + octets[i+1])
end
return parts
end
data.parts = collection()
return nil
for i = 1, 3, 2 do
data.parts:add(octets[i] * 256 + octets[i+1])
end
return true
end
return false
end
 
local function parseIPv6ipv6Address(data, ipStr)
-- If ipStr is a valid IPv6 string, returnstore aits collectionparts ofin itsdata parts.and
-- return true. Otherwise, return nilfalse.
ipStr = ipStr:match('^%s*(.-)%s*$')
local _, n = ipStr:gsub(':', ':')
if n < 7 then
ipStr, n = ipStr:gsub('::', string.rep(':', 9 - n))
end
local parts = collection()
for item in (ipStr .. ':'):gmatch('(.-):') do
parts:add(item)
end
if parts.n == 8 then
for i, s in ipairs(parts) do
if s == '' then
parts[i] = 0
else
local num = tonumber('0x' .. s)
if num and 0 <= num and num <= 65535 then
parts[i] = num
else
return false
local num = tonumber('0x' .. s)
if num and 0 <= num and num <= 65535 then
parts[i] = num
else
return false
end
end
end
return parts
end
data.parts = parts
return nil
return true
end
return false
end
 
--------------------------------------------------------------------------------
-- Constructor
function-- IPAddress.new(ip) class
-- Represents a single IPv4 or IPv6 address.
checkType('IPAddress.new', 1, ip, 'string')
--------------------------------------------------------------------------------
local self = setmetatable({}, IPAddress)
 
local IPAddress = {}
-- Set initial values
self._parts = parseIPv4(ip) or parseIPv6(ip)
if not self._parts then
error('invalid IP', 2)
end
self._version = self._parts.n == 2 and V4 or V6
 
do
return self
local dataKey = {} -- A unique key to access objects' internal data.
end
 
-- Public methods
function IPAddress:getIP()
return ipString(self._parts)
end
 
function IPAddress:getVersion()
return self._version
end
 
function IPAddress:getHighestIP(bitLength)
return IPAddress.new(uniqueId, setHostBits(self._parts, bitLength))
end
 
function IPAddress:getPrefix(bitLength)
return IPAddress.new(uniqueId, copyPrefix(self._parts, bitLength))
end
 
function IPAddress:isIPv4()
return self._version == V4
end
 
function IPAddress:isIPv6()
return self._version == V6
end
 
function IPAddress:isInSubnet(subnet)
-- TODO Consider alternative of checking:
-- (ipFirst <= self and self <= ipLast)
if self:getVersion() == subnet:getVersion() then
local prefix = self:getPrefix(subnet:getBitLength())
return prefix == subnet:getPrefix()
end
return false
end
 
function IPAddress:getNextIP()
return IPAddress.new(uniqueId, copyChanged(self._parts))
end
 
function IPAddress:getPreviousIP()
return IPAddress.new(uniqueId, copyChanged(self._parts, true))
end
 
-- Static private methods
function IPAddress:__eq(obj)
local function ipEquals(ip1, ip2)
local lhs = self._parts
local rhslhs = objip1[dataKey]._partsparts
local rhs = ip2[dataKey].parts
if lhs.n == rhs.n then
for i = 1, lhs.n do
Line 312 ⟶ 256:
end
 
local function IPAddress:__ltipLessThan(ip1, ip2)
local lhs = selfip1[dataKey]._partsparts
local rhs = objip2[dataKey]._partsparts
if lhs.n == rhs.n then
for i = 1, lhs.n do
Line 326 ⟶ 270:
end
 
-- Constructor
function IPAddress:__concat(obj)
function IPAddress.new(ip)
return tostring(self) .. tostring(obj)
checkType('IPAddress.new', 1, ip, 'string')
end
 
-- Set up structure
function IPAddress:__tostring()
local obj = {}
return ipString(self._parts)
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
function obj:getIP()
return ipString(data.parts)
end
 
function obj:getVersion()
return data.version
end
 
function obj:getHighestIP(bitLength)
return IPAddress.new(uniqueId, setHostBits(data.parts, bitLength))
end
 
function obj:getPrefix(bitLength)
return IPAddress.new(uniqueId, copyPrefix(data.parts, bitLength))
end
 
function obj:isIPv4()
return data.version == V4
end
 
function obj:isIPv6()
return data.version == V6
end
 
function obj:isInSubnet(subnet)
-- TODO Consider alternative of checking:
-- (ipFirst <= self and self <= ipLast)
if self:getVersion() == subnet:getVersion() then
local prefix = self:getPrefix(subnet:getBitLength())
return prefix == subnet:getPrefix()
end
return false
end
 
function obj:getNextIP()
return IPAddress.new(uniqueId, copyChanged(data.parts))
end
 
function obj:getPreviousIP()
return IPAddress.new(uniqueId, copyChanged(data.parts, true))
end
 
-- Metamethods
return setmetatable(obj, {
__eq = ipEquals,
__lt = ipLessThan,
__index = function (self, key)
if key == dataKey then
return data
end
end,
__concat = function (self, obj)
return tostring(self) .. tostring(obj)
end,
__tostring = function (self)
return ipString(self:getIPParts())
end,
})
end
end
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Navigation menu