| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Net::IPAM::Block::Private; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 13 |  |  | 13 |  | 133 | use 5.10.0; | 
|  | 13 |  |  |  |  | 34 |  | 
| 4 | 13 |  |  | 13 |  | 59 | use strict; | 
|  | 13 |  |  |  |  | 18 |  | 
|  | 13 |  |  |  |  | 244 |  | 
| 5 | 13 |  |  | 13 |  | 60 | use warnings; | 
|  | 13 |  |  |  |  | 23 |  | 
|  | 13 |  |  |  |  | 245 |  | 
| 6 | 13 |  |  | 13 |  | 51 | use utf8; | 
|  | 13 |  |  |  |  | 24 |  | 
|  | 13 |  |  |  |  | 57 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 13 |  |  | 13 |  | 285 | use Carp          (); | 
|  | 13 |  |  |  |  | 21 |  | 
|  | 13 |  |  |  |  | 255 |  | 
| 9 | 13 |  |  | 13 |  | 54 | use Scalar::Util  (); | 
|  | 13 |  |  |  |  | 18 |  | 
|  | 13 |  |  |  |  | 211 |  | 
| 10 | 13 |  |  | 13 |  | 66 | use Net::IPAM::IP (); | 
|  | 13 |  |  |  |  | 47 |  | 
|  | 13 |  |  |  |  | 27589 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | =head1 NAME | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | Net::IPAM::Block::Private - Just private functions for Net::IPAM::Block | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | Don't pollute the B<< namespace >> of Net::IPAM::Block | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | =cut | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | # use some pre-calculated tables for speed, see end of package | 
| 23 |  |  |  |  |  |  | my ( %valid_masks4, @table_mask_n, @nlz8 ); | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | # 1.2.3.4/255.0.0.0  => {base: 1.0.0.0, last: 1.255.255.255, mask: 255.0.0.0} | 
| 26 |  |  |  |  |  |  | # 1.2.3.4/24         => {base: 1.2.3.0, last: 1.2.3.255,     mask: 255.255.255.0} | 
| 27 |  |  |  |  |  |  | # fe80::1/124 =>        {base: fe80::,  last: fe80::f,       mask: ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0} | 
| 28 |  |  |  |  |  |  | sub _fromMask { | 
| 29 | 227 |  |  | 227 |  | 346 | my ( $self, $addr, $idx ) = @_; | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | # split input in prefix and suffix: | 
| 32 |  |  |  |  |  |  | #   10.0.0.0/255.0.0.0 => 10.0.0.0, 255.0.0.0 | 
| 33 |  |  |  |  |  |  | #   10.0.0.0/8         => 10.0.0.0, 8 | 
| 34 |  |  |  |  |  |  | #   fe80::1/124        => fe80::1,  124 | 
| 35 |  |  |  |  |  |  | # | 
| 36 | 227 |  |  |  |  | 369 | my $prefix_str = substr( $addr, 0, $idx ); | 
| 37 | 227 |  |  |  |  | 333 | my $suffix_str = substr( $addr, $idx + 1 ); | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 227 |  | 100 |  |  | 477 | my $prefix = Net::IPAM::IP->new($prefix_str) // return; | 
| 40 |  |  |  |  |  |  |  | 
| 41 | 225 |  |  |  |  | 3519 | my $mask_n; | 
| 42 | 225 | 100 |  |  |  | 416 | if ( index( $suffix_str, '.' ) >= 0 ) { | 
| 43 | 7 |  | 100 |  |  | 13 | my $ip = Net::IPAM::IP->new($suffix_str) // return; | 
| 44 | 6 |  |  |  |  | 79 | $mask_n = $ip->bytes; | 
| 45 | 6 | 100 |  |  |  | 32 | return unless exists $valid_masks4{$mask_n}; | 
| 46 |  |  |  |  |  |  | } | 
| 47 |  |  |  |  |  |  | else { | 
| 48 | 218 |  |  |  |  | 248 | my $bits = 32; | 
| 49 | 218 | 100 |  |  |  | 369 | $bits = 128 if $prefix->version == 6; | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 218 | 100 |  |  |  | 1223 | return unless $suffix_str =~ m/^\d+$/;    # pos integer | 
| 52 | 216 | 100 |  |  |  | 437 | return if $suffix_str > $bits; | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 212 |  |  |  |  | 355 | $mask_n = _make_mask_n( $suffix_str, $bits ); | 
| 55 |  |  |  |  |  |  | } | 
| 56 |  |  |  |  |  |  |  | 
| 57 | 217 |  |  |  |  | 446 | $self->{base} = Net::IPAM::IP->new_from_bytes( _make_base_n( $prefix->bytes, $mask_n ) ); | 
| 58 | 217 |  |  |  |  | 2798 | $self->{last} = Net::IPAM::IP->new_from_bytes( _make_last_n( $prefix->bytes, $mask_n ) ); | 
| 59 |  |  |  |  |  |  |  | 
| 60 | 217 |  |  |  |  | 2619 | return $self; | 
| 61 |  |  |  |  |  |  | } | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | # 1.2.3.4-1.2.3.17  => {base: 1.2.3.4, last: 1.2.3.17, mask: undef} | 
| 64 |  |  |  |  |  |  | # fe80::-fe80::ffff => {base: fe80::, last: fe80::ffff, mask: ffff:ffff:ffff:ffff:ffff:ffff:ffff::} | 
| 65 |  |  |  |  |  |  | sub _fromRange { | 
| 66 | 81 |  |  | 81 |  | 130 | my ( $self, $addr, $idx ) = @_; | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | # split range in base and last 10.0.0.1-10.0.0.3 => 10.0.0.1, 10.0.0.3 | 
| 69 | 81 |  |  |  |  | 146 | my $base_str = substr( $addr, 0, $idx ); | 
| 70 | 81 |  |  |  |  | 127 | my $last_str = substr( $addr, $idx + 1 ); | 
| 71 |  |  |  |  |  |  |  | 
| 72 | 81 |  | 100 |  |  | 186 | my $base_ip = Net::IPAM::IP->new($base_str) // return; | 
| 73 | 80 |  | 100 |  |  | 1398 | my $last_ip = Net::IPAM::IP->new($last_str) // return; | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | # version base != version last | 
| 76 | 78 |  |  |  |  | 1052 | my $version = $base_ip->version; | 
| 77 | 78 | 100 |  |  |  | 246 | return if $version != $last_ip->version; | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | # base > last? | 
| 80 | 76 | 100 |  |  |  | 274 | return if $base_ip->cmp($last_ip) > 0; | 
| 81 |  |  |  |  |  |  |  | 
| 82 | 74 |  |  |  |  | 350 | $self->{base} = $base_ip; | 
| 83 | 74 |  |  |  |  | 112 | $self->{last} = $last_ip; | 
| 84 |  |  |  |  |  |  |  | 
| 85 | 74 |  |  |  |  | 228 | return $self; | 
| 86 |  |  |  |  |  |  | } | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | # 1.2.3.4 => {base: 1.2.3.4, last: 1.2.3.4, mask: 255.255.255.255} | 
| 89 |  |  |  |  |  |  | # fe80::1 => {base: fe80::1, last: fe80::1, mask: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff} | 
| 90 |  |  |  |  |  |  | sub _fromAddr { | 
| 91 | 65 |  |  | 65 |  | 95 | my ( $self, $addr ) = @_; | 
| 92 |  |  |  |  |  |  |  | 
| 93 | 65 |  | 100 |  |  | 130 | my $base = Net::IPAM::IP->new($addr) // return; | 
| 94 |  |  |  |  |  |  |  | 
| 95 | 63 |  |  |  |  | 1026 | $self->{base} = $base; | 
| 96 | 63 |  |  |  |  | 79 | $self->{last} = $base; | 
| 97 |  |  |  |  |  |  |  | 
| 98 | 63 |  |  |  |  | 141 | return $self; | 
| 99 |  |  |  |  |  |  | } | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | # 1.2.3.4 => {base: 1.2.3.4, last: 1.2.3.4, mask: 255.255.255.255} | 
| 102 |  |  |  |  |  |  | # fe80::1 => {base: fe80::1, last: fe80::1, mask: ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff} | 
| 103 |  |  |  |  |  |  | sub _fromIP { | 
| 104 | 4 |  |  | 4 |  | 8 | my ( $self, $ip ) = @_; | 
| 105 |  |  |  |  |  |  |  | 
| 106 | 4 | 50 | 33 |  |  | 57 | return unless Scalar::Util::blessed($ip) && $ip->isa('Net::IPAM::IP'); | 
| 107 |  |  |  |  |  |  |  | 
| 108 | 4 |  |  |  |  | 12 | $self->{base} = $ip; | 
| 109 | 4 |  |  |  |  | 7 | $self->{last} = $ip; | 
| 110 |  |  |  |  |  |  |  | 
| 111 | 4 |  |  |  |  | 7 | return $self; | 
| 112 |  |  |  |  |  |  | } | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | # my $b = _clone($self) | 
| 115 |  |  |  |  |  |  | sub _clone { | 
| 116 | 19 |  |  | 19 |  | 26 | my $self  = shift; | 
| 117 | 19 |  |  |  |  | 34 | my $clone = bless {}, ref $self; | 
| 118 |  |  |  |  |  |  |  | 
| 119 | 19 |  |  |  |  | 40 | $clone->{base} = Net::IPAM::IP->new_from_bytes( $self->{base}->bytes ); | 
| 120 | 19 |  |  |  |  | 249 | $clone->{last} = Net::IPAM::IP->new_from_bytes( $self->{last}->bytes ); | 
| 121 |  |  |  |  |  |  |  | 
| 122 | 19 |  |  |  |  | 215 | return $clone; | 
| 123 |  |  |  |  |  |  | } | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | # a.base <= b && a.last >= b | 
| 126 |  |  |  |  |  |  | sub _contains_ip { | 
| 127 | 8 |  | 100 | 8 |  | 17 | return $_[0]->{base}->cmp( $_[1] ) <= 0 && $_[0]->{last}->cmp( $_[1] ) >= 0; | 
| 128 |  |  |  |  |  |  | } | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | sub _contains_block { | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | # a == b, return false | 
| 133 | 249 | 100 |  | 249 |  | 377 | return 0 if $_[0]->cmp( $_[1] ) == 0; | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | # a.base <= b.base && a.last >= b.last | 
| 136 | 247 |  | 100 |  |  | 1089 | return $_[0]->{base}->cmp( $_[1]->{base} ) <= 0 && $_[0]->{last}->cmp( $_[1]->{last} ) >= 0; | 
| 137 |  |  |  |  |  |  | } | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | # count leading zeros | 
| 140 |  |  |  |  |  |  | sub _leading_zeros { | 
| 141 | 678 | 50 |  | 678 |  | 1079 | my $n     = shift or die 'missing arg,'; | 
| 142 | 678 |  |  |  |  | 726 | my $zeros = 0; | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | # step byte-wise through $n from left to right | 
| 145 | 678 |  |  |  |  | 1132 | for my $i ( 0 .. length($n) - 1 ) { | 
| 146 | 4359 |  |  |  |  | 4842 | my $byte = vec( $n, $i, 8 ); | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | # count bytes | 
| 149 | 4359 | 100 |  |  |  | 5805 | if ( $byte == 0x00 ) { | 
| 150 | 3789 |  |  |  |  | 3819 | $zeros += 8; | 
| 151 | 3789 |  |  |  |  | 4283 | next; | 
| 152 |  |  |  |  |  |  | } | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  | # count bits, use a pre-calculated table | 
| 155 | 570 |  |  |  |  | 709 | $zeros += $nlz8[$byte]; | 
| 156 | 570 |  |  |  |  | 665 | last; | 
| 157 |  |  |  |  |  |  | } | 
| 158 |  |  |  |  |  |  |  | 
| 159 | 678 |  |  |  |  | 1321 | return $zeros; | 
| 160 |  |  |  |  |  |  | } | 
| 161 |  |  |  |  |  |  |  | 
| 162 |  |  |  |  |  |  | # number of common leading bits | 
| 163 |  |  |  |  |  |  | sub _common_prefix { | 
| 164 | 678 |  |  | 678 |  | 2634 | my ( $base_n, $last_n ) = @_; | 
| 165 | 678 |  |  |  |  | 1176 | return _leading_zeros( $base_n ^ $last_n ); | 
| 166 |  |  |  |  |  |  | } | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | # returns the common prefix bits and ok. ok is true when the range is a CIDR. | 
| 169 |  |  |  |  |  |  | sub _common_ok { | 
| 170 | 503 |  |  | 503 |  | 778 | my ( $base_n, $last_n, $bits ) = @_; | 
| 171 |  |  |  |  |  |  |  | 
| 172 | 503 |  |  |  |  | 735 | my $pfx    = _common_prefix( $base_n, $last_n ); | 
| 173 | 503 |  |  |  |  | 736 | my $mask_n = _make_mask_n( $pfx, $bits ); | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | # apply mask to base and last as AND and OR | 
| 176 |  |  |  |  |  |  | # and check for all zeros and all ones => it's a CIDR | 
| 177 | 503 |  |  |  |  | 903 | my $is_all_zeros = ( $base_n ^ ( $base_n & $mask_n ) ) eq _make_mask_n( 0, $bits ); | 
| 178 | 503 |  |  |  |  | 765 | my $is_all_ones  = ( $last_n | $mask_n ) eq _make_mask_n( 128, $bits ); | 
| 179 |  |  |  |  |  |  |  | 
| 180 | 503 |  | 100 |  |  | 1512 | return $pfx, $is_all_zeros && $is_all_ones; | 
| 181 |  |  |  |  |  |  | } | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | # switch to binary representation | 
| 184 |  |  |  |  |  |  | # push start block on stack | 
| 185 |  |  |  |  |  |  | # | 
| 186 |  |  |  |  |  |  | # loop while stack not dry | 
| 187 |  |  |  |  |  |  | # check if is_cidr | 
| 188 |  |  |  |  |  |  | # split the range in the middle | 
| 189 |  |  |  |  |  |  | # put both halves on stack (reverse order) | 
| 190 |  |  |  |  |  |  | # next | 
| 191 |  |  |  |  |  |  | # | 
| 192 |  |  |  |  |  |  | # return cidrs | 
| 193 |  |  |  |  |  |  | # | 
| 194 |  |  |  |  |  |  | sub _to_cidrs_iter { | 
| 195 | 10 |  |  | 10 |  | 12 | my $self = shift; | 
| 196 | 10 |  |  |  |  | 16 | my @stack; | 
| 197 |  |  |  |  |  |  | my @result; | 
| 198 |  |  |  |  |  |  |  | 
| 199 | 10 |  |  |  |  | 13 | my $bits = 32; | 
| 200 | 10 | 100 |  |  |  | 17 | $bits = 128 if $self->version == 6; | 
| 201 |  |  |  |  |  |  |  | 
| 202 |  |  |  |  |  |  | # make binary representation, put it as start on the stack | 
| 203 | 10 |  |  |  |  | 73 | push @stack, [ $self->{base}->bytes, $self->{last}->bytes ]; | 
| 204 |  |  |  |  |  |  |  | 
| 205 | 10 |  |  |  |  | 66 | while ( scalar @stack > 0 ) { | 
| 206 | 278 |  |  |  |  | 330 | my $block_n = pop @stack; | 
| 207 | 278 |  |  |  |  | 349 | my $base_n  = $block_n->[0]; | 
| 208 | 278 |  |  |  |  | 294 | my $last_n  = $block_n->[1]; | 
| 209 |  |  |  |  |  |  |  | 
| 210 | 278 |  |  |  |  | 371 | my ( $pfx, $is_cidr ) = _common_ok( $base_n, $last_n, $bits ); | 
| 211 |  |  |  |  |  |  |  | 
| 212 |  |  |  |  |  |  | # is this block already a CIDR? | 
| 213 | 278 | 100 |  |  |  | 416 | if ($is_cidr) { | 
| 214 |  |  |  |  |  |  |  | 
| 215 |  |  |  |  |  |  | # add block ro result | 
| 216 | 144 |  |  |  |  | 242 | my $block = bless {}, ref $self; | 
| 217 | 144 |  |  |  |  | 298 | $block->{base} = Net::IPAM::IP->new_from_bytes($base_n); | 
| 218 | 144 |  |  |  |  | 1792 | $block->{last} = Net::IPAM::IP->new_from_bytes($last_n); | 
| 219 |  |  |  |  |  |  |  | 
| 220 | 144 |  |  |  |  | 1571 | push @result, $block; | 
| 221 | 144 |  |  |  |  | 321 | next; | 
| 222 |  |  |  |  |  |  | } | 
| 223 |  |  |  |  |  |  |  | 
| 224 |  |  |  |  |  |  | # split block in two halves, add 1 to common prefix | 
| 225 | 134 |  |  |  |  | 191 | my $mask_n = _make_mask_n( $pfx + 1, $bits ); | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  | # split range with new mask | 
| 228 | 134 |  |  |  |  | 201 | my $mid_last_n = _make_last_n( $base_n, $mask_n ); | 
| 229 | 134 |  |  |  |  | 193 | my $mid_base_n = _make_base_n( $last_n, $mask_n ); | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | # make two new blocks | 
| 232 | 134 |  |  |  |  | 230 | my $block1_n = [ $base_n,     $mid_last_n ]; | 
| 233 | 134 |  |  |  |  | 222 | my $block2_n = [ $mid_base_n, $last_n ]; | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  | # push both blocks to stack, reverse the order | 
| 236 | 134 |  |  |  |  | 313 | push @stack, $block2_n, $block1_n; | 
| 237 |  |  |  |  |  |  | } | 
| 238 |  |  |  |  |  |  |  | 
| 239 | 10 |  |  |  |  | 31 | return \@result; | 
| 240 |  |  |  |  |  |  | } | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | # returns true if base and last forms a CIDR range | 
| 243 |  |  |  |  |  |  | sub _is_cidr { | 
| 244 | 225 |  |  | 225 |  | 280 | my $self = shift; | 
| 245 |  |  |  |  |  |  |  | 
| 246 | 225 |  |  |  |  | 253 | my $bits = 32; | 
| 247 | 225 | 100 |  |  |  | 367 | $bits = 128 if $self->version == 6; | 
| 248 |  |  |  |  |  |  |  | 
| 249 | 225 |  |  |  |  | 815 | my $base_n = $self->{base}->bytes; | 
| 250 | 225 |  |  |  |  | 768 | my $last_n = $self->{last}->bytes; | 
| 251 |  |  |  |  |  |  |  | 
| 252 | 225 |  |  |  |  | 685 | my ( $pfx, $is_cidr ) = _common_ok( $base_n, $last_n, $bits ); | 
| 253 | 225 |  |  |  |  | 606 | return $is_cidr; | 
| 254 |  |  |  |  |  |  | } | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | # base = addr & netMask | 
| 257 |  |  |  |  |  |  | sub _make_base_n { | 
| 258 | 360 |  |  | 360 |  | 920 | my ( $addr_n, $mask_n ) = @_; | 
| 259 | 360 |  |  |  |  | 923 | return $addr_n & $mask_n; | 
| 260 |  |  |  |  |  |  | } | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | # last = addr | hostMask | 
| 263 |  |  |  |  |  |  | sub _make_last_n { | 
| 264 | 369 |  |  | 369 |  | 895 | my ( $addr_n, $mask_n ) = @_; | 
| 265 | 369 |  |  |  |  | 816 | return $addr_n | ~$mask_n; | 
| 266 |  |  |  |  |  |  | } | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | # cut off the bits after 32, used for IPv4 | 
| 269 | 537 |  |  | 537 |  | 1051 | sub _strip_to_32_bits { return $_[0] & "\xff\xff\xff\xff" } | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | # make CIDR mask from bits: | 
| 272 |  |  |  |  |  |  | # (24, 32)  => 0xffff_ff00 | 
| 273 |  |  |  |  |  |  | # (56, 128) => 0xffff_ffff_ffff_ff00_0000_0000_0000_0000 | 
| 274 |  |  |  |  |  |  | # | 
| 275 |  |  |  |  |  |  | sub _make_mask_n { | 
| 276 | 1866 |  |  | 1866 |  | 2388 | my ( $n, $bits ) = @_; | 
| 277 | 1866 |  |  |  |  | 2182 | my $mask_n = $table_mask_n[$n]; | 
| 278 |  |  |  |  |  |  | # | 
| 279 |  |  |  |  |  |  | # cut to first 32 bits | 
| 280 | 1866 | 100 |  |  |  | 2541 | if ( $bits == 32 ) { | 
| 281 | 537 |  |  |  |  | 689 | return _strip_to_32_bits($mask_n); | 
| 282 |  |  |  |  |  |  | } | 
| 283 | 1329 |  |  |  |  | 1780 | return $mask_n; | 
| 284 |  |  |  |  |  |  | } | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | sub _get_mask_n { | 
| 287 | 2 |  |  | 2 |  | 3 | my ( $base_ip, $last_ip ) = @_; | 
| 288 |  |  |  |  |  |  |  | 
| 289 | 2 |  |  |  |  | 5 | my $pfx = _common_prefix( $base_ip->bytes, $last_ip->bytes ); | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 2 |  |  |  |  | 3 | my $bits = 32; | 
| 292 | 2 | 50 |  |  |  | 5 | $bits = 128 if $base_ip->version == 6; | 
| 293 |  |  |  |  |  |  |  | 
| 294 | 2 |  |  |  |  | 10 | return _make_mask_n( $pfx, $bits ); | 
| 295 |  |  |  |  |  |  | } | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  | ############################# | 
| 298 |  |  |  |  |  |  | #     pre-calc tables | 
| 299 |  |  |  |  |  |  | ############################# | 
| 300 |  |  |  |  |  |  |  | 
| 301 |  |  |  |  |  |  | #<<< skip marker for perltidy | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  | # pre-calced masks for 0.0.0.0 - 255.255.255.255 | 
| 304 |  |  |  |  |  |  | # only IPv4 addresses representable as a sequence of 1 bits followed by 0 bits | 
| 305 |  |  |  |  |  |  | # are allowed as masks as input | 
| 306 |  |  |  |  |  |  |  | 
| 307 |  |  |  |  |  |  | %valid_masks4 = ( | 
| 308 |  |  |  |  |  |  | "\x00\x00\x00\x00" => 0,  "\x80\x00\x00\x00" => 1,  "\xc0\x00\x00\x00" => 2, | 
| 309 |  |  |  |  |  |  | "\xe0\x00\x00\x00" => 3,  "\xf0\x00\x00\x00" => 4,  "\xf8\x00\x00\x00" => 5, | 
| 310 |  |  |  |  |  |  | "\xfc\x00\x00\x00" => 6,  "\xfe\x00\x00\x00" => 7,  "\xff\x00\x00\x00" => 8, | 
| 311 |  |  |  |  |  |  | "\xff\x80\x00\x00" => 9,  "\xff\xc0\x00\x00" => 10, "\xff\xe0\x00\x00" => 11, | 
| 312 |  |  |  |  |  |  | "\xff\xf0\x00\x00" => 12, "\xff\xf8\x00\x00" => 13, "\xff\xfc\x00\x00" => 14, | 
| 313 |  |  |  |  |  |  | "\xff\xfe\x00\x00" => 15, "\xff\xff\x00\x00" => 16, "\xff\xff\x80\x00" => 17, | 
| 314 |  |  |  |  |  |  | "\xff\xff\xc0\x00" => 18, "\xff\xff\xe0\x00" => 19, "\xff\xff\xf0\x00" => 20, | 
| 315 |  |  |  |  |  |  | "\xff\xff\xf8\x00" => 21, "\xff\xff\xfc\x00" => 22, "\xff\xff\xfe\x00" => 23, | 
| 316 |  |  |  |  |  |  | "\xff\xff\xff\x00" => 24, "\xff\xff\xff\x80" => 25, "\xff\xff\xff\xc0" => 26, | 
| 317 |  |  |  |  |  |  | "\xff\xff\xff\xe0" => 27, "\xff\xff\xff\xf0" => 28, "\xff\xff\xff\xf8" => 29, | 
| 318 |  |  |  |  |  |  | "\xff\xff\xff\xfc" => 30, "\xff\xff\xff\xfe" => 31, "\xff\xff\xff\xff" => 32, | 
| 319 |  |  |  |  |  |  | ); | 
| 320 |  |  |  |  |  |  |  | 
| 321 |  |  |  |  |  |  | # pre-calced CIDR masks for /0 .. /128, | 
| 322 |  |  |  |  |  |  | # e.g. | 
| 323 |  |  |  |  |  |  | # $table_mask_n[3]   == "\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" | 
| 324 |  |  |  |  |  |  | # $table_mask_n[64]  == "\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00" | 
| 325 |  |  |  |  |  |  | # $table_mask_n[128] == "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | @table_mask_n = ( | 
| 328 |  |  |  |  |  |  | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 329 |  |  |  |  |  |  | "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 330 |  |  |  |  |  |  | "\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 331 |  |  |  |  |  |  | "\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 332 |  |  |  |  |  |  | "\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 333 |  |  |  |  |  |  | "\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 334 |  |  |  |  |  |  | "\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 335 |  |  |  |  |  |  | "\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 336 |  |  |  |  |  |  | "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 337 |  |  |  |  |  |  | "\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 338 |  |  |  |  |  |  | "\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 339 |  |  |  |  |  |  | "\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 340 |  |  |  |  |  |  | "\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 341 |  |  |  |  |  |  | "\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 342 |  |  |  |  |  |  | "\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 343 |  |  |  |  |  |  | "\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 344 |  |  |  |  |  |  | "\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 345 |  |  |  |  |  |  | "\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 346 |  |  |  |  |  |  | "\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 347 |  |  |  |  |  |  | "\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 348 |  |  |  |  |  |  | "\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 349 |  |  |  |  |  |  | "\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 350 |  |  |  |  |  |  | "\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 351 |  |  |  |  |  |  | "\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 352 |  |  |  |  |  |  | "\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 353 |  |  |  |  |  |  | "\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 354 |  |  |  |  |  |  | "\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 355 |  |  |  |  |  |  | "\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 356 |  |  |  |  |  |  | "\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 357 |  |  |  |  |  |  | "\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 358 |  |  |  |  |  |  | "\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 359 |  |  |  |  |  |  | "\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 360 |  |  |  |  |  |  | "\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 361 |  |  |  |  |  |  | "\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 362 |  |  |  |  |  |  | "\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 363 |  |  |  |  |  |  | "\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 364 |  |  |  |  |  |  | "\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 365 |  |  |  |  |  |  | "\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 366 |  |  |  |  |  |  | "\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 367 |  |  |  |  |  |  | "\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 368 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 369 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 370 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 371 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 372 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 373 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 374 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 375 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 376 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 377 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 378 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 379 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 380 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 381 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 382 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 383 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 384 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 385 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 386 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 387 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 388 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 389 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 390 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 391 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 392 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00", | 
| 393 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00", | 
| 394 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00", | 
| 395 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00\x00", | 
| 396 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00", | 
| 397 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00\x00", | 
| 398 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00\x00", | 
| 399 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00\x00", | 
| 400 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00", | 
| 401 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00", | 
| 402 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00", | 
| 403 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00\x00", | 
| 404 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00", | 
| 405 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00\x00", | 
| 406 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x00", | 
| 407 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x00", | 
| 408 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00", | 
| 409 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00", | 
| 410 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00", | 
| 411 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00\x00", | 
| 412 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00", | 
| 413 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00\x00", | 
| 414 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00\x00", | 
| 415 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00\x00", | 
| 416 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00", | 
| 417 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00\x00", | 
| 418 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00", | 
| 419 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00\x00", | 
| 420 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00", | 
| 421 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00\x00", | 
| 422 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00\x00", | 
| 423 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00\x00", | 
| 424 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00", | 
| 425 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00\x00", | 
| 426 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00", | 
| 427 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00\x00", | 
| 428 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00", | 
| 429 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x00", | 
| 430 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00\x00", | 
| 431 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00\x00", | 
| 432 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00", | 
| 433 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00\x00", | 
| 434 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00", | 
| 435 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00\x00", | 
| 436 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00\x00", | 
| 437 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x00", | 
| 438 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x00", | 
| 439 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x00", | 
| 440 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00", | 
| 441 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x00", | 
| 442 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00", | 
| 443 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x00", | 
| 444 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x00", | 
| 445 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00", | 
| 446 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00", | 
| 447 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00", | 
| 448 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00", | 
| 449 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80", | 
| 450 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0", | 
| 451 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0", | 
| 452 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0", | 
| 453 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8", | 
| 454 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc", | 
| 455 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe", | 
| 456 |  |  |  |  |  |  | "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", | 
| 457 |  |  |  |  |  |  | ); | 
| 458 |  |  |  |  |  |  |  | 
| 459 |  |  |  |  |  |  | # pre-calced 'number of leading zeros' for byte values 0x00 - 0xff | 
| 460 |  |  |  |  |  |  | # e.g. | 
| 461 |  |  |  |  |  |  | # $nlz[0]  ==  8 # 0b0000_0000 | 
| 462 |  |  |  |  |  |  | # $nlz[1]  ==  7 # 0b0000_0001 | 
| 463 |  |  |  |  |  |  | # $nlz[64] ==  1 # 0b0100_0000 | 
| 464 |  |  |  |  |  |  | # $nlz[128] == 0 # 0b1000_0000 | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | @nlz8 = ( | 
| 467 |  |  |  |  |  |  | 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, # 00..1f | 
| 468 |  |  |  |  |  |  | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, # 20..3f | 
| 469 |  |  |  |  |  |  | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 40..5f | 
| 470 |  |  |  |  |  |  | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 60..7f | 
| 471 |  |  |  |  |  |  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 80..9f | 
| 472 |  |  |  |  |  |  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # a0..bf | 
| 473 |  |  |  |  |  |  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # c0..df | 
| 474 |  |  |  |  |  |  | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # e0..ff | 
| 475 |  |  |  |  |  |  | ); | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  | #################################### | 
| 478 |  |  |  |  |  |  | #>>> end of skip marker for perltidy | 
| 479 |  |  |  |  |  |  | #################################### | 
| 480 |  |  |  |  |  |  |  | 
| 481 |  |  |  |  |  |  | =head1 AUTHOR | 
| 482 |  |  |  |  |  |  |  | 
| 483 |  |  |  |  |  |  | Karl Gaissmaier, C<<  >> | 
| 484 |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  | =head1 LICENSE AND COPYRIGHT | 
| 486 |  |  |  |  |  |  |  | 
| 487 |  |  |  |  |  |  | This software is copyright (c) 2020-2022 by Karl Gaissmaier. | 
| 488 |  |  |  |  |  |  |  | 
| 489 |  |  |  |  |  |  | This is free software; you can redistribute it and/or modify it under | 
| 490 |  |  |  |  |  |  | the same terms as the Perl 5 programming language system itself. | 
| 491 |  |  |  |  |  |  |  | 
| 492 |  |  |  |  |  |  | =cut | 
| 493 |  |  |  |  |  |  |  | 
| 494 |  |  |  |  |  |  | 1; |