--- /dev/null
+package NB::Encoding::FixLatin;
+
+use warnings;
+use strict;
+
+require 5.008;
+
+our $VERSION = '1.02';
+
+use Carp qw(croak);
+use Exporter qw(import);
+use Encode qw(is_utf8 encode_utf8);
+
+our @EXPORT_OK = qw(fix_latin);
+
+
+my $byte_map;
+
+my $ascii_str = qr{\A([\x00-\x7F]+)(.*)\z}s;
+
+my $cont_byte = '[\x80-\xBF]';
+my $utf8_2 = qr{\A([\xC0-\xDF])($cont_byte)(.*)\z}s;
+my $utf8_3 = qr{\A([\xE0-\xEF])($cont_byte)($cont_byte)(.*)\z}s;
+my $utf8_4 = qr{\A([\xF0-\xF7])($cont_byte)($cont_byte)($cont_byte)(.*)\z}s;
+my $utf8_5 = qr{\A([\xF8-\xFB])($cont_byte)($cont_byte)($cont_byte)($cont_byte)(.*)\z}s;
+
+my %known_opt = map { $_ => 1 } qw(bytes_only ascii_hex overlong_fatal);
+
+my %non_1252 = (
+ "\x81" => '%81',
+ "\x8D" => '%8D',
+ "\x8F" => '%8F',
+ "\x90" => '%90',
+ "\x9D" => '%9D',
+);
+
+sub fix_latin {
+ my $input = shift;
+ my %opt = (
+ ascii_hex => 1,
+ bytes_only => 0,
+ overlong_fatal => 0,
+ @_
+ );
+
+ foreach (keys %opt) {
+ croak "Unknown option '$_'" unless $known_opt{$_};
+ }
+
+ return unless defined($input);
+ _init_byte_map(\%opt) unless $byte_map;
+
+ if(is_utf8($input)) { # input string already has utf8 flag set
+ if($opt{bytes_only}) {
+ return encode_utf8($input);
+ }
+ else {
+ return $input;
+ }
+ }
+
+ my $output = '';
+ my $char = '';
+ my $rest = '';
+ my $olf = $opt{overlong_fatal};
+ while(length($input) > 0) {
+ if($input =~ $ascii_str) {
+ $output .= $1;
+ $rest = $2;
+ }
+ elsif($input =~ $utf8_2) {
+ $output .= _decode_utf8($olf, ord($1) & 0x1F, $1, $2);
+ $rest = $3;
+ }
+ elsif($input =~ $utf8_3) {
+ $output .= _decode_utf8($olf, ord($1) & 0x0F, $1, $2, $3);
+ $rest = $4;
+ }
+ elsif($input =~ $utf8_4) {
+ $output .= _decode_utf8($olf, ord($1) & 0x07, $1, $2, $3, $4);
+ $rest = $5;
+ }
+ elsif($input =~ $utf8_5) {
+ $output .= _decode_utf8($olf, ord($1) & 0x03, $1, $2, $3, $4, $5);
+ $rest = $6;
+ }
+ else {
+ ($char, $rest) = $input =~ /^(.)(.*)$/s;
+ if($opt{ascii_hex} && exists $non_1252{$char}) {
+ $output .= $non_1252{$char};
+ }
+ else {
+ $output .= $byte_map->{$char};
+ }
+ }
+ $input = $rest;
+ }
+ utf8::decode($output) unless $opt{bytes_only};
+ return $output;
+}
+
+
+sub _decode_utf8 {
+ my $overlong_fatal = shift;
+ my $c = shift;
+ my $byte_count = @_;
+ foreach my $i (1..$#_) {
+ $c = ($c << 6) + (ord($_[$i]) & 0x3F);
+ }
+ my $bytes = encode_utf8(chr($c));
+ if($overlong_fatal and $byte_count > length($bytes)) {
+ my $hex_bytes= join ' ', map { sprintf('%02X', ord($_)) } @_;
+ croak "Over-long UTF-8 byte sequence: $hex_bytes";
+ }
+ return $bytes;
+}
+
+
+sub _init_byte_map {
+ foreach my $i (0x80..0xFF) {
+ my $utf_char = chr($i);
+ utf8::encode($utf_char);
+ $byte_map->{pack('C', $i)} = $utf_char;
+ }
+ _add_cp1252_mappings();
+}
+
+
+sub _add_cp1252_mappings {
+ # From http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT
+ my %ms_map = (
+ "\x80" => "\xE2\x82\xAC", # EURO SIGN
+ "\x82" => "\xE2\x80\x9A", # SINGLE LOW-9 QUOTATION MARK
+ "\x83" => "\xC6\x92", # LATIN SMALL LETTER F WITH HOOK
+ "\x84" => "\xE2\x80\x9E", # DOUBLE LOW-9 QUOTATION MARK
+ "\x85" => "\xE2\x80\xA6", # HORIZONTAL ELLIPSIS
+ "\x86" => "\xE2\x80\xA0", # DAGGER
+ "\x87" => "\xE2\x80\xA1", # DOUBLE DAGGER
+ "\x88" => "\xCB\x86", # MODIFIER LETTER CIRCUMFLEX ACCENT
+ "\x89" => "\xE2\x80\xB0", # PER MILLE SIGN
+ "\x8A" => "\xC5\xA0", # LATIN CAPITAL LETTER S WITH CARON
+ "\x8B" => "\xE2\x80\xB9", # SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+ "\x8C" => "\xC5\x92", # LATIN CAPITAL LIGATURE OE
+ "\x8E" => "\xC5\xBD", # LATIN CAPITAL LETTER Z WITH CARON
+ "\x91" => "\xE2\x80\x98", # LEFT SINGLE QUOTATION MARK
+ "\x92" => "\xE2\x80\x99", # RIGHT SINGLE QUOTATION MARK
+ "\x93" => "\xE2\x80\x9C", # LEFT DOUBLE QUOTATION MARK
+ "\x94" => "\xE2\x80\x9D", # RIGHT DOUBLE QUOTATION MARK
+ "\x95" => "\xE2\x80\xA2", # BULLET
+ "\x96" => "\xE2\x80\x93", # EN DASH
+ "\x97" => "\xE2\x80\x94", # EM DASH
+ "\x98" => "\xCB\x9C", # SMALL TILDE
+ "\x99" => "\xE2\x84\xA2", # TRADE MARK SIGN
+ "\x9A" => "\xC5\xA1", # LATIN SMALL LETTER S WITH CARON
+ "\x9B" => "\xE2\x80\xBA", # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+ "\x9C" => "\xC5\x93", # LATIN SMALL LIGATURE OE
+ "\x9E" => "\xC5\xBE", # LATIN SMALL LETTER Z WITH CARON
+ "\x9F" => "\xC5\xB8", # LATIN CAPITAL LETTER Y WITH DIAERESIS
+ );
+ while(my($k, $v) = each %ms_map) {
+ $byte_map->{$k} = $v;
+ }
+}
+
+
+1;
+
+__END__
+
+=head1 NAME
+
+Encoding::FixLatin - takes mixed encoding input and produces UTF-8 output
+
+
+=head1 SYNOPSIS
+
+ use NB::Encoding::FixLatin qw(fix_latin);
+
+ my $utf8_string = fix_latin($mixed_encoding_string);
+
+
+=head1 DESCRIPTION
+
+Most encoding conversion tools take input in one encoding and produce output in
+another encoding. This module takes input which may contain characters in more
+than one encoding and makes a best effort to convert them all to UTF-8 output.
+
+
+=head1 EXPORTS
+
+Nothing is exported by default. The only public function is C<fix_latin> which
+will be exported on request (as per SYNOPSIS).
+
+
+=head1 FUNCTIONS
+
+=head2 fix_latin( string, options ... )
+
+Decodes the supplied 'string' and returns a UTF-8 version of the string. The
+following rules are used:
+
+=over 4
+
+=item *
+
+ASCII characters (single bytes in the range 0x00 - 0x7F) are passed through
+unchanged.
+
+=item *
+
+Well-formed UTF-8 multi-byte characters are also passed through unchanged.
+
+=item *
+
+UTF-8 multi-byte character which are over-long but otherwise well-formed are
+converted to the shortest UTF-8 normal form.
+
+=item *
+
+Bytes in the range 0xA0 - 0xFF are assumed to be Latin-1 characters (ISO8859-1
+encoded) and are converted to UTF-8.
+
+=item *
+
+Bytes in the range 0x80 - 0x9F are assumed to be Win-Latin-1 characters (CP1252
+encoded) and are converted to UTF-8. Except for the five bytes in this range
+which are not defined in CP1252 (see the C<ascii_hex> option below).
+
+=back
+
+The achilles heel of these rules is that it's possible for certain combinations
+of two consecutive Latin-1 characters to be misinterpreted as a single UTF-8
+character - ie: there is some risk of data corruption. See the 'LIMITATIONS'
+section below to quantify this risk for the type of data you're working with.
+
+If you pass in a string that is already a UTF-8 character string (the utf8 flag
+is set on the Perl scalar) then the string will simply be returned unchanged.
+However if the 'bytes_only' option is specified (see below), the returned
+string will be a byte string rather than a character string. The rules
+described above will not be applied in either case.
+
+The C<fix_latin> function accepts options as name => value pairs. Recognised
+options are:
+
+=over 4
+
+=item bytes_only => 1/0
+
+The value returned by fix_latin is normally a Perl character string and will
+have the utf8 flag set if it contains non-ASCII characters. If you set the
+C<bytes_only> option to a true value, the returned string will be a binary
+string of UTF-8 bytes. The utf8 flag will not be set. This is useful if
+you're going to immediately use the string in an IO operation and wish to avoid
+the overhead of converting to and from Perl's internal representation.
+
+=item ascii_hex => 1/0
+
+Bytes in the range 0x80-0x9F are assumed to be CP1252, however CP1252 does not
+define a mapping for 5 of these bytes (0x81, 0x8D, 0x8F, 0x90 and 0x9D). Use
+this option to specify how they should be handled:
+
+=over 4
+
+=item *
+
+If the ascii_hex option is set to true (the default), these bytes will be
+converted to 3 character ASCII hex strings of the form %XX. For example the
+byte 0x81 will become %81.
+
+=item *
+
+If the ascii_hex option is set to false, these bytes will be treated as Latin-1
+control characters and converted to the equivalent UTF-8 multi-byte sequences.
+
+=back
+
+When processing text strings you will almost certainly never encounter these
+bytes at all. The most likely reason you would see them is if a malicious
+attacker was feeding random bytes to your application. It is difficult to
+conceive of a scenario in which it makes sense to change this option from its
+default setting.
+
+=item overlong_fatal => 1/0
+
+An over-long UTF-8 byte sequence is one which uses more than the minimum number
+of bytes required to represent the character. Use this option to specify how
+overlong sequences should be handled.
+
+=over 4
+
+=item *
+
+If the overlong_fatal option is set to false (the default) over-long sequences
+will be converted to the shortest normal UTF-8 sequence. For example the input
+byte string "\xC0\xBCscript>" would be converted to "<script>".
+
+=item *
+
+If the overlong_fatal option is set to true, this module will die with an
+error when an overlong sequence is encountered. You would probably want to
+use eval to trap and handle this scenario.
+
+=back
+
+There is a strong argument that overlong sequences are only ever encountered
+in malicious input and therefore they should always be rejected.
+
+=back
+
+=head1 LIMITATIONS OF THIS MODULE
+
+This module is perfectly safe when handling data containing only ASCII and
+UTF-8 characters. Introducing ISO8859-1 or CP1252 characters does add a risk
+of data corruption (ie: some characters in the input being converted to
+incorrect characters in the output). To quantify the risk it is necessary to
+understand it's cause. First, let's break the input bytes into two categories.
+
+=over 4
+
+=item *
+
+ASCII bytes fall into the range 0x00-0x7F - the most significant bit is always
+set to zero. I'll use the symbol 'a' to represent these bytes.
+
+=item *
+
+Non-ASCII bytes fall into the range 0x80-0xFF - the most significant bit is
+always set to one. I'll use the symbol 'B' to represent these bytes.
+
+=back
+
+A sequence of ASCII bytes ('aaa') is always unambiguous and will not be
+misinterpreted.
+
+Lone non-ASCII bytes within sequences of ASCII bytes ('aaBaBa') are also
+unambiguous and will not be misinterpreted.
+
+The potential for error occurs with two (or more) consecutive non-ASCII bytes.
+For example the sequence 'BB' might be intended to represent two characters in
+one of the legacy encodings or a single character in UTF-8. Because this
+module gives precedence to the UTF-8 characters it is possible that a random
+pair of legacy characters may be misinterpreted as a single UTF-8 character.
+
+The risk is reduced by the fact that not all pairs of non-ASCII bytes form
+valid UTF-8 sequences. Every non-ASCII UTF-8 character is made up of two or
+more 'B' bytes and no 'a' bytes. For a two-byte character, the first byte must
+be in the range 0xC0-0xDF and the second must be in the range 0x80-0xBF.
+
+Any pair of 'BB' bytes that do not fall into the required ranges are
+unambiguous and will not be misinterpreted.
+
+Pairs of 'BB' bytes that are actually individual Latin-1 characters but
+happen to fall into the required ranges to be misinterpreted as a UTF-8
+character are rather unlikely to appear in normal text. If you look those
+ranges up on a Latin-1 code chart you'll see that the first character would
+need to be an uppercase accented letter and the second would need to be a
+non-printable control character or a special punctuation symbol.
+
+One way to summarise the role of this module is that it guarantees to
+produce UTF-8 output, possibly at the cost of introducing the odd 'typo'.
+
+
+=head1 BUGS
+
+Please report any bugs to C<bug-encoding-fixlatin at rt.cpan.org>, or through
+the web interface at
+L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Encoding-FixLatin>. I will be
+notified, and then you'll automatically be notified of progress on your bug as
+I make changes.
+
+
+=head1 SUPPORT
+
+You can also look for information at:
+
+=over 4
+
+=item * RT: CPAN's request tracker
+
+L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Encoding-FixLatin>
+
+=item * AnnoCPAN: Annotated CPAN documentation
+
+L<http://annocpan.org/dist/Encoding-FixLatin>
+
+=item * CPAN Ratings
+
+L<http://cpanratings.perl.org/d/Encoding-FixLatin>
+
+=item * Search CPAN
+
+L<http://search.cpan.org/dist/Encoding-FixLatin/>
+
+=item * Source code repository
+
+L<http://github.com/grantm/encoding-fixlatin>
+
+=back
+
+
+=head1 AUTHOR
+
+Grant McLean, C<< <grantm at cpan.org> >>
+
+
+=head1 COPYRIGHT & LICENSE
+
+Copyright 2009-2010 Grant McLean
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+
+=cut
+
--- /dev/null
+# 3159mLT - Math::BaseCnv.pm created by Pip Stuart <Pip@CPAN.Org> to CoNVert between arbitrary number Bases. I'm totally addicted to bass!
+package NB::Math::BaseCnv;
+require Exporter;
+use strict;
+use warnings;
+use base qw(Exporter);
+use Memoize; memoize('summ'); memoize('fact'); memoize('choo');
+# only export cnv() for 'use Math::BaseCnv;' && all other stuff optionally
+our @EXPORT = qw(cnv ) ;
+our @EXPORT_OK = qw( dec hex b10 b64 b64sort dig diginit summ fact choo) ;
+our %EXPORT_TAGS = ( 'all' =>[ qw(cnv dec hex b10 b64 b64sort dig diginit summ fact choo) ],
+ 'hex' =>[ qw( dec hex ) ],
+ 'b64' =>[ qw(cnv b10 b64 b64sort ) ],
+ 'dig' =>[ qw( dig diginit) ],
+ 'sfc' =>[ qw( summ fact choo) ] );
+our $VERSION = '1.4.75O6Pbr'; our $PTVR = $VERSION; $PTVR =~ s/^\d+\.\d+\.//; # Please see `perldoc Time::PT` for an explanation of $PTVR.
+my $d2bs = ''; my %bs2d = (); my $nega = '';
+my %digsets = (
+ 'usr' => [], # this will be assigned if a dig(\@newd) call is made
+ 'bin' => ['0', '1'],
+ 'oct' => ['0'..'7'],
+ 'dec' => ['0'..'9'],
+ 'hex' => ['0'..'9', 'a'..'f'],
+ 'HEX' => ['0'..'9', 'A'..'F'],
+ 'b62' => ['0'..'9', 'a'..'z', 'A'..'Z'],
+ 'm64' => ['A'..'Z', 'a'..'z', '0'..'9', '+', '/'], # 0-63 from MIME::Base64
+ 'b64' => ['0'..'9', 'A'..'Z', 'a'..'z', '.', '_'], # month:C:12 day:V:31
+ 'b85' => ['0'..'9', 'A'..'Z', 'a'..'z', '!', '#', # RFC 1924 for IPv6 addresses, might need to return Math::BigInt objs
+ '$', '%', '&', '(', ')', '*', '+', '-', ';', '<', '=', '>', '?', '@', '^', '_', '`', '{', '|', '}', '~'],
+);
+sub bs2init { %bs2d = (); for(my $i = 0; $i < @{ $digsets{$d2bs} }; $i++) { $bs2d{${ $digsets{$d2bs} }[$i]} = $i; } } # build hash digit chars => array indices
+sub diginit { $d2bs = 'b64'; bs2init(); } # reset digit character list to initial Dflt
+sub dig { # assign a new digit character list
+ return( @{ $digsets{$d2bs} } ) unless(@_);
+ if(ref $_[0]) { $d2bs = 'usr'; $digsets{$d2bs} = [ @{ shift() } ]; }
+ else { my $setn = shift(); return(-1) unless(exists $digsets{$setn}); $d2bs = $setn; }
+ diginit() unless(@{ $digsets{$d2bs} });
+ bs2init();
+}
+sub cnv__10 { # convert from some number base to decimal fast
+ my $t = shift || '0'; my $s = shift || 64; my $n = 0;
+ $nega = ''; $nega = '-' if($t =~ s/^-//);
+ foreach(split(//, $t)) { return(-1) unless(exists $bs2d{$_}); }
+ while(length($t)) { $n += $bs2d{substr($t,0,1,'')}; $n *= $s; }
+ return($nega . int($n / $s));
+}
+sub cnv10__ { # convert from decimal to some number base fast
+ my $n = shift || 0; my $s = shift || 64; my $t = '';
+ return(-1) if($s > @{ $digsets{$d2bs} });
+ $nega = ''; $nega = '-' if($n =~ s/^-//);
+ while($n) { $t = $digsets{$d2bs}->[($n % $s)] . $t; $n = int($n / $s); }
+ if(length($t)) { $t = $nega . $t; }
+ else { $t = $digsets{$d2bs}->[0]; }
+ return($t);
+}
+sub dec { return(cnv__10(uc(shift), 16)); }#shortcut for hexadecimal -> decimal
+sub hex { return(cnv10__( shift, 16)); }#shortcut for decimal -> hex
+sub b10 { return(cnv__10( shift, 64)); }#shortcut for base64 -> decimal
+sub b64 { return(cnv10__( shift, 64)); }#shortcut for decimal -> base64
+sub b64sort { return( map { b64($_) } sort { $a <=> $b } map { b10($_) } @_ ); }
+sub cnv { # CoNVert between any number base
+ my $numb = shift; return(-1) unless(defined($numb) && length($numb));
+ my $fbas = shift; my $tbas = shift; my $rslt = ''; my $temp = 0;
+ return($digsets{$d2bs}->[0]) if($numb =~ /^-?0+$/); # lots of (negative?) zeros is just zero
+ if(!defined($tbas)) { # makeup reasonable values for missing params
+ if(!defined($fbas)) { $fbas = 10; $tbas = 16;
+ if ($numb =~ /^0x/i || ($numb =~ /[A-F]/i && $numb =~ /^[0-9A-F]+$/i )) { $fbas = 16; $tbas = 10; }
+ elsif($numb =~ /[G-Z._]/i && $numb =~ /^[0-9A-Z._]+$/i) { $fbas = 64; $tbas = 10; }
+ elsif($numb =~ /\D/) { print "!*EROR*! Can't determine reasonable FromBase && ToBase from number:$numb!\n"; }
+ } else { $tbas = $fbas; $fbas = 10; }
+ }
+ $fbas = 16 if($fbas =~ /\D/); $tbas = 10 if($tbas =~ /\D/);
+ if($fbas == 16) { $numb =~ s/^0x//i; $numb = uc($numb); }
+ return(-1) if($fbas < 2 || $tbas < 2); # invalid base error
+ $numb = cnv__10($numb, $fbas) if($numb =~ /\D/ || $fbas != 10);
+ $numb = cnv10__($numb, $tbas) if( $tbas != 10);
+ return($numb);
+}
+sub summ { # simple function to calculate summation down to 1
+ my $summ = shift; return(0) unless(defined($summ) && $summ && ($summ > 0)); my $answ = $summ; while(--$summ) { $answ += $summ; } return($answ);
+}
+sub fact { # simple function to calculate factorials
+ my $fact = shift; return(0) unless(defined($fact) && $fact && ($fact > 0)); my $answ = $fact; while(--$fact) { $answ *= $fact; } return($answ);
+}
+sub choo { # simple function to calculate n choose m (i.e., (n! / (m! * (n - m)!)))
+ my $ennn = shift; my $emmm = shift; return(0) unless(defined($ennn) && defined($emmm) && $ennn && $emmm && ($ennn != $emmm));
+ ($ennn, $emmm) = ($emmm, $ennn) if($ennn < $emmm); my $diff = $ennn - $emmm; my $answ = fact($ennn); my $mfct = fact($emmm); my $dfct = fact($diff);
+ $mfct *= $dfct; return(0) unless($mfct);
+ $answ /= $mfct; return($answ);
+}
+diginit(); # initialize the Dflt digit set whenever BaseCnv is used
+
+127;
+
+=head1 NAME
+
+Math::BaseCnv - fast functions to CoNVert between number Bases
+
+=head1 VERSION
+
+This documentation refers to version 1.4.75O6Pbr of Math::BaseCnv, which was released on Thu May 24 06:25:37:53 2007.
+
+=head1 SYNOPSIS
+
+ use NB::Math::BaseCnv;
+
+ # CoNVert 63 from base-10 (decimal) to base- 2 (binary )
+ $binary_63 = cnv( 63, 10, 2 );
+ # CoNVert 111111 from base- 2 (binary ) to base-16 (hex )
+ $hex_63 = cnv( 111111, 2, 16 );
+ # CoNVert 3F from base-16 (hex ) to base-10 (decimal)
+ $decimal_63 = cnv( '3F', 16, 10 );
+ print "63 dec->bin $binary_63 bin->hex $hex_63 hex->dec $decimal_63\n";
+
+=head1 DESCRIPTION
+
+BaseCnv provides a few simple functions for converting between arbitrary number bases. It is as fast as I currently know how to make it (of course
+relying only on the lovely Perl). If you would rather utilize an object syntax for number-base conversion, please see Ken Williams's
+<Ken@Forum.Swarthmore.Edu> fine L<Math::BaseCalc> module.
+
+=head1 PURPOSE
+
+The reason I created BaseCnv was that I needed a simple way to convert quickly between the 3 number bases I use most (10, 16, && 64). It turned out
+that it was trivial to handle any arbitrary number base that is represented as characters. High-bit ASCII has proven somewhat problemmatic but at least
+BaseCnv can simply && realiably convert between any possible base between 2 && 64 (or 85). I'm happy with it && employ b64() in places I probably
+shouldn't now =).
+
+=head1 USAGE
+
+=head2 cnv($numb[,$from[,$tobs]])
+
+CoNVert the number contained in $numb from its current number base ($from) into the result number base ($tobs).
+
+B<When only $numb is provided as a parameter:>
+
+If $numb only contains valid decimal (base 10) digits, it will be converted to hexadecimal (base 16).
+
+If $numb only contains valid hexadecimal (base 16) digits or begins with '0x', it will be it will be converted to decimal (base 10).
+
+B<When only $numb && $from are provided as parameters:>
+
+cnv() assumes that $numb is already in decimal format && uses $from as the $tobs.
+
+B<When all three parameters are provided:>
+
+The normal (&& most clear) usage of cnv() is to provide all three parameters where $numb is converted from $from base to $tobs.
+
+cnv() is the only function that is exported from a normal 'use Math::BaseCnv;' command. The other functions below can be imported to local namespaces
+explicitly or with the following tags:
+
+ :all - every function described here
+ :hex - only dec() && hex()
+ :b64 - only b10() && b64() && b64sort() && cnv()
+ :dig - only dig() && diginit()
+ :sfc - only summ(), fact(), && choo()
+
+=head2 b10($b64n)
+
+A shortcut to convert the number given as a parameter ($b64n) from base 64 to decimal (base 10).
+
+=head2 b64($b10n)
+
+A shortcut to convert the number given as a parameter ($b10n) from decimal (base 10) to base 64.
+
+=head2 b64sort(@b64s)
+
+A way to sort b64 strings as though they were decimal numbers.
+
+=head2 dec($b16n)
+
+A shortcut to convert the number given as a parameter ($b16n) from hexadecimal (base 16) to decimal (base 10).
+
+=head2 hex($b10n)
+
+A shortcut to convert the number given as a parameter ($b10n) from decimal (base 10) to hexadecimal (base 16).
+
+Please read the L<"NOTES"> regarding hex().
+
+=head2 dig(\@newd)
+
+Assign the new digit character list to be used in place of the default one. dig() can also alternately accept a string name matching one of the
+following predefined digit sets:
+
+ 'bin' => ['0', '1']
+ 'oct' => ['0'..'7']
+ 'dec' => ['0'..'9']
+ 'hex' => ['0'..'9', 'a'..'f']
+ 'HEX' => ['0'..'9', 'A'..'F']
+ 'b62' => ['0'..'9', 'a'..'z', 'A'..'Z']
+ 'm64' => ['A'..'Z', 'a'..'z', '0'..'9', '+', '/'] # MIME::Base64
+ 'b64' => ['0'..'9', 'A'..'Z', 'a'..'z', '.', '_']
+ 'b85' => ['0'..'9', 'A'..'Z', 'a'..'z', '!', '#', # RFC 1924 for
+ '$', '%', '&', '(', ')', '*', '+', '-', # IPv6 addrs
+ ';', '<', '=', '>', '?', '@', '^', '_', # like in
+ '`', '{', '|', '}', '~' ] # Math::Base85
+
+If no \@newd list or digit set name is provided as a parameter, dig() returns the current character list. It's fine to have many more characters
+in your current digit set than will be used with your conversions (e.g., using dig('b64') works fine for any cnv() call with $from && $tobs params
+less than or equal to 64).
+
+An example of a \@newd parameter for a specified alternate digit set for base 9 conversions is:
+
+ dig( [ qw( n a c h o z y u m ) ] );
+
+=head2 diginit()
+
+Resets the used digit list to the initial default order of the predefined digit set: 'b64'. This is simply a shortcut for calling dig('b64') for
+reinitialization purposes.
+
+=head2 summ($numb)
+
+A simple function to calculate a memoized summation of $numb down to 1.
+
+=head2 fact($numb)
+
+A simple function to calculate a memoized factorial of $numb.
+
+=head2 choo($ennn, $emmm)
+
+A simple function to calculate a memoized function of $ennn choose $emmm.
+
+=head1 NOTES
+
+The Perl builtin hex() function takes a hex string as a parameter && returns the decimal value (FromBase = 16, ToBase = 10) but this notation seems
+counter-intuitive to me since a simple reading of the code suggests that a hex() function will turn your parameter into hexadecimal (i.e., It sounds
+like Perl's hex() will hexify your parameter but it does not.) so I've decided (maybe foolishly) to invert the notation for my similar functions since
+it makes more sense to me this way && will be easier to remember (I've had to lookup hex() in the Camel book many times already which was part of the
+impetus for this module... as well as the gut reaction that sprintf() is not a proper natural inverse function for hex()).
+
+This means that my b64() function takes a decimal number as a parameter && returns the base64 equivalent (FromBase = 10, ToBase = 64) && my b10()
+function takes a base64 number (string) && returns the decimal value (FromBase = 64, ToBase = 10). My hex() function overloads Perl's builtin version
+with this opposite behavior so my dec() function behaves like Perl's normal hex() function. I know it's confusing && maybe bad form of me to do this
+but I like it so much better this way that I'd rather go against the grain.
+
+Please think of my dec() && hex() functions as meaning decify && hexify. Also the pronunciation of dec() is 'dess' (!'deck' which would be the inverse
+of 'ink' which -- && ++ already do so well). After reading the informative Perl module etiquette guidelines, I now appreciate the need to export as
+little as is necessary by default. So to be responsible, I have limited BaseCnv exporting to only cnv() under normal circumstances. Please
+specify the other functions you'd like to import into your namespace or use the tags described above in the cnv() section like:
+
+ 'use Math::BaseCnv qw(:all !:hex);'
+
+Error checking is minimal.
+
+This module does not handle fractional number inputs because I like using the dot (.) character as a standard base64 digit since it makes for clean filenames.
+
+summ(), fact(), && choo() are general Math function utilities which are unrelated to number-base conversion but I didn't feel like making another separate
+module just for them so they snuck in here.
+
+I hope you find Math::BaseCnv useful. Please feel free to e-mail me any suggestions or coding tips or notes of appreciation ("app-ree-see-ay-shun").
+Thank you. TTFN.
+
+=head1 2DO
+
+=over 2
+
+=item - better error checking
+
+=item - handle fractional parts? umm but I like using '.' as a b64 char so ',' comma or some other separator?
+
+=item - What else does BaseCnv need?
+
+=back
+
+=head1 CHANGES
+
+Revision history for Perl extension Math::BaseCnv:
+
+=over 2
+
+=item - 1.4.75O6Pbr Thu May 24 06:25:37:53 2007
+
+* added Test::Pod(::Coverage)? tests && PREREQ entries
+
+* added b85 for IPv6, gen'd META.yml (w/ newline before EOF), up'd minor ver
+
+=item - 1.2.68J9uJQ Sat Aug 19 09:56:19:26 2006
+
+* added b64sort() && put pod at bottom
+
+=item - 1.2.59M7mRX Thu Sep 22 07:48:27:33 2005
+
+* testing Make as primary and BuildPL backup (needing rename for dot)
+
+=item - 1.2.59IBlgw Sun Sep 18 11:47:42:58 2005
+
+* testing just using Module::Build instead of MakeMaker
+
+* fixed test 12 which was failing on AMD64
+
+* added Build.PL to pkg
+
+=item - 1.2.54HK3pB Sun Apr 17 20:03:51:11 2005
+
+* removed 128 digit-set since some hi-bit chars cause probs on Win32
+
+* made bin/cnv only executable to go in EXE_FILES
+
+* made Math::BaseCalc a link in pod && updated License
+
+=item - 1.2.45UC8fo Sun May 30 12:08:41:50 2004
+
+* tidied POD && upped minor version number since CPAN can't read PTVR
+
+=item - 1.0.44E9ljP Wed Apr 14 09:47:45:25 2004
+
+* added test for div-by-zero error in choo()
+
+* added summ()
+
+=item - 1.0.446EIbS Tue Apr 6 14:18:37:28 2004
+
+* snuck in fact() && choo()
+
+=item - 1.0.42REDir Fri Feb 27 14:13:44:53 2004
+
+* changed test.pl to hopefully pass MSWin32-x86-multi-thread
+
+=item - 1.0.428LV46 Sun Feb 8 21:31:04:06 2004
+
+* broke apart CHANGES to descend chronologically
+
+* made dec() auto uppercase param since dec(a) was returning 36 instead of 10
+
+=item - 1.0.41M4GMP Thu Jan 22 04:16:22:25 2004
+
+* put cnv in bin/ as EXE_FILES
+
+=item - 1.0.418BEPc Thu Jan 8 11:14:25:38 2004
+
+* testing new e auto-gen MANIFEST(.SKIP)?
+
+=item - 1.0.3CNH37s Tue Dec 23 17:03:07:54 2003
+
+* updated POD
+
+=item - 1.0.3CG3dIx Tue Dec 16 03:39:18:59 2003
+
+* normalized base spelling
+
+=item - 1.0.3CD1Vdd Sat Dec 13 01:31:39:39 2003
+
+* added ABSTRACT section to WriteMakeFile()
+
+* changed synopsis example
+
+* updated all POD indenting
+
+=item - 1.0.3CCA5Mi Fri Dec 12 10:05:22:44 2003
+
+* removed indenting from POD NAME field
+
+=item - 1.0.3CB7M43 Thu Dec 11 07:22:04:03 2003
+
+* updated package to coincide with Time::Fields release
+
+=item - 1.0.39B36Lv Thu Sep 11 03:06:21:57 2003
+
+* synchronized POD with README documentation using new e utility
+
+* templatized package compilation
+
+* fixed boundary bugs
+
+=item - 1.0.37SLNGN Mon Jul 28 21:23:16:23 2003
+
+* first version (&& my first Perl module... yay!) put on CPAN
+
+=item - 1.0.37JKj3w Sat Jul 19 20:45:03:58 2003
+
+* reworked interface from shell utility to package
+
+=item - 1.0.3159mLT Sun Jan 5 09:48:21:29 2003
+
+* original version
+
+=back
+
+=head1 INSTALL
+
+Please run:
+
+ `perl -MCPAN -e "install Math::BaseCnv"`
+
+or uncompress the package && run:
+
+ `perl Makefile.PL; make; make test; make install`
+ or if you don't have `make` but Module::Build is installed
+ `perl Build.PL; perl Build; perl Build test; perl Build install`
+
+=head1 LICENSE
+
+Most source code should be Free! Code I have lawful authority over is && shall be!
+Copyright: (c) 2003-2007, Pip Stuart.
+Copyleft : This software is licensed under the GNU General Public License (version 2). Please consult the Free Software Foundation (HTTP://FSF.Org)
+ for important information about your freedom.
+
+=head1 AUTHOR
+
+Pip Stuart <Pip@CPAN.Org>
+
+=cut