Many ways to do that. Using pack/unpack:
@ary = map { pack "B32", join "", (1) x $_, (0) x (32 - $_) } 0..31; print unpack("B*",$_),"\n" for @ary;
pack"B*" packs a string containing 1 and 0 into binary, unpack does the reverse.
Using vec:
$#ary = 31; # create an array of 32 empty slots $c = 0; vec($_,0,32) = ~((1<<++$c)-1) for @ary; @ary = reverse @ary; # another way without $c vec($ary[31+$_],0,32) = ~((1<<(-$_+1))-1) for -31..0; print unpack("B*",$_),"\n" for @ary;
Both solutions output the table you used for illustration. Now you can use that @ary e.g. to calculate network addresses from address and mask:
@ary = map { pack "B32", join "", (1) x $_, (0) x (32 - $_) } 0..31; $dotted = "192.168.248.17"; $netmask = $ary[19]; # prefix 19, i.e. cidr 192.168.248.17/19 $address = pack "C4", split /\./, $dotted; $network = $address & $netmask; $broadcast = $address | ~ $netmask; print $_,$/ for map { join ".", unpack "C4", $_ } $netmask, $address, $network, $broadcast; __END__ 255.255.224.0 192.168.248.17 192.168.224.0 192.168.255.255
Both your example table and those created with the above snippets lack the last element having all 32 bits set, which corresponds to prefix 32, i.e. $address == $network == $broadcast with netmask 255.255.255.255 - fixing that is left as an excercise for the reader.
update: ...a golfed CIDR calculator:
#!/usr/bin/perl # file cidr $m=pack B32,pop=~'/'x$';printf"$` network %vd broadcast %vd netmask %v +d\n",($z=eval$`)&$m,$z|~$m,$m
qwurx [shmem] ~> cidr 192.168.248.17/19 192.168.248.17 network 192.168.224.0 broadcast 192.168.255.255 netmask + 255.255.224.0
In reply to Re: vec vs pack/unpack
by shmem
in thread vec vs pack/unpack
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |