Module:IP: Difference between revisions

From the Croc Wiki, the Croc encyclopedia
Jump to navigationJump to search
411 bytes removed ,  7 years ago
try different format with underscores instead of private data
(test new IPAddress class structure to make the objects more memory-efficient)
(try different format with underscores instead of private data)
Line 163:
end
return ipv6String(ip)
end
 
local function ipv4Address(data, ipStr)
-- If ipStr is a valid IPv4 string, store its parts in data and
-- return true. Otherwise, return false.
-- This representation is for compatibility with IPv6 addresses.
local octets = collection()
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
else
return false
end
end
data.parts = collection()
for i = 1, 3, 2 do
data.parts:add(octets[i] * 256 + octets[i+1])
end
return true
end
return false
end
 
local function ipv6Address(data, ipStr)
-- If ipStr is a valid IPv6 string, store its parts in data and
-- return true. Otherwise, return false.
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
end
end
end
data.parts = parts
return true
end
return false
end
 
Line 237 ⟶ 171:
 
local IPAddress = {}
IPAddress.__index = IPAddress
 
do
-- Private static methods
local dataKey = {} -- A unique key to access objects' internal data.
local function parseIPv4(ipStr)
 
-- If ipStr is a valid IPv4 string, return a collection of its parts.
-- Static private methods
-- Otherwise, return nil.
local function ipEquals(ip1, ip2)
-- This representation is for compatibility with IPv6 addresses.
local lhs = ip1[dataKey].parts
local rhsoctets = ip2[dataKey].partscollection()
local s = ipStr:match('^%s*(.-)%s*$') .. '.'
if lhs.n == rhs.n then
for iitem =in 1, lhss:gmatch('(.-)%.n') do
octets:add(item)
if lhs[i] ~= rhs[i] then
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
else
return false
end
end
local parts = collection()
return true
for i = 1, 3, 2 do
parts:add(octets[i] * 256 + octets[i+1])
end
return parts
end
return falsenil
end
 
local function ipLessThanparseIPv6(ip1, ip2ipStr)
-- If ipStr is a valid IPv6 string, return a collection of its parts.
local lhs = ip1[dataKey].parts
-- Otherwise, return nil.
local rhs = ip2[dataKey].parts
ipStr = ipStr:match('^%s*(.-)%s*$')
if lhs.n == rhs.n then
forlocal i_, n = 1ipStr:gsub(':', lhs.n do':')
if lhs[i]n ~=< rhs[i]7 then
ipStr, n = ipStr:gsub('::', string.rep(':', 9 - n))
return lhs[i] < rhs[i]
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
end
end
end
return falseparts
end
return lhs.n < rhs.nnil
end
 
local function concatIPs(ip1, ip2)
return tostring(ip1) .. tostring(ip2)
end
 
local function ipToString(ip)
return ipString(ip[dataKey].parts)
end
 
Line 281 ⟶ 243:
function IPAddress.new(ip)
checkType('IPAddress.new', 1, ip, 'string')
local self = setmetatable({}, IPAddress)
 
-- Set up structure
local obj = {}
local data = {}
 
-- Set initial values
self._parts = parseIPv4(ip) or parseIPv6(ip)
if not (ipv4Address(data, ip) or ipv6Address(data, ip)) then
if not self._parts then
error('invalid IP', 2)
end
dataself.version_version = dataself.parts_parts.n == 2 and V4 or V6
 
return self
-- Metamethods
return setmetatable(obj, {
__eq = ipEquals,
__lt = ipLessThan,
__concat = concatIPs,
__tostring = ipToString,
__index = function (self, key)
if key == dataKey then
return data
else
return IPAddress[key]
end
end,
})
end
 
-- Public methods
function IPAddress:getIP()
return ipString(self[dataKey].parts_parts)
end
 
function IPAddress:getVersion()
return self[dataKey].version_version
end
 
function IPAddress:getHighestIP(bitLength)
return IPAddress.new(uniqueId, setHostBits(self[dataKey].parts_parts, bitLength))
end
 
function IPAddress:getPrefix(bitLength)
return IPAddress.new(uniqueId, copyPrefix(self[dataKey].parts_parts, bitLength))
end
 
function IPAddress:isIPv4()
return self[dataKey].version_version == V4
end
 
function IPAddress:isIPv6()
return self[dataKey].version_version == V6
end
 
Line 344 ⟶ 291:
 
function IPAddress:getNextIP()
return IPAddress.new(uniqueId, copyChanged(self[dataKey].parts_parts))
end
 
function IPAddress:getPreviousIP()
return IPAddress.new(uniqueId, copyChanged(self[dataKey].parts_parts, true))
end
 
function IPAddress:__eq(obj)
local lhs = self._parts
local rhs = obj._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
 
function IPAddress:__lt(ip1, ip2)
local lhs = self._parts
local rhs = obj._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
 
function IPAddress:__concat(obj)
return tostring(self) .. tostring(obj)
end
 
function IPAddress:__tostring()
return ipString(self._parts)
end
end
 
Cookies help us deliver our services. By using our services, you agree to our use of cookies.

Navigation menu