IPv4 address ranges parsing: Add merging.

This commit is contained in:
Nodir Temirkhodjaev 2015-01-25 14:45:23 +05:00
parent 98a9533608
commit 489783ad73
2 changed files with 67 additions and 14 deletions

View File

@ -23,7 +23,7 @@ do
local to_ip local to_ip
if sep == '-' then -- e.g. "127.0.0.0-127.255.255.255" if sep == '-' then -- e.g. "127.0.0.0-127.255.255.255"
to_ip = sock.inet_pton(mask, true) to_ip = sock.inet_pton(mask, true)
if not to_ip then if not to_ip or from_ip > to_ip then
return return
end end
elseif sep == '/' then -- e.g. "127.0.0.0/24" elseif sep == '/' then -- e.g. "127.0.0.0/24"
@ -40,9 +40,51 @@ do
return from_ip, to_ip return from_ip, to_ip
end end
-- sort and try to merge ranges
local function iprange_map_merge(map)
-- fill temporary "from" range
local tmp_from, tmp_count = {}, 0
for from in pairs(map) do
tmp_count = tmp_count + 1
tmp_from[tmp_count] = from
end
table.sort(tmp_from)
-- try to merge ranges
local prev_from, prev_to
for i = 1, tmp_count do
local from = tmp_from[i]
local to = map[from]
if prev_from and from <= prev_to then -- collides with previous?
if to > prev_to then
map[prev_from], prev_to = to, to
end
tmp_from[i] = nil
else
prev_from, prev_to = from, to
end
end
-- fill "from" & "to" ranges
local iprange_from, iprange_to, count = {}, {}, 0
for i = 1, tmp_count do
local from = tmp_from[i]
if from then
count = count + 1
iprange_from[count] = from
iprange_to[count] = map[from]
end
end
iprange_from.n, iprange_to.n = count, count
return iprange_from, iprange_to
end
ip4range_to_numbers = function (text) ip4range_to_numbers = function (text)
local iprange_from, iprange_to = {}, {} local iprange_map = {}
local line_no, index = 0, 0 local line_no = 0
for line in string.gmatch(text, "%s*([^\n]+)") do for line in string.gmatch(text, "%s*([^\n]+)") do
local from, to = parse_address_mask(line) local from, to = parse_address_mask(line)
@ -50,16 +92,13 @@ do
line_no = line_no + 1 line_no = line_no + 1
if from then if from then
index = index + 1 iprange_map[from] = to
iprange_from[index], iprange_to[index] = from, to
elseif string.find(line, "%S") then elseif string.find(line, "%S") then
return nil, line_no return nil, line_no
end end
end end
iprange_from.n, iprange_to.n = index, index return iprange_map_merge(iprange_map)
return iprange_from, iprange_to
end end
end end

View File

@ -45,7 +45,16 @@ end
print"-- IPv4 Conversions" print"-- IPv4 Conversions"
do do
local from, to = util_ip.ip4range_to_numbers[[ local _, err_line
_, err_line = util_ip.ip4range_to_numbers[[172.16.0.0/33]]
assert(err_line == 1)
_, err_line = util_ip.ip4range_to_numbers[[172.16.0.255/-16]]
assert(err_line == 1)
_, err_line = util_ip.ip4range_to_numbers[[10.0.0.32 - 10.0.0.24]]
assert(err_line == 1)
local from, to
from, to = util_ip.ip4range_to_numbers[[
172.16.0.0/20 172.16.0.0/20
192.168.0.0 - 192.168.255.255 192.168.0.0 - 192.168.255.255
]] ]]
@ -55,11 +64,16 @@ do
assert(from[2] == sock.inet_pton("192.168.0.0", true)) assert(from[2] == sock.inet_pton("192.168.0.0", true))
assert(to[2] == sock.inet_pton("192.168.255.255", true)) assert(to[2] == sock.inet_pton("192.168.255.255", true))
local _, err_line -- merge ranges
_, err_line = util_ip.ip4range_to_numbers[[172.16.0.0/33]] from, to = util_ip.ip4range_to_numbers[[
assert(err_line == 1) 10.0.0.0 - 10.0.0.255
_, err_line = util_ip.ip4range_to_numbers[[172.16.0.255/-16]] 10.0.0.64 - 10.0.0.128
assert(err_line == 1) 10.0.0.128 - 10.0.2.0
]]
assert(from.n == 1 and to.n == 1)
assert(from[1] == sock.inet_pton("10.0.0.0", true))
assert(to[1] == sock.inet_pton("10.0.2.0", true))
print("OK") print("OK")
end end