### vec vs pack/unpack

 on Jul 08, 2018 at 03:47 UTC 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;
print \$_,\$/
for map {
join ".", unpack "C4", \$_
__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
+d\n",(\$z=eval\$`)&\$m,\$z|~\$m,\$m
```qwurx [shmem] ~> cidr 192.168.248.17/19
+ 255.255.224.0
perl -le'print map{pack c,(\$-++?1:13)+ord}split//,ESEL'
Re: vec vs pack/unpack
by johngg (Canon) 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 \$value = 0xfffffffe;

for my \$maskLen ( reverse 0 .. 31 )
{
\$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

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?

Create A New User
Node Status?
node history
Node Type: perlquestion [id://1218098]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (5)
As of 2019-02-19 08:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
I use postfix dereferencing ...

Results (104 votes). Check out past polls.

Notices?