Newer
Older
NetAddr-IP / Lite / t / bigints.t
@Michael Robinton Michael Robinton on 21 Oct 2014 3 KB Import of MIKER/NetAddr-IP-4.020 from CPAN.

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)) ];
}