Use Math::BigInt for describe_bytestring address display
Peter Rabbitson [Thu, 2 Feb 2012 17:45:25 +0000 (18:45 +0100)]
Changes
Makefile.PL
lib/Devel/PeekPoke.pm
lib/Devel/PeekPoke/BigInt.pm [new file with mode: 0644]
t/02describe_bytestring.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index 957e641..60cbcf8 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,3 +1,5 @@
+    - Fix describe_bytestring to work correctly with large offsets on
+      32bit machines
 
 0.01  2011-08-31 11:10 (UTC)
 
index abe6bf4..9592707 100644 (file)
@@ -13,7 +13,7 @@ if ($use_pp and ($] =~ /^5.(\d{3})/)[0] % 2) {
   die "Instalation will need Devel::PeekPoke::PP, which does not work (by design) on development perls ($])\n";
 }
 
-# the XS version should work fine on 5.6
+# the XS version (when written) should work fine on 5.6
 perl_version $use_pp ? '5.008001' : '5.006';
 
 test_requires 'Test::More'      => '0.88';  # done testing
index 24bfc41..cb034fc 100644 (file)
@@ -191,12 +191,14 @@ for (values %$ctrl_names) {
 
 sub describe_bytestring {
   my ($bytes, $start_addr) = @_;
-  $start_addr ||= 0;
+
+  require Devel::PeekPoke::BigInt;
+  $start_addr = Devel::PeekPoke::BigInt->new($start_addr || 0);
 
   my $len = length($bytes);
 
-  my $max_addr_hexsize = length (sprintf ('%x', $start_addr + $len));
-  $max_addr_hexsize = 7 if $max_addr_hexsize < 7; # to match perl itself
+  my $max_addr_hexsize = length ( ($start_addr + $len)->as_unmarked_hex );
+  $max_addr_hexsize = 7 if $max_addr_hexsize < 7; # to match perl itself (minimum 7 digits)
   my $addr_hdr_pad = ' ' x ($max_addr_hexsize + 3);
 
   my @out = (
@@ -222,8 +224,8 @@ sub describe_bytestring {
   for my $off (0 .. $len - 1) {
     my $byte = substr $bytes, $off, 1;
     my ($val) = unpack ('C', $byte);
-    push @out, sprintf( "0x%0${max_addr_hexsize}x   %02X % 4d % 4o  %s  %s",
-      $start_addr + $off,
+    push @out, sprintf( "0x%0${max_addr_hexsize}s   %02X % 4d % 4o  %s  %s",
+      ($start_addr + $off)->as_unmarked_hex,
       ($val) x 3,
       unpack('B8', $byte),
       $ctrl_names->{$val} || ( $val > 127 ? sprintf('"\%o"', $val) : "  $byte   " ),
@@ -261,7 +263,8 @@ sub describe_bytestring {
       if @ints;
   }
 
-  join "\n", @out;
+  s/\s+$// for @out;
+  join "\n", @out, '';
 }
 
 =head1 AUTHOR
diff --git a/lib/Devel/PeekPoke/BigInt.pm b/lib/Devel/PeekPoke/BigInt.pm
new file mode 100644 (file)
index 0000000..a338e9c
--- /dev/null
@@ -0,0 +1,11 @@
+package # hide from PAUSE
+  Devel::PeekPoke::BigInt;
+
+use strict;
+use warnings;
+
+use base 'Math::BigInt';
+
+sub as_unmarked_hex { substr ( shift->as_hex, 2 ) }
+
+1;
diff --git a/t/02describe_bytestring.t b/t/02describe_bytestring.t
new file mode 100644 (file)
index 0000000..99c3561
--- /dev/null
@@ -0,0 +1,62 @@
+use strict;
+use warnings;
+
+use Test::More;
+
+use Devel::PeekPoke qw/describe_bytestring/;
+use Devel::PeekPoke::Constants qw/BIG_ENDIAN/;
+
+my $out = BIG_ENDIAN
+  ? <<'EOD'
+             Hex  Dec  Oct    Bin     ASCII      32      32+2          64
+            --------------------------------  -------- -------- ----------------
+0xadeadbeef   48   72  110  01001000    H     48617220          4861722068617209
+0xadeadbef0   61   97  141  01100001    a     ___/              _______/
+0xadeadbef1   72  114  162  01110010    r     __/      72206861 ______/
+0xadeadbef2   20   32   40  00100000  (SP)    _/       ___/     _____/
+0xadeadbef3   68  104  150  01101000    h     68617209 __/      ____/
+0xadeadbef4   61   97  141  01100001    a     ___/     _/       ___/
+0xadeadbef5   72  114  162  01110010    r     __/      72091337 __/
+0xadeadbef6   09    9   11  00001001  (HT)    _/       ___/     _/
+0xadeadbef7   13   19   23  00010011  (DC3)   1337B00B __/      1337B00B1E552021
+0xadeadbef8   37   55   67  00110111    7     ___/     _/       _______/
+0xadeadbef9   B0  176  260  10110000  "\260"  __/      B00B1E55 ______/
+0xadeadbefa   0B   11   13  00001011  (VT)    _/       ___/     _____/
+0xadeadbefb   1E   30   36  00011110  (RS)    1E552021 __/      ____/
+0xadeadbefc   55   85  125  01010101    U     ___/     _/       ___/
+0xadeadbefd   20   32   40  00100000  (SP)    __/      20212121 __/
+0xadeadbefe   21   33   41  00100001    !     _/       ___/     _/
+0xadeadbeff   21   33   41  00100001    !              __/
+0xadeadbf00   21   33   41  00100001    !              _/
+EOD
+  : <<'EOD'
+             Hex  Dec  Oct    Bin     ASCII      32      32+2          64
+            --------------------------------  -------- -------- ----------------
+0xadeadbeef   48   72  110  01001000    H     20726148          0972616820726148
+0xadeadbef0   61   97  141  01100001    a     ___/              _______/
+0xadeadbef1   72  114  162  01110010    r     __/      61682072 ______/
+0xadeadbef2   20   32   40  00100000  (SP)    _/       ___/     _____/
+0xadeadbef3   68  104  150  01101000    h     09726168 __/      ____/
+0xadeadbef4   61   97  141  01100001    a     ___/     _/       ___/
+0xadeadbef5   72  114  162  01110010    r     __/      37130972 __/
+0xadeadbef6   09    9   11  00001001  (HT)    _/       ___/     _/
+0xadeadbef7   13   19   23  00010011  (DC3)   0BB03713 __/      2120551E0BB03713
+0xadeadbef8   37   55   67  00110111    7     ___/     _/       _______/
+0xadeadbef9   B0  176  260  10110000  "\260"  __/      551E0BB0 ______/
+0xadeadbefa   0B   11   13  00001011  (VT)    _/       ___/     _____/
+0xadeadbefb   1E   30   36  00011110  (RS)    2120551E __/      ____/
+0xadeadbefc   55   85  125  01010101    U     ___/     _/       ___/
+0xadeadbefd   20   32   40  00100000  (SP)    __/      21212120 __/
+0xadeadbefe   21   33   41  00100001    !     _/       ___/     _/
+0xadeadbeff   21   33   41  00100001    !              __/
+0xadeadbf00   21   33   41  00100001    !              _/
+EOD
+;
+
+is(
+  describe_bytestring( "Har har\t\x13\x37\xb0\x0b\x1e\x55 !!!", 46685601519 ),
+  $out,
+  'describe_bytestring works as expected'
+);
+
+done_testing;