diff --git a/Changes b/Changes index 5e94767..e7a2f3f 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,12 @@ Revision history for Perl extension NetAddr::IP +4.050 Sat Oct 22 01:58:57 PDT 2011 + In Lite/Util/lib/NetAddr/IP/Lite/Util/InetBase.pm v0.02 + Socket6 prior to version 0.23 does not have AF_INET6 in the + EXPORT_OK array, modify InetBase.pm v0.2 to work around this. + + Add support for Math::BigInt to NetAddr::IP::Lite v1.33 + 4.049 Sat Oct 15 22:15:10 PDT 2011 Updates to Lite.pm, Util.pm, new module InetBase.pm diff --git a/IP.pm b/IP.pm index 935676e..8b64154 100644 --- a/IP.pm +++ b/IP.pm @@ -35,7 +35,7 @@ @ISA = qw(Exporter NetAddr::IP::Lite); -$VERSION = do { sprintf " %d.%03d", (q$Revision: 4.49 $ =~ /\d+/g) }; +$VERSION = do { sprintf " %d.%03d", (q$Revision: 4.50 $ =~ /\d+/g) }; =pod @@ -63,8 +63,9 @@ NOTE: NetAddr::IP::Util has a full complement of network address utilities to convert back and forth between binary and text. - inet_aton, inet_ntoa, ipv6_aton, ipv6_n2x, ipv6_n2d - inet_any2d, inet_n2dx, inet_n2ad, inetanyto6, ipv6to4 + inet_aton, inet_ntoa, ipv6_aton, ipv6_ntoa + ipv6_n2x, ipv6_n2d inet_any2d, inet_n2dx, + inet_n2ad, inetanyto6, ipv6to4 See L @@ -187,8 +188,8 @@ This module provides an object-oriented abstraction on top of IP addresses or IP subnets, that allows for easy manipulations. -Version 4.xx of NetAdder::IP will will work older -versions of Perl and does B use Math::BigInt as in previous versions. +Version 4.xx of NetAdder::IP will will work with older +versions of Perl and does B use but is compatible with Math::BigInt. The internal representation of all IP objects is in 128 bit IPv6 notation. IPv4 and IPv6 objects may be freely mixed. @@ -594,7 +595,8 @@ ::x:x/host 0xABCDEF, 0b111111000101011110 within the limits of perl's number resolution - 123456789012 a 'big' bcd number i.e. Math::BigInt + 123456789012 a 'big' bcd number (bigger than perl likes) + and Math::BigInt If called with no arguments, 'default' is assumed. @@ -706,6 +708,14 @@ This method is essential for serializing the representation of a subnet. +=item C<-Ebigint()> + +When called in scalar context, will return a Math::BigInt +representation of the address part of the IP address. When called in +an array context, it returns a list of tow elements, The first +element is as described, the second element is the Math::BigInt +representation of the netmask. + =item C<-Ewildcard()> When called in a scalar context, returns the wildcard bits diff --git a/Lite/Changes b/Lite/Changes index 7990ca0..c2b80fb 100644 --- a/Lite/Changes +++ b/Lite/Changes @@ -1,5 +1,12 @@ Revision history for Perl extension NetAddr::IP::Lite +1.33 Sat Oct 22 01:47:42 PDT 2011 + In Lite/Util/lib/NetAddr/IP/Lite/Util/InetBase.pm v0.02 + Socket6 prior to version 0.23 does not have AF_INET6 in the + EXPORT_OK array, modify InetBase.pm v0.2 to work around this. + + Add support for Math::BigInt objects + 1.32 Sat Oct 15 22:05:23 PDT 2011 bug68723, add capability to parse input of the form ->new6(12345,1). This should have been there but was diff --git a/Lite/Lite.pm b/Lite/Lite.pm index 6b9cc54..b0b13de 100644 --- a/Lite/Lite.pm +++ b/Lite/Lite.pm @@ -11,6 +11,7 @@ isIPv4 inet_n2dx inet_aton +inet_ntoa ipv6_aton ipv6_n2x ); @@ -31,7 +32,7 @@ use vars qw(@ISA @EXPORT_OK $VERSION $Accept_Binary_IP $Old_nth $AUTOLOAD *Zero); -$VERSION = do { my @r = (q$Revision: 1.32 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; +$VERSION = do { my @r = (q$Revision: 1.33 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; require Exporter; @@ -111,8 +112,8 @@ This module provides an object-oriented abstraction on top of IP addresses or IP subnets, that allows for easy manipulations. Most of the -operations of NetAddr::IP are supported. This module will work older -versions of Perl and does B use Math::BigInt. +operations of NetAddr::IP are supported. This module will work with older +versions of Perl and does B use but is compatible with Math::BigInt. * By default B functions and methods return string IPv6 addresses in uppercase. To change that to lowercase: @@ -606,7 +607,8 @@ ::x:x/host 0xABCDEF, 0b111111000101011110 within the limits of perl's number resolution - 123456789012 a 'big' bcd number i.e. Math::BigInt + 123456789012 a 'big' bcd number (bigger than perl likes) + and Math::BigInt If called with no arguments, 'default' is assumed. @@ -727,16 +729,26 @@ my $class = ref $proto || $proto || __PACKAGE__; my $ip = lc shift; $ip = 'default' unless defined $ip; + $ip = join('',reverse @{$ip->{value}}) # treat as big bcd string + if ref $ip && ref $ip eq 'Math::BigInt' && # can /CIDR notation + ($ip->{sign} eq '+' || + die 'NetAddr::IP does not accept negative Math::BigInt numbers'); my $hasmask = 1; my($mask,$tmp); while (1) { +# process IP's with no CIDR or that have the CIDR as part of the IP argument string unless (@_) { # if ($ip =~ m!^(.+)/(.+)$!) { - if ($ip =~ m!^([a-z0-9.:-]+)(?:/|\s+)([a-z0-9.:-]+)$!) { + if ($ip !~ /\D/) { # binary number notation + $ip = bcd2bin($ip); + $mask = Ones; + last; + } + elsif ($ip =~ m!^([a-z0-9.:-]+)(?:/|\s+)([a-z0-9.:-]+)$!) { $ip = $1; $mask = $2; - } elsif (grep($ip eq $_,qw(default any broadcast loopback unspecified))) { + } elsif (grep($ip eq $_,(qw(default any broadcast loopback unspecified)))) { $isV6 = 1 if $ip eq 'unspecified'; if ($isV6) { $mask = $fip6m{$ip}; @@ -748,80 +760,93 @@ last; } } +# process "ipv6" token and default IP's elsif (defined $_[0]) { if ($_[0] =~ /ipv6/i || $isV6) { - if (grep($ip eq $_,qw(default any loopback unspecified))) { + if (grep($ip eq $_,(qw(default any loopback unspecified)))) { $mask = $fip6m{$ip}; $ip = $fip6{$ip}; last; } else { return undef unless $isV6; # add for ipv6 notation "12345, 1" - $mask = lc $_[0]; } - } else { - $mask = lc $_[0]; +# $mask = lc $_[0]; +# } else { +# $mask = lc $_[0]; } +# extract mask + $mask = lc $_[0]; } +### +### process mask unless (defined $mask) { $hasmask = 0; $mask = 'host'; } -# parse mask - if ($mask =~ /^(\d+)$/) { - my $mval = $1; -# need to test here for 'dots' try running the tests that fail with $ip =~ /\D/ and print what IP is to see what's missing - if (! $isV6 && index($ip,':') < 0) { # ipV4 - my $try; - if ($ip !~ /\D/ && # binary IP address, could be ipV6 - ($try = bcd2bin($ip)) && - ! isIPv4($try) ) { - $isV6 = 1; - if ($mask < 128) { # small cidr - $mask = shiftleft(Ones,128 -$mval); # with small cidr - } else { # else binary mask - $mask = bcd2bin($mval); +# two kinds of IP's can turn on the isV6 flag +# 1) big digits that are over the IPv4 boundry +# 2) IPv6 IP syntax +# +# check these conditions and set isV6 as appropriate +# + my $try; + $isV6 = 1 # unconditionally + if # check big bcd and IPv6 rfc1884 + ( $ip !~ /\D/ && # ip is all decimal + (length($ip) > 3 || $ip > 255) && # exclude a single digit in the range of zero to 255, could be funny IPv4 + ($try = bcd2bin($ip)) && ! isIPv4($try)) || # precedence so $try is not corrupted + (index($ip,':') >= 0 && ($try = ipv6_aton($ip))); # fails if not an rfc1884 address + +# if either of the above conditions is true, $try contains the NetAddr 128 bit address + +# checkfor Math::BigInt mask + $mask = join('',reverse @{$mask->{value}}) # treat as big bcd string + if ref $mask && ref $mask eq 'Math::BigInt' && + ($mask->{sign} eq '+' || + die 'NetAddr::IP does not accept negative Math::BigInt numbers'); + if ($mask !~ /\D/) { # bcd or CIDR notation + my $isCIDR = length($mask) < 4 && $mask < 129; + if ($isV6) { + if ($isCIDR) { + if ($ip =~ /^\d+\.\d+\.\d+\.\d+$/) { # corner condition of IPv4 with isV6 + $try = ipv4to6(inet_aton($ip)); + if ($mask < 32) { + $mask = shiftleft(Ones,32 -$mask); + } + elsif ($mask == 32) { + $mask = Ones; + } else { + return undef; # undoubtably an error + } } - $ip = $try; - last; - } - elsif ($mval == 32) { # cidr 32 - $mask = Ones; - } - elsif ($mask < 32) { # small cidr - $mask = shiftleft(Ones,32 -$mval); - } else { # is a binary mask - $mask = pack('L3N',0xffffffff,0xffffffff,0xffffffff,$mval); - } -# } -# elsif (! $isV6 && $ip !~ /\D/) { # is just a big number -# $ip = bcd2bin($ip); # special case -# if (isAnyIPv4($ip)) { -# $mask = shiftleft(Ones,32 -$mval); -# } else { -# $mask = shiftleft(Ones,128 -$mval); -# } - } else { # is ipV6 - $isV6 = 1; - if ($mval == 128) { # cidr 128 - $mask = Ones; - } - elsif ($ip !~ /\D/) { # numeric IPv6 address - if ($mask < 128) { # small cidr - $mask = shiftleft(Ones,128 -$mval); # with small cidr - } else { # else binary mask - $mask = bcd2bin($mval); + elsif ($mask < 128) { + $mask = shiftleft(Ones,128 -$mask); # small cidr + } else { + $mask = Ones(); } + } else { + $mask = bcd2bin($mask); } - elsif (index($ip,':') < 0) { # corner case of ipV4 with new6 - $mask = shiftleft(Ones,32 -$mval); + } + elsif ($isCIDR && $mask < 33) { # is V4 + if ($mask < 32) { + $mask = shiftleft(Ones,32 -$mask); } - elsif ($mask < 128) { # small cidr - $mask = shiftleft(Ones,128 -$mval); - } else { # is a binary mask - $mask = bcd2bin($mval); + elsif ( $mask == 32) { + $mask = Ones; + } else { + $mask = bcd2bin($mask); + $mask |= $_v4mask; # v4 always } + } else { # also V4 + $mask = bcd2bin($mask); + $mask |= $_v4mask; + } + if ($try) { # is a big number + $ip = $try; + last; } } elsif ($mask =~ m/^\d+\.\d+\.\d+\.\d+$/) { # ipv4 form of mask $mask = _no_octal($mask) if $noctal; # filter for octal @@ -837,13 +862,13 @@ return undef unless defined ($mask = ipv6_aton($mask)); # try ipv6 form of mask } -# parse IP +# process remaining IP's if (index($ip,':') < 0) { # ipv4 address if ($ip =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { ; # the common case } - elsif (grep($ip eq $_,qw(default any broadcast loopback))) { + elsif (grep($ip eq $_,(qw(default any broadcast loopback)))) { return undef unless defined ($ip = $fip4{$ip}); last; } @@ -865,6 +890,7 @@ $ip = bcd2bin($ip); last; } +# these next three might be broken??? but they have been in the code a long time and no one has complained elsif ($ip =~ /^0[xb]\d+$/ && $hasmask && (($tmp = eval "$ip") || 1) && $tmp >= 0 && $tmp < 256) { @@ -965,12 +991,11 @@ $ip = $tmp; last; } - last if grep($ip eq $_,qw(default any loopback unspecified)) && + last if grep($ip eq $_,(qw(default any loopback unspecified))) && defined ($ip = $fip6{$ip}); return undef; } } # end while (1) - return undef if notcontiguous($mask); # invalid if not contiguous my $self = { @@ -1120,7 +1145,7 @@ When called in a scalar context, will return a numeric representation of the address part of the IP address. When called in an array -contest, it returns a list of two elements. The first element is as +context, it returns a list of two elements. The first element is as described, the second element is the numeric representation of the netmask. @@ -1145,6 +1170,74 @@ : bin2bcd($_[0]->{addr}); } +=item C<-Ebigint()> + +When called in a scalar context, will return a Math::BigInt representation +of the address part of the IP address. When called in an array +contest, it returns a list of two elements. The first element is as +described, the second element is the Math::BigInt representation of the +netmask. + +=cut + +sub _biValue { + my $bi; + unless ($_[0]) { + $bi = { + sign => '+', + value => ['0'], + }; + return bless $bi, 'Math::BigInt'; + } + my $numstr = $_[0]; + my @bi; + while ($numstr) { + my $nibble = substr($numstr,-7,7,''); + push @bi, $nibble; + } + $bi = { + sign => '+', + value => \@bi, + }; + bless $bi, 'Math::BigInt'; +} + +sub bigint($) { + my($addr,$mask); + if (wantarray) { + if (! $_[0]->{isv6} && isIPv4($_[0]->{addr})) { + $addr = $_[0]->{addr} + ? sprintf("%u",unpack('N',ipv6to4($_[0]->{addr}))) + : 0; + $mask = $_[0]->{mask} + ? sprintf("%u",unpack('N',ipv6to4($_[0]->{mask}))) + : 0; + } + else { + $addr = $_[0]->{addr} + ? bin2bcd($_[0]->{addr}) + : 0; + $mask = $_[0]->{mask} + ? bin2bcd($_[0]->{mask}) + : 0; + } + (_biValue($addr),_biValue($mask)); + + } else { # not wantarray + + if (! $_[0]->{isv6} && isIPv4($_[0]->{addr})) { + $addr = $_[0]->{addr} + ? sprintf("%u",unpack('N',ipv6to4($_[0]->{addr}))) + : 0; + } else { + $addr = $_[0]->{addr} + ? bin2bcd($_[0]->{addr}) + : 0; + } + _biValue($addr); + } +} + =item C<$me-Econtains($other)> Returns true when C<$me> completely contains C<$other>. False is @@ -1379,7 +1472,7 @@ :upper :lower -=head1 AUTHOR +=head1 AUTHORS Luis E. Mu�oz Eluismunoz@cpan.orgE, Michael Robinton Emichael@bizsystems.comE diff --git a/Lite/MANIFEST b/Lite/MANIFEST index fe92d78..600fe4c 100644 --- a/Lite/MANIFEST +++ b/Lite/MANIFEST @@ -8,7 +8,8 @@ bug2742981 t/addr.t t/aton.t -t/bigints.t +t/bigint.t +t/bignums.t t/bin_ips.t t/bits.t t/broadcast.t diff --git a/Lite/README b/Lite/README index fcbae0f..6bc3364 100644 --- a/Lite/README +++ b/Lite/README @@ -59,7 +59,7 @@ This module provides an object-oriented abstraction on top of IP addresses or IP subnets, that allows for easy manipulations. Most of the operations of NetAddr::IP are supported. This module will work older - versions of Perl and does not use Math::BigInt. + versions of Perl and does not use but is compatible with Math::BigInt. * By default NetAddr::IP functions and methods return string IPv6 addresses in uppercase. To change that to lowercase: @@ -284,7 +284,8 @@ ::x:x/host 0xABCDEF, 0b111111000101011110 within the limits of perl's number resolution - 123456789012 a 'big' bcd number i.e. Math::BigInt + 123456789012 a 'big' bcd number (bigger than perl likes) + and Math::BigInt If called with no arguments, 'default' is assumed. @@ -349,6 +350,13 @@ This method is essential for serializing the representation of a subnet. + "->bigint()" + When called in a scalar context, will return a Math::BigInt + representation of the address part of the IP address. When called in + an array contest, it returns a list of two elements. The first + element is as described, the second element is the Math::BigInt + representation of the netmask. + "$me->contains($other)" Returns true when "$me" completely contains "$other". False is returned otherwise and "undef" is returned if "$me" and "$other" are @@ -453,7 +461,7 @@ :upper :lower -AUTHOR +AUTHORS Luis E. Mu�oz , Michael Robinton diff --git a/Lite/Util/Changes b/Lite/Util/Changes index a922282..c0385cd 100644 --- a/Lite/Util/Changes +++ b/Lite/Util/Changes @@ -1,3 +1,6 @@ +1.42 Fri Oct 21 10:34:46 PDT 2011 + Socket6 prior to version 0.23 does not have AF_INET6 in the + EXPORT_OK array, modify InetBase.pm v0.2 to work around this. 1.41 Sat Oct 15 17:26:21 PDT 2011 add inet_pton, inet_ntop, AF_INET, AF_INET6 diff --git a/Lite/Util/Makefile.PL b/Lite/Util/Makefile.PL index c13e77b..d25d9cc 100644 --- a/Lite/Util/Makefile.PL +++ b/Lite/Util/Makefile.PL @@ -39,7 +39,7 @@ # depend => {$cfile => q[xs_include/miniSocket.inc localconf.h config.h localperl.h], depend => {$cfile => q[ localconf.h config.h localperl.h ], }, -# PREREQ_PM => {Test::More => 0, +# PREREQ_PM => { Socket6 => 0.23, can't do this # }, LIBS => [], XS => {}, diff --git a/Lite/Util/Util.pm b/Lite/Util/Util.pm index 774aff8..058693a 100644 --- a/Lite/Util/Util.pm +++ b/Lite/Util/Util.pm @@ -21,7 +21,7 @@ @ISA = qw(Exporter DynaLoader); -$VERSION = do { my @r = (q$Revision: 1.41 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; +$VERSION = do { my @r = (q$Revision: 1.42 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; @EXPORT_OK = qw( inet_aton diff --git a/Lite/Util/lib/NetAddr/IP/InetBase.pm b/Lite/Util/lib/NetAddr/IP/InetBase.pm index 1d1fe1b..5fd67ec 100644 --- a/Lite/Util/lib/NetAddr/IP/InetBase.pm +++ b/Lite/Util/lib/NetAddr/IP/InetBase.pm @@ -11,7 +11,7 @@ @ISA = qw(Exporter); -$VERSION = do { my @r = (q$Revision: 0.01 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; +$VERSION = do { my @r = (q$Revision: 0.02 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; @EXPORT_OK = qw( inet_aton @@ -81,17 +81,12 @@ $emulateAF_INET6 = -1; # have it, remind below } if (eval{ require Socket6 } ) { - if ($emulateAF_INET6) { - import Socket6 qw( + import Socket6 qw( inet_pton inet_ntop - ); - } else { - import Socket6 qw( - inet_pton - inet_ntop - AF_INET6 - ); + ); + unless ($emulateAF_INET6) { + *AF_INET6 = \&Socket6::AF_INET6; } $emulateAF_INET6 = 0; # clear, have it from elsewhere or here } else { diff --git a/Lite/t/bigint.t b/Lite/t/bigint.t new file mode 100644 index 0000000..c07701c --- /dev/null +++ b/Lite/t/bigint.t @@ -0,0 +1,665 @@ + +use strict; +#use diagnostics; +use Test::More; + +use NetAddr::IP::Lite; + +use Data::Dumper; + +BEGIN { + unless ( eval { require Math::BigInt }) { + print "ok 1 # skip all tests, Math::BigInt not found!\n"; + exit; + } + import Math::BigInt @Math::BigInt::EXPORTS; +} + +# good test results go here +my $build = q| +not ok 1 +# Failed test in test.pl at line 39. +# got: '4294967294' +# expected: undef +not ok 2 +# Failed test in test.pl at line 41. +# got: '255.255.255.254/32' +# expected: undef +not ok 3 +# Failed test in test.pl at line 39. +# got: '4294967295' +# expected: undef +not ok 4 +# Failed test in test.pl at line 41. +# got: '255.255.255.255/32' +# expected: undef +not ok 5 +# Failed test in test.pl at line 39. +# got: '4294967296' +# expected: undef +not ok 6 +# Failed test in test.pl at line 41. +# got: '0:0:0:0:0:1:0:0/128' +# expected: undef +not ok 7 +# Failed test in test.pl at line 39. +# got: '4294967297' +# expected: undef +not ok 8 +# Failed test in test.pl at line 41. +# got: '0:0:0:0:0:1:0:1/128' +# expected: undef +not ok 9 +# Failed test in test.pl at line 39. +# got: '4294967298' +# expected: undef +not ok 10 +# Failed test in test.pl at line 41. +# got: '0:0:0:0:0:1:0:2/128' +# expected: undef +not ok 11 +# Failed test in test.pl at line 39. +# got: '340282366920938463463374607431768211454' +# expected: undef +not ok 12 +# Failed test in test.pl at line 41. +# got: 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFE/128' +# expected: undef +not ok 13 +# Failed test in test.pl at line 39. +# got: '340282366920938463463374607431768211455' +# expected: undef +not ok 14 +# Failed test in test.pl at line 41. +# got: 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF/128' +# expected: undef +not ok 15 +# Failed test in test.pl at line 39. +# got: '340282366920938463463374607431768211456' +# expected: undef +not ok 16 +# Failed test in test.pl at line 41. +# got: '0.0.0.0/32' +# expected: undef +not ok 17 +# Failed test in test.pl at line 39. +# got: '1' +# expected: undef +not ok 18 +# Failed test in test.pl at line 41. +# got: '0.0.0.1/32' +# expected: undef +not ok 19 +# Failed test in test.pl at line 39. +# got: '2' +# expected: undef +not ok 20 +# Failed test in test.pl at line 41. +# got: '0.0.0.2/32' +# expected: undef +not ok 21 +# Failed test in test.pl at line 63. +# got: '2066563929' +# expected: undef +not ok 22 +# Failed test in test.pl at line 64. +# got: '4294967295' +# expected: undef +not ok 23 +# Failed test in test.pl at line 65. +# got: '123.45.67.89/32' +# expected: undef +not ok 24 +# Failed test in test.pl at line 63. +# got: '2066563929' +# expected: undef +not ok 25 +# Failed test in test.pl at line 64. +# got: '4294967280' +# expected: undef +not ok 26 +# Failed test in test.pl at line 65. +# got: '123.45.67.89/28' +# expected: undef +not ok 27 +# Failed test in test.pl at line 63. +# got: '2066563929' +# expected: undef +not ok 28 +# Failed test in test.pl at line 64. +# got: '4294967040' +# expected: undef +not ok 29 +# Failed test in test.pl at line 65. +# got: '123.45.67.89/24' +# expected: undef +not ok 30 +# Failed test in test.pl at line 63. +# got: '2066563929' +# expected: undef +not ok 31 +# Failed test in test.pl at line 64. +# got: '4294963200' +# expected: undef +not ok 32 +# Failed test in test.pl at line 65. +# got: '123.45.67.89/20' +# expected: undef +not ok 33 +# Failed test in test.pl at line 63. +# got: '2066563929' +# expected: undef +not ok 34 +# Failed test in test.pl at line 64. +# got: '4294901760' +# expected: undef +not ok 35 +# Failed test in test.pl at line 65. +# got: '123.45.67.89/16' +# expected: undef +not ok 36 +# Failed test in test.pl at line 63. +# got: '2066563929' +# expected: undef +not ok 37 +# Failed test in test.pl at line 64. +# got: '4293918720' +# expected: undef +not ok 38 +# Failed test in test.pl at line 65. +# got: '123.45.67.89/12' +# expected: undef +not ok 39 +# Failed test in test.pl at line 63. +# got: '2066563929' +# expected: undef +not ok 40 +# Failed test in test.pl at line 64. +# got: '4278190080' +# expected: undef +not ok 41 +# Failed test in test.pl at line 65. +# got: '123.45.67.89/8' +# expected: undef +not ok 42 +# Failed test in test.pl at line 63. +# got: '2066563929' +# expected: undef +not ok 43 +# Failed test in test.pl at line 64. +# got: '4026531840' +# expected: undef +not ok 44 +# Failed test in test.pl at line 65. +# got: '123.45.67.89/4' +# expected: undef +not ok 45 +# Failed test in test.pl at line 63. +# got: '2066563929' +# expected: undef +not ok 46 +# Failed test in test.pl at line 64. +# got: '0' +# expected: undef +not ok 47 +# Failed test in test.pl at line 65. +# got: '123.45.67.89/0' +# expected: undef +not ok 48 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 49 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374607431768211455' +# expected: undef +not ok 50 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/128' +# expected: undef +not ok 51 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 52 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374607431768211440' +# expected: undef +not ok 53 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/124' +# expected: undef +not ok 54 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 55 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374607431768211200' +# expected: undef +not ok 56 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/120' +# expected: undef +not ok 57 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 58 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374607431768207360' +# expected: undef +not ok 59 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/116' +# expected: undef +not ok 60 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 61 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374607431768145920' +# expected: undef +not ok 62 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/112' +# expected: undef +not ok 63 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 64 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374607431767162880' +# expected: undef +not ok 65 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/108' +# expected: undef +not ok 66 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 67 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374607431751434240' +# expected: undef +not ok 68 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/104' +# expected: undef +not ok 69 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 70 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374607431499776000' +# expected: undef +not ok 71 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/100' +# expected: undef +not ok 72 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 73 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374607427473244160' +# expected: undef +not ok 74 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/96' +# expected: undef +not ok 75 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 76 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374607363048734720' +# expected: undef +not ok 77 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/92' +# expected: undef +not ok 78 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 79 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374606332256583680' +# expected: undef +not ok 80 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/88' +# expected: undef +not ok 81 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 82 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374589839582167040' +# expected: undef +not ok 83 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/84' +# expected: undef +not ok 84 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 85 +# Failed test in test.pl at line 64. +# got: '340282366920938463463374325956791500800' +# expected: undef +not ok 86 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/80' +# expected: undef +not ok 87 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 88 +# Failed test in test.pl at line 64. +# got: '340282366920938463463370103832140840960' +# expected: undef +not ok 89 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/76' +# expected: undef +not ok 90 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 91 +# Failed test in test.pl at line 64. +# got: '340282366920938463463302549837730283520' +# expected: undef +not ok 92 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/72' +# expected: undef +not ok 93 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 94 +# Failed test in test.pl at line 64. +# got: '340282366920938463462221685927161364480' +# expected: undef +not ok 95 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/68' +# expected: undef +not ok 96 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 97 +# Failed test in test.pl at line 64. +# got: '340282366920938463444927863358058659840' +# expected: undef +not ok 98 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/64' +# expected: undef +not ok 99 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 100 +# Failed test in test.pl at line 64. +# got: '340282366920938463168226702252415385600' +# expected: undef +not ok 101 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/60' +# expected: undef +not ok 102 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 103 +# Failed test in test.pl at line 64. +# got: '340282366920938458741008124562122997760' +# expected: undef +not ok 104 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/56' +# expected: undef +not ok 105 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 106 +# Failed test in test.pl at line 64. +# got: '340282366920938387905510881517444792320' +# expected: undef +not ok 107 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/52' +# expected: undef +not ok 108 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 109 +# Failed test in test.pl at line 64. +# got: '340282366920937254537554992802593505280' +# expected: undef +not ok 110 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/48' +# expected: undef +not ok 111 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 112 +# Failed test in test.pl at line 64. +# got: '340282366920919120650260773364972912640' +# expected: undef +not ok 113 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/44' +# expected: undef +not ok 114 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 115 +# Failed test in test.pl at line 64. +# got: '340282366920628978453553262363043430400' +# expected: undef +not ok 116 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/40' +# expected: undef +not ok 117 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 118 +# Failed test in test.pl at line 64. +# got: '340282366915986703306233086332171714560' +# expected: undef +not ok 119 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/36' +# expected: undef +not ok 120 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 121 +# Failed test in test.pl at line 64. +# got: '340282366841710300949110269838224261120' +# expected: undef +not ok 122 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/32' +# expected: undef +not ok 123 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 124 +# Failed test in test.pl at line 64. +# got: '340282365653287863235145205935065006080' +# expected: undef +not ok 125 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/28' +# expected: undef +not ok 126 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 127 +# Failed test in test.pl at line 64. +# got: '340282346638528859811704183484516925440' +# expected: undef +not ok 128 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/24' +# expected: undef +not ok 129 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 130 +# Failed test in test.pl at line 64. +# got: '340282042402384805036647824275747635200' +# expected: undef +not ok 131 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/20' +# expected: undef +not ok 132 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 133 +# Failed test in test.pl at line 64. +# got: '340277174624079928635746076935438991360' +# expected: undef +not ok 134 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/16' +# expected: undef +not ok 135 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 136 +# Failed test in test.pl at line 64. +# got: '340199290171201906221318119490500689920' +# expected: undef +not ok 137 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/12' +# expected: undef +not ok 138 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 139 +# Failed test in test.pl at line 64. +# got: '338953138925153547590470800371487866880' +# expected: undef +not ok 140 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/8' +# expected: undef +not ok 141 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 142 +# Failed test in test.pl at line 64. +# got: '319014718988379809496913694467282698240' +# expected: undef +not ok 143 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/4' +# expected: undef +not ok 144 +# Failed test in test.pl at line 63. +# got: '170145699920964442595609400891477785294' +# expected: undef +not ok 145 +# Failed test in test.pl at line 64. +# got: '0' +# expected: undef +not ok 146 +# Failed test in test.pl at line 65. +# got: '8000:DEAD:BEEF:4:CAFE:BAD:2:FACE/0' +# expected: undef + +|; + +my @exp; + +my @build = split("\n",$build); +foreach (@build) { + next unless $_ =~ /got:\s+'(.+)'/; + push @exp, $1; +} + +my $ptr = 0; +my $max = @exp; +plan tests => $max || 1; + +my $ip = new NetAddr::IP::Lite('255.255.255.253'); + +sub run { + foreach(1..5) { + my $mbi = $ip->bigint(); + $mbi++; + is($mbi, $exp[$ptr++]); + $ip = new NetAddr::IP::Lite($mbi); + is($ip, $exp[$ptr++]); + } +} + +run(); +$ip = new NetAddr::IP::Lite('FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFD'); +run(); + +sub mrun { + my ($jump) = @_; + my($mbia,$mbim) = $ip->bigint(); + +#print $ip,"\n"; +#print Dumper $mbia; +#print Dumper $mbim; + + $ip = new NetAddr::IP::Lite($mbia,$mbim); + + while(1) { + ($mbia,$mbim) = $ip->bigint(); + my($ary,$msk,$eip) = @exp[$ptr,$ptr+1,$ptr+2]; + $ptr += 3; + is($mbia, $ary); + is($mbim, $msk); + is($ip, $eip); + my $len = $ip->masklen(); + last unless $len; + last if $ptr > $max + 200; # loop stop, just in case + $mbim *= $jump; + $ip = new NetAddr::IP::Lite($mbia,$mbim); + } +} + +$ip = new NetAddr::IP::Lite('123.45.67.89'); +mrun(16); + +$ip = new NetAddr::IP::Lite('8000:dead:beef:4:cafe:bad:2:face'); + +mrun(16); diff --git a/Lite/t/bigints.t b/Lite/t/bigints.t deleted file mode 100644 index 186c872..0000000 --- a/Lite/t/bigints.t +++ /dev/null @@ -1,130 +0,0 @@ - -use strict; -use Test::More; - -use NetAddr::IP::Lite; -#use NetAddr::IP::Util qw( -# bcd2bin -# ipv6_n2x -# bin2bcd -#); -#use Data::Dumper; - -my @num = qw( - 2001:468:D01:3C:0:0:80DF:3C1B/128 42540577535367674011024906890208295963 - 73.150.6.197/32 1234568901 - 128.0.0.0/32 2147483648 - 0:0:0:0:0:1:0:0/128 4294967296 - 0:0:0:0:0:2:0:0/128 8589934592 - 0:0:0:0:0:2:540B:E400/128 10000000000 - 0:0:0:0:0:4:0:0/128 17179869184 - 0:0:0:0:0:8:0:0/128 34359738368 - 0:0:0:0:0:10:0:0/128 68719476736 - 0:0:0:0:0:20:0:0/128 137438953472 - 0:0:0:0:0:40:0:0/128 274877906944 - 0:0:0:0:0:80:0:0/128 549755813888 - 0:0:0:0:0:100:0:0/128 1099511627776 - 0:0:0:0:0:200:0:0/128 2199023255552 - 0:0:0:0:0:400:0:0/128 4398046511104 - 0:0:0:0:0:800:0:0/128 8796093022208 - 0:0:0:0:0:1000:0:0/128 17592186044416 - 0:0:0:0:0:2000:0:0/128 35184372088832 - 0:0:0:0:0:4000:0:0/128 70368744177664 - 0:0:0:0:0:8000:0:0/128 140737488355328 - 0:0:0:0:8000:0:0:0/128 9223372036854775808 - 0:0:0:8000:0:0:0:0/128 604462909807314587353088 - 0:0:8000:0:0:0:0:0/128 39614081257132168796771975168 - 0:8000:0:0:0:0:0:0/128 2596148429267413814265248164610048 - 8000:0:0:0:0:0:0:0/128 170141183460469231731687303715884105728 - 255.255.255.255/32 4294967295 - 1.2.3.4/32 16909060 - 10.253.230.9/32 184411657 -); - -plan tests => scalar @num; - -#diag ("\ntesting SCALARS\n\n"); - -for(my $i = 0;$i <= $#num;$i += 2) { - my $n = $num[$i +1]; - my $ip = new NetAddr::IP::Lite($n); - ok($ip eq $num[$i],"$n\t=> got: $ip\texp: ". $num[$i]); -} - -#diag ("\ntesting Math::BigInt's\n\n"); - -for(my $i = 0;$i <= $#num;$i += 2) { - my $n = new Math::BigInt($num[$i +1]); - my $ip = new NetAddr::IP::Lite($num[$i +1]); - ok($ip eq $num[$i],"$n\t=> got: $ip\texp: ". $num[$i]); -} - - - - -# simulate the use of Math::BigInt - -package Math::BigInt; -use strict; - -use overload -'""' => sub { $_[0]->_str(); }; - -sub BASE_LEN () { 7 }; - -sub _str { # adapted from Math::BigInt::Calc::_str - # (ref to BINT) return num_str - # Convert number from internal base 100000 format to string format. - # internal format is always normalized (no leading zeros, "-0" => "+0") - my $ar = $_[0]->{value}; - - my $l = scalar @$ar; # number of parts - my $ret = ""; - # handle first one different to strip leading zeros from it (there are no - # leading zero parts in internal representation) - $l --; $ret .= int($ar->[$l]); $l--; - # Interestingly, the pre-padd method uses more time - # the old grep variant takes longer (14 vs. 10 sec) - my $z = '0' x (BASE_LEN -1); - while ($l >= 0) - { - $ret .= substr($z.$ar->[$l],- BASE_LEN); # fastest way I could think of - $l--; - } - $ret; -} - -sub new { # adapted from Math::BigInt::new - my ($class,$wanted) = @_; - my $self = bless {}, $class; - - die "oops, not a good Math::BigInt number" - unless ((!ref $wanted) && ($wanted =~ /^([+-]?)[1-9][0-9]*\z/)); - $self->{sign} = $1 || '+'; - - if ($wanted =~ /^[+-]/) { -# remove sign without touching wanted to make it work with constants - my $t = $wanted; $t =~ s/^[+-]//; - $self->{value} = _new($t); - } - else { - $self->{value} = _new($wanted); - } - return $self; -} - -sub _new { # adapted from Math::BigInt::Calc::_new - my $wanted = $_[0]; - # (ref to string) return ref to num_array - # Convert a number from string format (without sign) to internal base - # 1ex format. Assumes normalized value as input. - my $il = length($wanted)-1; - - # < BASE_LEN due len-1 above - return [ int($wanted) ] if $il < BASE_LEN; # shortcut for short numbers - - my $base_len = BASE_LEN; - # this leaves '00000' instead of int 0 and will be corrected after any op - [ reverse(unpack("a" . ($il % BASE_LEN +1) - . ("a$base_len" x ($il / BASE_LEN)), $wanted)) ]; -} diff --git a/Lite/t/bignums.t b/Lite/t/bignums.t new file mode 100644 index 0000000..186c872 --- /dev/null +++ b/Lite/t/bignums.t @@ -0,0 +1,130 @@ + +use strict; +use Test::More; + +use NetAddr::IP::Lite; +#use NetAddr::IP::Util qw( +# bcd2bin +# ipv6_n2x +# bin2bcd +#); +#use Data::Dumper; + +my @num = qw( + 2001:468:D01:3C:0:0:80DF:3C1B/128 42540577535367674011024906890208295963 + 73.150.6.197/32 1234568901 + 128.0.0.0/32 2147483648 + 0:0:0:0:0:1:0:0/128 4294967296 + 0:0:0:0:0:2:0:0/128 8589934592 + 0:0:0:0:0:2:540B:E400/128 10000000000 + 0:0:0:0:0:4:0:0/128 17179869184 + 0:0:0:0:0:8:0:0/128 34359738368 + 0:0:0:0:0:10:0:0/128 68719476736 + 0:0:0:0:0:20:0:0/128 137438953472 + 0:0:0:0:0:40:0:0/128 274877906944 + 0:0:0:0:0:80:0:0/128 549755813888 + 0:0:0:0:0:100:0:0/128 1099511627776 + 0:0:0:0:0:200:0:0/128 2199023255552 + 0:0:0:0:0:400:0:0/128 4398046511104 + 0:0:0:0:0:800:0:0/128 8796093022208 + 0:0:0:0:0:1000:0:0/128 17592186044416 + 0:0:0:0:0:2000:0:0/128 35184372088832 + 0:0:0:0:0:4000:0:0/128 70368744177664 + 0:0:0:0:0:8000:0:0/128 140737488355328 + 0:0:0:0:8000:0:0:0/128 9223372036854775808 + 0:0:0:8000:0:0:0:0/128 604462909807314587353088 + 0:0:8000:0:0:0:0:0/128 39614081257132168796771975168 + 0:8000:0:0:0:0:0:0/128 2596148429267413814265248164610048 + 8000:0:0:0:0:0:0:0/128 170141183460469231731687303715884105728 + 255.255.255.255/32 4294967295 + 1.2.3.4/32 16909060 + 10.253.230.9/32 184411657 +); + +plan tests => scalar @num; + +#diag ("\ntesting SCALARS\n\n"); + +for(my $i = 0;$i <= $#num;$i += 2) { + my $n = $num[$i +1]; + my $ip = new NetAddr::IP::Lite($n); + ok($ip eq $num[$i],"$n\t=> got: $ip\texp: ". $num[$i]); +} + +#diag ("\ntesting Math::BigInt's\n\n"); + +for(my $i = 0;$i <= $#num;$i += 2) { + my $n = new Math::BigInt($num[$i +1]); + my $ip = new NetAddr::IP::Lite($num[$i +1]); + ok($ip eq $num[$i],"$n\t=> got: $ip\texp: ". $num[$i]); +} + + + + +# simulate the use of Math::BigInt + +package Math::BigInt; +use strict; + +use overload +'""' => sub { $_[0]->_str(); }; + +sub BASE_LEN () { 7 }; + +sub _str { # adapted from Math::BigInt::Calc::_str + # (ref to BINT) return num_str + # Convert number from internal base 100000 format to string format. + # internal format is always normalized (no leading zeros, "-0" => "+0") + my $ar = $_[0]->{value}; + + my $l = scalar @$ar; # number of parts + my $ret = ""; + # handle first one different to strip leading zeros from it (there are no + # leading zero parts in internal representation) + $l --; $ret .= int($ar->[$l]); $l--; + # Interestingly, the pre-padd method uses more time + # the old grep variant takes longer (14 vs. 10 sec) + my $z = '0' x (BASE_LEN -1); + while ($l >= 0) + { + $ret .= substr($z.$ar->[$l],- BASE_LEN); # fastest way I could think of + $l--; + } + $ret; +} + +sub new { # adapted from Math::BigInt::new + my ($class,$wanted) = @_; + my $self = bless {}, $class; + + die "oops, not a good Math::BigInt number" + unless ((!ref $wanted) && ($wanted =~ /^([+-]?)[1-9][0-9]*\z/)); + $self->{sign} = $1 || '+'; + + if ($wanted =~ /^[+-]/) { +# remove sign without touching wanted to make it work with constants + my $t = $wanted; $t =~ s/^[+-]//; + $self->{value} = _new($t); + } + else { + $self->{value} = _new($wanted); + } + return $self; +} + +sub _new { # adapted from Math::BigInt::Calc::_new + my $wanted = $_[0]; + # (ref to string) return ref to num_array + # Convert a number from string format (without sign) to internal base + # 1ex format. Assumes normalized value as input. + my $il = length($wanted)-1; + + # < BASE_LEN due len-1 above + return [ int($wanted) ] if $il < BASE_LEN; # shortcut for short numbers + + my $base_len = BASE_LEN; + # this leaves '00000' instead of int 0 and will be corrected after any op + [ reverse(unpack("a" . ($il % BASE_LEN +1) + . ("a$base_len" x ($il / BASE_LEN)), $wanted)) ]; +} diff --git a/Lite/t/v4_new_cis.t b/Lite/t/v4_new_cis.t index 4c26258..f9c3788 100644 --- a/Lite/t/v4_new_cis.t +++ b/Lite/t/v4_new_cis.t @@ -43,12 +43,12 @@ plan tests => (4 * scalar @a * scalar @m) + 4; -foreach my $invalid qw( +foreach my $invalid (qw( 256.1.1.1 256.256.1.1 256.256.256.1 256.256.256.256 -) { +)) { ok (! defined NetAddr::IP::Lite->new($invalid), "Invalid IP $invalid returns undef"); } diff --git a/MANIFEST b/MANIFEST index 5f00bb4..7bf4439 100644 --- a/MANIFEST +++ b/MANIFEST @@ -47,7 +47,8 @@ Lite/bug2742981 Lite/t/addr.t Lite/t/aton.t -Lite/t/bigints.t +Lite/t/bigint.t +Lite/t/bignums.t Lite/t/bin_ips.t Lite/t/bits.t Lite/t/broadcast.t diff --git a/META.yml b/META.yml index b1fd991..fc1965d 100644 --- a/META.yml +++ b/META.yml @@ -1,6 +1,6 @@ --- #YAML:1.0 name: NetAddr-IP -version: 4.049 +version: 4.050 abstract: Manages IPv4 and IPv6 addresses and subnets license: ~ author: