]> git.nbdom.net Git - nb.git/commitdiff
missing modules from IZI
authorNicolas Boisselier <nicolas.boisselier@gmail.com>
Sat, 2 Nov 2024 21:53:47 +0000 (22:53 +0100)
committerNicolas Boisselier <nicolas.boisselier@gmail.com>
Sat, 2 Nov 2024 21:53:47 +0000 (22:53 +0100)
20 files changed:
lib/perl/NB/Encoding/FixLatin.pm [new file with mode: 0644]
lib/perl/NB/Encoding/big5.enc [new file with mode: 0644]
lib/perl/NB/Encoding/euc-kr.enc [new file with mode: 0644]
lib/perl/NB/Encoding/iso-8859-15.enc [new file with mode: 0644]
lib/perl/NB/Encoding/iso-8859-2.enc [new file with mode: 0644]
lib/perl/NB/Encoding/iso-8859-3.enc [new file with mode: 0644]
lib/perl/NB/Encoding/iso-8859-4.enc [new file with mode: 0644]
lib/perl/NB/Encoding/iso-8859-5.enc [new file with mode: 0644]
lib/perl/NB/Encoding/iso-8859-7.enc [new file with mode: 0644]
lib/perl/NB/Encoding/iso-8859-8.enc [new file with mode: 0644]
lib/perl/NB/Encoding/iso-8859-9.enc [new file with mode: 0644]
lib/perl/NB/Encoding/windows-1250.enc [new file with mode: 0644]
lib/perl/NB/Encoding/windows-1252.enc [new file with mode: 0644]
lib/perl/NB/Encoding/x-euc-jp-jisx0221.enc [new file with mode: 0644]
lib/perl/NB/Encoding/x-euc-jp-unicode.enc [new file with mode: 0644]
lib/perl/NB/Encoding/x-sjis-cp932.enc [new file with mode: 0644]
lib/perl/NB/Encoding/x-sjis-jdk117.enc [new file with mode: 0644]
lib/perl/NB/Encoding/x-sjis-jisx0221.enc [new file with mode: 0644]
lib/perl/NB/Encoding/x-sjis-unicode.enc [new file with mode: 0644]
lib/perl/NB/Math/BaseCnv.pm [new file with mode: 0644]

diff --git a/lib/perl/NB/Encoding/FixLatin.pm b/lib/perl/NB/Encoding/FixLatin.pm
new file mode 100644 (file)
index 0000000..15f6794
--- /dev/null
@@ -0,0 +1,415 @@
+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
+
diff --git a/lib/perl/NB/Encoding/big5.enc b/lib/perl/NB/Encoding/big5.enc
new file mode 100644 (file)
index 0000000..94b2bd4
Binary files /dev/null and b/lib/perl/NB/Encoding/big5.enc differ
diff --git a/lib/perl/NB/Encoding/euc-kr.enc b/lib/perl/NB/Encoding/euc-kr.enc
new file mode 100644 (file)
index 0000000..3da8a13
Binary files /dev/null and b/lib/perl/NB/Encoding/euc-kr.enc differ
diff --git a/lib/perl/NB/Encoding/iso-8859-15.enc b/lib/perl/NB/Encoding/iso-8859-15.enc
new file mode 100644 (file)
index 0000000..77fdc3e
Binary files /dev/null and b/lib/perl/NB/Encoding/iso-8859-15.enc differ
diff --git a/lib/perl/NB/Encoding/iso-8859-2.enc b/lib/perl/NB/Encoding/iso-8859-2.enc
new file mode 100644 (file)
index 0000000..d320d7f
Binary files /dev/null and b/lib/perl/NB/Encoding/iso-8859-2.enc differ
diff --git a/lib/perl/NB/Encoding/iso-8859-3.enc b/lib/perl/NB/Encoding/iso-8859-3.enc
new file mode 100644 (file)
index 0000000..ba48378
Binary files /dev/null and b/lib/perl/NB/Encoding/iso-8859-3.enc differ
diff --git a/lib/perl/NB/Encoding/iso-8859-4.enc b/lib/perl/NB/Encoding/iso-8859-4.enc
new file mode 100644 (file)
index 0000000..0294a24
Binary files /dev/null and b/lib/perl/NB/Encoding/iso-8859-4.enc differ
diff --git a/lib/perl/NB/Encoding/iso-8859-5.enc b/lib/perl/NB/Encoding/iso-8859-5.enc
new file mode 100644 (file)
index 0000000..6dbd169
Binary files /dev/null and b/lib/perl/NB/Encoding/iso-8859-5.enc differ
diff --git a/lib/perl/NB/Encoding/iso-8859-7.enc b/lib/perl/NB/Encoding/iso-8859-7.enc
new file mode 100644 (file)
index 0000000..02a4aee
Binary files /dev/null and b/lib/perl/NB/Encoding/iso-8859-7.enc differ
diff --git a/lib/perl/NB/Encoding/iso-8859-8.enc b/lib/perl/NB/Encoding/iso-8859-8.enc
new file mode 100644 (file)
index 0000000..f211bd5
Binary files /dev/null and b/lib/perl/NB/Encoding/iso-8859-8.enc differ
diff --git a/lib/perl/NB/Encoding/iso-8859-9.enc b/lib/perl/NB/Encoding/iso-8859-9.enc
new file mode 100644 (file)
index 0000000..fdc574b
Binary files /dev/null and b/lib/perl/NB/Encoding/iso-8859-9.enc differ
diff --git a/lib/perl/NB/Encoding/windows-1250.enc b/lib/perl/NB/Encoding/windows-1250.enc
new file mode 100644 (file)
index 0000000..d4a64b5
Binary files /dev/null and b/lib/perl/NB/Encoding/windows-1250.enc differ
diff --git a/lib/perl/NB/Encoding/windows-1252.enc b/lib/perl/NB/Encoding/windows-1252.enc
new file mode 100644 (file)
index 0000000..ab2d57c
Binary files /dev/null and b/lib/perl/NB/Encoding/windows-1252.enc differ
diff --git a/lib/perl/NB/Encoding/x-euc-jp-jisx0221.enc b/lib/perl/NB/Encoding/x-euc-jp-jisx0221.enc
new file mode 100644 (file)
index 0000000..ca79c07
Binary files /dev/null and b/lib/perl/NB/Encoding/x-euc-jp-jisx0221.enc differ
diff --git a/lib/perl/NB/Encoding/x-euc-jp-unicode.enc b/lib/perl/NB/Encoding/x-euc-jp-unicode.enc
new file mode 100644 (file)
index 0000000..34d4d0d
Binary files /dev/null and b/lib/perl/NB/Encoding/x-euc-jp-unicode.enc differ
diff --git a/lib/perl/NB/Encoding/x-sjis-cp932.enc b/lib/perl/NB/Encoding/x-sjis-cp932.enc
new file mode 100644 (file)
index 0000000..c2a6bc4
Binary files /dev/null and b/lib/perl/NB/Encoding/x-sjis-cp932.enc differ
diff --git a/lib/perl/NB/Encoding/x-sjis-jdk117.enc b/lib/perl/NB/Encoding/x-sjis-jdk117.enc
new file mode 100644 (file)
index 0000000..b6c2c07
Binary files /dev/null and b/lib/perl/NB/Encoding/x-sjis-jdk117.enc differ
diff --git a/lib/perl/NB/Encoding/x-sjis-jisx0221.enc b/lib/perl/NB/Encoding/x-sjis-jisx0221.enc
new file mode 100644 (file)
index 0000000..cbb2db5
Binary files /dev/null and b/lib/perl/NB/Encoding/x-sjis-jisx0221.enc differ
diff --git a/lib/perl/NB/Encoding/x-sjis-unicode.enc b/lib/perl/NB/Encoding/x-sjis-unicode.enc
new file mode 100644 (file)
index 0000000..6f88a06
Binary files /dev/null and b/lib/perl/NB/Encoding/x-sjis-unicode.enc differ
diff --git a/lib/perl/NB/Math/BaseCnv.pm b/lib/perl/NB/Math/BaseCnv.pm
new file mode 100644 (file)
index 0000000..aca8867
--- /dev/null
@@ -0,0 +1,401 @@
+# 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