Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

vec vs pack/unpack

by Anonymous Monk
on Jul 08, 2018 at 03:47 UTC ( #1218098=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I wish to create a 32 element array of subnet masks using only pure perl, no packages. My goal is to understand vec vs pack/unpack. Here is an example of the code and table I want to create using vec and/or pack/unpack:
@_ = (0, map -1<<$_ , reverse 0 .. 31); print unpack("B*",pack(N,$_)) . "\n" foreach @_; 00000000000000000000000000000000 10000000000000000000000000000000 11000000000000000000000000000000 11100000000000000000000000000000 11110000000000000000000000000000 11111000000000000000000000000000 11111100000000000000000000000000 11111110000000000000000000000000 11111111000000000000000000000000 11111111100000000000000000000000 11111111110000000000000000000000 11111111111000000000000000000000 11111111111100000000000000000000 11111111111110000000000000000000 11111111111111000000000000000000 11111111111111100000000000000000 11111111111111110000000000000000 11111111111111111000000000000000 11111111111111111100000000000000 11111111111111111110000000000000 11111111111111111111000000000000 11111111111111111111100000000000 11111111111111111111110000000000 11111111111111111111111000000000 11111111111111111111111100000000 11111111111111111111111110000000 11111111111111111111111111000000 11111111111111111111111111100000 11111111111111111111111111110000 11111111111111111111111111111000 11111111111111111111111111111100 11111111111111111111111111111110
So, can you create the 32 element array using vec or pack/unpack? I give up.

Replies are listed 'Best First'.
Re: vec vs pack/unpack
by shmem (Chancellor) on Jul 08, 2018 at 10:00 UTC

    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
    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
Re: vec vs pack/unpack
by johngg (Abbot) on Jul 08, 2018 at 12:57 UTC

    This is an adapted excerpt from a larger script and uses pack in a loop on a bit-shifted value.

    use 5.022; use warnings; my @netmasks; my $value = 0xfffffffe; for my $maskLen ( reverse 0 .. 31 ) { unshift @netmasks, pack q{N}, $value; $value = do { no warnings qw{ portable }; ( $value <<= 1 ) % 0x100000000; }; } say for map { unpack q{B32}, $_ } @netmasks;

    The output.

    00000000000000000000000000000000 10000000000000000000000000000000 11000000000000000000000000000000 11100000000000000000000000000000 11110000000000000000000000000000 11111000000000000000000000000000 11111100000000000000000000000000 11111110000000000000000000000000 11111111000000000000000000000000 11111111100000000000000000000000 11111111110000000000000000000000 11111111111000000000000000000000 11111111111100000000000000000000 11111111111110000000000000000000 11111111111111000000000000000000 11111111111111100000000000000000 11111111111111110000000000000000 11111111111111111000000000000000 11111111111111111100000000000000 11111111111111111110000000000000 11111111111111111111000000000000 11111111111111111111100000000000 11111111111111111111110000000000 11111111111111111111111000000000 11111111111111111111111100000000 11111111111111111111111110000000 11111111111111111111111111000000 11111111111111111111111111100000 11111111111111111111111111110000 11111111111111111111111111111000 11111111111111111111111111111100 11111111111111111111111111111110

    I hope this is helpful.

    Cheers,

    JohnGG

Re: vec vs pack/unpack
by KurtZ (Friar) on Jul 08, 2018 at 06:43 UTC
    I don't understand, you already have a pack solution, don't you?

    What you need is a vec one, right?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1218098]
Front-paged by Corion
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2018-07-22 07:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?















    Results (452 votes). Check out past polls.

    Notices?