Canonicalize CIDR: Difference between revisions

Add Swift implementation
imported>Thebeez
(Add Swift implementation)
 
(5 intermediate revisions by 3 users not shown)
Line 41:
| d < 0 | d > 255
R (0, 0)
V mask = (-)~((1 << (32 - m)) - 1)
V address = (a << 24) + (b << 16) + (c << 8) + d
address [&]= mask
Line 74:
184.232.176.184/18 -> 184.232.128.0/18
</pre>
 
=={{header|ALGOL 68}}==
<syntaxhighlight lang="algol68">BEGIN # show IPv4 addresses in CIDR notation in canonical form #
Line 812 ⟶ 813:
<pre>Before canonicalization: 87.70.141.1/22
After canonicalization: 87.70.140.0/22</pre>
=={{header|EasyLang}}==
<syntaxhighlight>
func$ can_cidr s$ .
n[] = number strsplit s$ "./"
if len n[] <> 5
return ""
.
for i to 4
if n[i] < 0 or n[i] > 255
return ""
.
ad = ad * 256 + n[i]
.
if n[5] > 31 or n[5] < 1
return ""
.
mask = bitnot (bitshift 1 (32 - n[5]) - 1)
ad = bitand ad mask
for i to 4
if r$ <> ""
r$ = "." & r$
.
r$ = ad mod 256 & r$
ad = ad div 256
.
return r$ & "/" & n[5]
.
repeat
s$ = input
until s$ = ""
print s$ & " -> " & can_cidr s$
.
#
input_data
87.70.141.1/22
36.18.154.103/12
62.62.197.11/29
67.137.119.181/4
161.214.74.21/24
184.232.176.184/18
 
</syntaxhighlight>
 
=={{header|Factor}}==
{{trans|Ruby}}
Line 842 ⟶ 886:
87.70.140.0/22
</pre>
 
=={{header|Go}}==
{{trans|Ruby}}
Line 1,397 ⟶ 1,442:
161.214.74.0/24
184.232.128.0/18</pre>
 
=={{header|MATLAB}}==
{{trans|Python}}
<syntaxhighlight lang="MATLAB">
clear all;close all;clc;
cidrCanonicalizer();
 
function cidrCanonicalizer
% Main function to test CIDR canonicalization
% Define test cases
testCases = {
'36.18.154.103/12', '36.16.0.0/12';
'62.62.197.11/29', '62.62.197.8/29';
'67.137.119.181/4', '64.0.0.0/4';
'161.214.74.21/24', '161.214.74.0/24';
'184.232.176.184/18', '184.232.128.0/18'
};
% Run test cases
for i = 1:size(testCases, 1)
ip = testCases{i, 1};
expected = testCases{i, 2};
result = canonicalize(ip);
fprintf('%s -> %s\n', ip, result);
assert(strcmp(result, expected));
end
end
 
function result = dottedToInt(dotted)
% Convert dotted IP to integer representation
parts = str2double(strsplit(dotted, '.'));
result = sum(parts .* (256 .^ (3:-1:0)));
end
 
function result = intToDotted(ip)
% Convert integer IP to dotted representation
result = strjoin(arrayfun(@(x) num2str(bitshift(bitand(ip, bitshift(255, x)), -x)), [24 16 8 0], 'UniformOutput', false), '.');
end
 
function result = networkMask(numberOfBits)
% Create a network mask for the given number of bits
result = bitshift((bitshift(1, numberOfBits) - 1), (32 - numberOfBits));
end
 
function result = canonicalize(ip)
% Canonicalize the given CIDR IP
[dotted, networkBits] = strtok(ip, '/');
networkBits = str2double(strrep(networkBits, '/', ''));
i = dottedToInt(dotted);
mask = networkMask(networkBits);
result = strcat(intToDotted(bitand(i, mask)), '/', num2str(networkBits));
end
</syntaxhighlight>
{{out}}
<pre>
36.18.154.103/12 -> 36.16.0.0/12
62.62.197.11/29 -> 62.62.197.8/29
67.137.119.181/4 -> 64.0.0.0/4
161.214.74.21/24 -> 161.214.74.0/24
184.232.176.184/18 -> 184.232.128.0/18
</pre>
 
=={{header|Nim}}==
Using the IpAddress type from standard module “net”.
Line 2,019 ⟶ 2,127:
println!("{}", canonical_cidr("127.1.2.3/24").unwrap());
}</syntaxhighlight>
 
=={{header|Scala}}==
{{trans|Java}}
<syntaxhighlight lang="Scala">
import java.text.MessageFormat
 
object CanonicalizeCIDR extends App {
case class CIDR(address: Int, maskLength: Int) {
override def toString: String = {
val a = (address >> 24) & 0xFF
val b = (address >> 16) & 0xFF
val c = (address >> 8) & 0xFF
val d = address & 0xFF
MessageFormat.format(CIDR.format, a.asInstanceOf[AnyRef], b.asInstanceOf[AnyRef], c.asInstanceOf[AnyRef], d.asInstanceOf[AnyRef], maskLength.asInstanceOf[AnyRef])
}
}
 
object CIDR {
private val format = "{0,number,integer}.{1,number,integer}.{2,number,integer}.{3,number,integer}/{4,number,integer}"
 
def apply(str: String): CIDR = {
val args = new MessageFormat(format).parse(str)
val address = args.take(4).foldLeft(0) { (acc, arg) =>
val a = arg.asInstanceOf[Number].intValue()
require(a >= 0 && a <= 255, "Invalid IP address")
(acc << 8) + a
}
val maskLength = args(4).asInstanceOf[Number].intValue()
require(maskLength >= 1 && maskLength <= 32, "Invalid mask length")
val mask = ~((1 << (32 - maskLength)) - 1)
new CIDR(address & mask, maskLength)
}
}
 
val tests = Array(
"87.70.141.1/22",
"36.18.154.103/12",
"62.62.197.11/29",
"67.137.119.181/4",
"161.214.74.21/24",
"184.232.176.184/18"
)
 
tests.foreach { test =>
try {
val cidr = CIDR(test)
println(f"$test%-18s -> $cidr")
} catch {
case ex: Exception => println(s"Error parsing '$test': ${ex.getLocalizedMessage}")
}
}
}
</syntaxhighlight>
{{out}}
<pre>
87.70.141.1/22 -> 87.70.140.0/22
36.18.154.103/12 -> 36.16.0.0/12
62.62.197.11/29 -> 62.62.197.8/29
67.137.119.181/4 -> 64.0.0.0/4
161.214.74.21/24 -> 161.214.74.0/24
184.232.176.184/18 -> 184.232.128.0/18
 
</pre>
 
=={{header|SNOBOL}}==
<syntaxhighlight lang="snobol">* Pattern to match any number of digits
Line 2,076 ⟶ 2,248:
161.214.74.0/24
184.232.128.0/18</pre>
 
=={{header|Swift}}==
{{trans|Python}}
<syntaxhighlight lang="Swift">
import Foundation
 
func dottedToInt(_ dotted: String) -> UInt32 {
let digits = dotted.split(separator: ".").map { UInt32($0)! }
return digits.enumerated().reduce(0) { $0 + ($1.element << (24 - $1.offset * 8)) }
}
 
func intToDotted(_ ip: UInt32) -> String {
let digits = [24, 16, 8, 0].map { (ip & (255 << $0)) >> $0 }
return digits.map { String($0) }.joined(separator: ".")
}
 
func networkMask(_ numberOfBits: Int) -> UInt32 {
// Explicitly use UInt32 for bitwise operations
return UInt32((1 << numberOfBits) - 1) << (32 - numberOfBits)
}
 
func canonicalize(_ ip: String) -> String {
let parts = ip.split(separator: "/")
let dotted = String(parts[0])
let networkBits = Int(parts[1])!
let i = dottedToInt(dotted)
let mask = networkMask(networkBits)
return "\(intToDotted(i & mask))/\(networkBits)"
}
 
let testCases = [
("36.18.154.103/12", "36.16.0.0/12"),
("62.62.197.11/29", "62.62.197.8/29"),
("67.137.119.181/4", "64.0.0.0/4"),
("161.214.74.21/24", "161.214.74.0/24"),
("184.232.176.184/18", "184.232.128.0/18"),
]
 
for testCase in testCases {
let (ip, expect) = testCase
let result = canonicalize(ip)
print("\(ip) -> \(result)")
assert(result == expect, "Test failed for \(ip)")
}
</syntaxhighlight>
{{out}}
<pre>
36.18.154.103/12 -> 36.16.0.0/12
62.62.197.11/29 -> 62.62.197.8/29
67.137.119.181/4 -> 64.0.0.0/4
161.214.74.21/24 -> 161.214.74.0/24
184.232.176.184/18 -> 184.232.128.0/18
 
</pre>
 
 
=={{header|Tcl}}==
{{trans|Python}}
<syntaxhighlight lang="Tcl">
# Canonicalize CIDR in Tcl
 
# Convert dotted IP address to integer
proc dotted_to_int {dotted} {
set digits [split $dotted .]
set result 0
foreach digit $digits {
set result [expr {$result * 256 + $digit}]
}
return $result
}
 
# Convert integer IP address to dotted format
proc int_to_dotted {ip} {
set result {}
for {set i 3} {$i >= 0} {incr i -1} {
lappend result [expr {($ip >> ($i * 8)) & 0xFF}]
}
return [join $result .]
}
 
# Calculate network mask
proc network_mask {number_of_bits} {
return [expr {(1 << $number_of_bits) - 1 << (32 - $number_of_bits)}]
}
 
# Canonicalize IP address
proc canonicalize {ip} {
regexp {^(.*)/(.*)$} $ip -> dotted network_bits
set i [dotted_to_int $dotted]
set mask [network_mask $network_bits]
return [int_to_dotted [expr {$i & $mask}]]/$network_bits
}
 
# Test cases
set test_cases {
{"36.18.154.103/12" "36.16.0.0/12"}
{"62.62.197.11/29" "62.62.197.8/29"}
{"67.137.119.181/4" "64.0.0.0/4"}
{"161.214.74.21/24" "161.214.74.0/24"}
{"184.232.176.184/18" "184.232.128.0/18"}
}
 
# Main execution
foreach test $test_cases {
foreach {ip expect} $test {}
set rv [canonicalize $ip]
puts "$ip -> $rv"
if {$rv ne $expect} {
error "Test failed: $rv != $expect"
}
}
</syntaxhighlight>
{{out}}
<pre>
36.18.154.103/12 -> 36.16.0.0/12
62.62.197.11/29 -> 62.62.197.8/29
67.137.119.181/4 -> 64.0.0.0/4
161.214.74.21/24 -> 161.214.74.0/24
184.232.176.184/18 -> 184.232.128.0/18
 
</pre>
 
 
=={{header|TXR}}==
 
338

edits