Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | package BigIntSupport; |
2 | ||
3 | require 5.005_62; | |
4 | use strict; | |
5 | use warnings; | |
6 | ||
7 | require Exporter; | |
8 | use Math::BigInt; | |
9 | use Carp; | |
10 | ||
11 | our @ISA = qw(Exporter); | |
12 | ||
13 | # Items to export into callers namespace by default. Note: do not export | |
14 | # names by default without a very good reason. Use EXPORT_OK instead. | |
15 | # Do not simply export all your public functions/methods/constants. | |
16 | ||
17 | # This allows declaration use BigIntSupport ':all'; | |
18 | # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK | |
19 | # will save memory. | |
20 | our %EXPORT_TAGS = ( 'all' => [ qw( | |
21 | ||
22 | ) ] ); | |
23 | ||
24 | our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); | |
25 | ||
26 | our @EXPORT = qw( | |
27 | hex2bigint | |
28 | bigint2hex | |
29 | bigint_sprintf | |
30 | ); | |
31 | our $VERSION = '0.01'; | |
32 | ||
33 | ||
34 | # Preloaded methods go here. | |
35 | ||
36 | sub hex2bigint { | |
37 | my $hexstring = shift; | |
38 | $hexstring = 0 unless defined $hexstring; | |
39 | $hexstring =~ s/^\s+//; | |
40 | $hexstring =~ s/\s+$//; | |
41 | $hexstring =~ s/^0[xX]//; | |
42 | ||
43 | my $bignum = Math::BigInt->new(0); | |
44 | my $shift = 0; | |
45 | ||
46 | while(length $hexstring) { | |
47 | my $tail = substr $hexstring, -8, 8, ""; | |
48 | my $tailval = hex($tail); | |
49 | $bignum += Math::BigInt->new($tailval) << $shift; | |
50 | $shift += 32; | |
51 | } | |
52 | ||
53 | return $bignum; | |
54 | } | |
55 | ||
56 | ||
57 | sub bigint2hex { | |
58 | my $bignum = shift; | |
59 | ||
60 | if(not ref $bignum) { | |
61 | return sprintf("%x", $bignum); | |
62 | } | |
63 | ||
64 | my $string = ""; | |
65 | ||
66 | while($bignum) { | |
67 | my $low = $bignum & 0xffffffff; | |
68 | $string = sprintf("%08x", $low) . $string; | |
69 | $bignum >>= 32; | |
70 | } | |
71 | $string =~ s/^0+//; | |
72 | ||
73 | $string = '0' if $string eq ''; | |
74 | ||
75 | return $string; | |
76 | } | |
77 | ||
78 | ||
79 | sub bigint_sprintf { | |
80 | my $bigint = shift; | |
81 | my $format = shift; | |
82 | ||
83 | if($format =~ /^\s*\%?(0)?(\d+)?[lL]*([xd])\s*/) { | |
84 | my ($lead, $width, $base) = ($1, $2, $3); | |
85 | ||
86 | $width = 0 unless defined $width; | |
87 | $base = '' unless defined $base; | |
88 | ||
89 | my $string; | |
90 | ||
91 | ||
92 | if($base eq 'd') { | |
93 | $string = "$bigint"; | |
94 | $string =~ s/^\+//; | |
95 | } else { | |
96 | $string = bigint2hex($bigint); | |
97 | } | |
98 | ||
99 | my $strlen = length($string); | |
100 | if($width > $strlen) { | |
101 | my $diff = $width - $strlen; | |
102 | my $char = defined($lead)? '0' : ' '; | |
103 | my $leading = $char x $diff; | |
104 | $string = "$leading$string"; | |
105 | } | |
106 | return $string; | |
107 | } else { | |
108 | croak "Bad format string: $format"; | |
109 | } | |
110 | } | |
111 | ||
112 | ||
113 | 1; | |
114 | __END__ | |
115 | # Below is stub documentation for your module. You better edit it! | |
116 | ||
117 | =head1 NAME | |
118 | ||
119 | BigIntSupport - Perl extension for interfacing between Math::BigInt values and text strings. | |
120 | ||
121 | =head1 SYNOPSIS | |
122 | ||
123 | use BigIntSupport; | |
124 | use Math::BigInt; | |
125 | ||
126 | # Create Math::BigInt from an arbitrary-sized hex number | |
127 | my $bigint1 = hex2bigint("0xdeadbeefcafebabe01234567"); | |
128 | my $bigint2 = hex2bigint("0xffffffff"); | |
129 | # Do math | |
130 | $bigint2 <<= 32; | |
131 | $bigint1 &= $bigint2; | |
132 | # Get hex string back | |
133 | my $string = bigint2hex($bigint1); | |
134 | # Print it | |
135 | print "Result is 0x$string\n"; | |
136 | ||
137 | ||
138 | =head1 DESCRIPTION | |
139 | ||
140 | This provides some interface functions for the Math::BigInt library, | |
141 | which is part of the perl standard libary. Basically, Math::BigInt is | |
142 | a module for arbitrary-sized integers. It overloads all the standard | |
143 | math operators for use with Math::BigInt objects, but it does not | |
144 | overload either the hex() function or sprintf "%x", so it is difficult | |
145 | to use Math::BigInt objects for large hex numbers. This module is a | |
146 | solution to that problem. | |
147 | ||
148 | =head2 EXPORT | |
149 | ||
150 | The following functions are exported: | |
151 | ||
152 | =over 4 | |
153 | ||
154 | =item hex2bigint($hex_string) | |
155 | ||
156 | Interprets $hex_string as a hex number (whether or not a leading 0x is | |
157 | present). Returns a Math::BigInt object representing the number. To | |
158 | convert decimal numbers to Math::BigInt objects, use | |
159 | Math::BigInt->new($decimal_string). | |
160 | ||
161 | =item bigint2hex($bigint) | |
162 | ||
163 | Formats the given Math::BigInt object as a hexidecimal string and | |
164 | returns it. The string has no leading zeros or 0x. | |
165 | ||
166 | =item bigint_sprintf($bigint, $format) | |
167 | ||
168 | Takes a Math::BigInt and a printf-style format string and returns a | |
169 | string with the appropriately-formatted string. The format string can | |
170 | contain only %x or %d, and may optionally include a width | |
171 | specification, which may include a leading zero. In other words, | |
172 | "%016x" is legal but "The answer is %d" is not. A leading "%" is | |
173 | optional. | |
174 | ||
175 | =back | |
176 | ||
177 | ||
178 | =head1 AUTHOR | |
179 | ||
180 | Jeff Gibson, jgibson@afara.com | |
181 | ||
182 | =head1 SEE ALSO | |
183 | ||
184 | Math::BigInt(3), perl(1). | |
185 | ||
186 | =cut |