File Coverage

blib/lib/Acme/Bleach/Numerically.pm
Criterion Covered Total %
statement 54 69 78.2
branch 7 16 43.7
condition n/a
subroutine 11 11 100.0
pod 0 2 0.0
total 72 98 73.4


line stmt bran cond sub pod time code
1             package Acme::Bleach::Numerically;
2              
3 2     2   1626 use 5.008001;
  2         6  
  2         77  
4 2     2   11 use strict;
  2         3  
  2         63  
5 2     2   20 use warnings;
  2         4  
  2         210  
6             our $VERSION = sprintf "%d.%02d", q$Revision: 0.4 $ =~ /(\d+)/g;
7             our $MAX_SIZE = 0x7fff_ffff;
8 2     2   3435 use Math::BigInt lib => 'GMP'; # faster if there, fallbacks if not
  2         44445  
  2         15  
9 2     2   39959 use Math::BigFloat;
  2         44893  
  2         18  
10 2     2   4019 use Math::BigRat;
  2         24967  
  2         32  
11              
12             sub str2num{
13 26     26 0 18089 my $str = shift;
14 26 100       97 return 0 if $str eq '';
15 22         147 Math::BigFloat->accuracy(length($str) * 8);
16 22         508 my $bnum = Math::BigFloat->new(0);
17 22         2827 my $bden = Math::BigInt->new(256);
18 22         711 $bden **= length($str);
19 22         33716 for my $ord (unpack "C*", $str){
20 1485         1172191 $bnum = $bnum * 256 + $ord;
21             }
22 22         13948 $bnum /= $bden;
23 22         356874 $bnum =~ s/0+$//o;
24 22         5544 return $bnum;
25             }
26              
27             sub num2str{
28 26     26 0 72 my $num = shift;
29 26 100       120 return '' unless $num;
30 22         604 my $bnum = Math::BigFloat->new($num);
31 22         2874 my $str = '';
32 22         105 while($bnum > 0){
33 1485         1705583 $bnum *= 256;
34 1485         1924979 my $ord = int $bnum->copy;
35 1485         266324 $str .= chr $ord;
36 1485         45934 $bnum -= $ord;
37             }
38 22         11134 return $str;
39             }
40              
41             sub import{
42 2     2   459 my $class = shift;
43 2 50       13 if (@_){ # behave nicely
44 2         7 my ($pkg, $filename, $line) = caller;
45 2         5 for my $arg (@_){
46 2     2   8737 no strict 'refs';
  2         4  
  2         474  
47 5 100       9 next unless defined &{ "$arg" };
  5         28  
48 4         6 *{ $pkg . "::$arg" } = \&{ "$arg" };
  4         22  
  4         9  
49             }
50             }else{ # bleach!
51 0 0         open my $in, "<:raw", $0 or die "$0 : $!";
52 0           my $src = join '', grep !/use\s*Acme::Bleach::Numerically/, <$in>;
53 0           close $in;
54             # warn $src;
55 0 0         if ($src =~ /^0\.[0-9]+;?\s*$/){ # bleached
56 0           my $code = num2str($src);
57 0           eval $code;
58             }else{ # whiten
59             {
60 2     2   11 no warnings;
  2         4  
  2         386  
  0            
61 0           eval $src;
62 0 0         if ($@){ # dirty
63 0           $@ =~ s/\(eval \d+\)/$0/eg;
  0            
64 0           die $@;
65             }
66             }
67 0 0         open my $out, ">:raw", $0 or die "$0 : $!";
68 0           print $out
69             "use ", __PACKAGE__, ";\n",
70             str2num($src), "\n";
71             }
72 0           exit;
73             }
74             }
75             1;
76             __END__