Move docs for Encode::valid_utf8 (which does not exist)
[p5sagit/p5-mst-13.2.git] / ext / Encode / Encode.pm
index 863022b..6a86673 100644 (file)
@@ -1,7 +1,6 @@
 package Encode;
 use strict;
-
-our $VERSION = '0.02';
+our $VERSION = '0.40';
 
 require DynaLoader;
 require Exporter;
@@ -50,7 +49,6 @@ our %winlatin2cp   = (
                      'Latin1'     => 1252,
                      'Latin2'     => 1250,
                      'Cyrillic'   => 1251,
-                     'Baltic'     => 1257,
                      'Greek'      => 1253,
                      'Turkish'    => 1254,
                      'Hebrew'     => 1255,
@@ -59,57 +57,86 @@ our %winlatin2cp   = (
                      'Vietnamese' => 1258,
                     );
 
+our %external_tables =
+    (
+       'euc-cn'        => 'Encode/CN.pm',
+       gb2312          => 'Encode/CN.pm',
+       gb12345         => 'Encode/CN.pm',
+       gbk             => 'Encode/CN.pm',
+       cp936           => 'Encode/CN.pm',
+       'iso-ir-165'    => 'Encode/CN.pm',
+       'euc-jp'        => 'Encode/JP.pm',
+       shiftjis        => 'Encode/JP.pm',
+       macjapan        => 'Encode/JP.pm',
+       cp932           => 'Encode/JP.pm',
+       'euc-kr'        => 'Encode/KR.pm',
+       ksc5601         => 'Encode/KR.pm',
+       cp949           => 'Encode/KR.pm',
+       big5            => 'Encode/TW.pm',
+       'big5-hkscs'    => 'Encode/TW.pm',
+       cp950           => 'Encode/TW.pm',
+       gb18030         => 'Encode/HanExtra.pm',
+       big5plus        => 'Encode/HanExtra.pm',
+       'euc-tw'        => 'Encode/HanExtra.pm',
+    );
+
 sub encodings
 {
  my ($class) = @_;
- return keys %encoding;
+ return
+     map { $_->[0] }
+         sort { $a->[1] cmp $b->[1] }
+               map { [$_, lc $_] }
+                   grep { $_ ne 'Internal' }
+                        keys %encoding;
 }
 
 sub findAlias
 {
- my $class = shift;
- local $_ = shift;
- unless (exists $alias{$_})
-  {
-   for (my $i=0; $i < @alias; $i += 2)
+    my $class = shift;
+    local $_ = shift;
+    # print "# findAlias $_\n";
+    unless (exists $alias{$_})
     {
-     my $alias = $alias[$i];
-     my $val   = $alias[$i+1];
-     my $new;
-     if (ref($alias) eq 'Regexp' && $_ =~ $alias)
-      {
-       $new = eval $val;
-      }
-     elsif (ref($alias) eq 'CODE')
-      {
-       $new = &{$alias}($val)
-      }
-     elsif (lc($_) eq lc($alias))
-      {
-       $new = $val;
-      }
-     if (defined($new))
-      {
-       next if $new eq $_; # avoid (direct) recursion on bugs
-       my $enc = (ref($new)) ? $new : find_encoding($new);
-       if ($enc)
-        {
-         $alias{$_} = $enc;
-         last;
-        }
-      }
+       for (my $i=0; $i < @alias; $i += 2)
+       {
+           my $alias = $alias[$i];
+           my $val   = $alias[$i+1];
+           my $new;
+           if (ref($alias) eq 'Regexp' && $_ =~ $alias)
+           {
+               $new = eval $val;
+           }
+           elsif (ref($alias) eq 'CODE')
+           {
+               $new = &{$alias}($val)
+               }
+           elsif (lc($_) eq lc($alias))
+           {
+               $new = $val;
+           }
+           if (defined($new))
+           {
+               next if $new eq $_; # avoid (direct) recursion on bugs
+               my $enc = (ref($new)) ? $new : find_encoding($new);
+               if ($enc)
+               {
+                   $alias{$_} = $enc;
+                   last;
+               }
+           }
+       }
     }
-  }
- return $alias{$_};
+    return $alias{$_};
 }
 
 sub define_alias
 {
- while (@_)
-  {
-   my ($alias,$name) = splice(@_,0,2);
-   push(@alias, $alias => $name);
-  }
+    while (@_)
+    {
+       my ($alias,$name) = splice(@_,0,2);
+       push(@alias, $alias => $name);
+    }
 }
 
 # Allow variants of iso-8859-1 etc.
@@ -121,6 +148,9 @@ define_alias( qr/^iso8859(\d+)$/i => '"iso-8859-$1"' );
 # More HP stuff.
 define_alias( qr/^(?:hp-)?(arabic|greek|hebrew|kana|roman|thai|turkish)8$/i => '"${1}8"' );
 
+# The Official name of ASCII.
+define_alias( qr/^ANSI[-_]?X3\.4[-_]?1968$/i => '"ascii"' );
+
 # This is a font issue, not an encoding issue.
 # (The currency symbol of the Latin 1 upper half
 #  has been redefined as the euro symbol.)
@@ -143,301 +173,153 @@ define_alias( 'ascii'    => 'US-ascii',
            );
 
 # At least AIX has IBM-NNN (surprisingly...) instead of cpNNN.
-define_alias( qr/^ibm[-_]?(\d\d\d\d?)$/i => '"cp$1"');
+# And Microsoft has their own naming (again, surprisingly).
+define_alias( qr/^(?:ibm|ms)[-_]?(\d\d\d\d?)$/i => '"cp$1"');
+
+# Sometimes seen with a leading zero.
+define_alias( qr/^cp037$/i => '"cp37"');
+
+# Ououououou.
+define_alias( qr/^macRomanian$/i => '"macRumanian"');
 
 # Standardize on the dashed versions.
 define_alias( qr/^utf8$/i  => 'utf-8' );
 define_alias( qr/^koi8r$/i => 'koi8-r' );
 define_alias( qr/^koi8u$/i => 'koi8-u' );
 
+# Seen in some Linuxes.
+define_alias( qr/^ujis$/i => 'euc-jp' );
+
+# CP936 doesn't have vendor-addon for GBK, so they're identical.
+define_alias( qr/^gbk$/i => '"cp936"');
+
 # TODO: HP-UX '8' encodings arabic8 greek8 hebrew8 kana8 thai8 turkish8
 # TODO: HP-UX '15' encodings japanese15 korean15 roi15
 # TODO: Cyrillic encoding ISO-IR-111 (useful?)
-# TODO: Chinese encodings GB18030 GBK Big5-HSKCS EUC-TW
 # TODO: Armenian encoding ARMSCII-8
 # TODO: Hebrew encoding ISO-8859-8-1
 # TODO: Thai encoding TCVN
 # TODO: Korean encoding Johab
-# TODO: Vietnamese encodings VISCII VPS
+# TODO: Vietnamese encodings VPS
 # TODO: Japanese encoding JIS (not the same as SJIS)
 # TODO: Mac Asian+African encodings: Arabic Armenian Bengali Burmese
 #       ChineseSimp ChineseTrad Devanagari Ethiopic ExtArabic
 #       Farsi Georgian Gujarati Gurmukhi Hebrew Japanese
 #       Kannada Khmer Korean Laotian Malayalam Mongolian
 #       Oriya Sinhalese Symbol Tamil Telugu Tibetan Vietnamese
-# TODO: what is the Japanese 'UJIS' encoding seen in some Linuxes?
 
 # Map white space and _ to '-'
 define_alias( qr/^(\S+)[\s_]+(.*)$/i => '"$1-$2"' );
 
 sub define_encoding
 {
- my $obj  = shift;
- my $name = shift;
- $encoding{$name} = $obj;
- my $lc = lc($name);
- define_alias($lc => $obj) unless $lc eq $name;
- while (@_)
-  {
-   my $alias = shift;
-   define_alias($alias,$obj);
-  }
- return $obj;
+    my $obj  = shift;
+    my $name = shift;
+    $encoding{$name} = $obj;
+    my $lc = lc($name);
+    define_alias($lc => $obj) unless $lc eq $name;
+    while (@_)
+    {
+       my $alias = shift;
+       define_alias($alias,$obj);
+    }
+    return $obj;
 }
 
 sub getEncoding
 {
- my ($class,$name) = @_;
- my $enc;
- if (ref($name) && $name->can('new_sequence'))
-  {
-   return $name;
-  }
- if (exists $encoding{$name})
-  {
-   return $encoding{$name};
-  }
- else
-  {
-   return $class->findAlias($name);
-  }
-}
-
-sub find_encoding
-{
- my ($name) = @_;
- return __PACKAGE__->getEncoding($name);
-}
-
-sub encode
-{
- my ($name,$string,$check) = @_;
- my $enc = find_encoding($name);
- croak("Unknown encoding '$name'") unless defined $enc;
- my $octets = $enc->encode($string,$check);
- return undef if ($check && length($string));
- return $octets;
-}
-
-sub decode
-{
- my ($name,$octets,$check) = @_;
- my $enc = find_encoding($name);
- croak("Unknown encoding '$name'") unless defined $enc;
- my $string = $enc->decode($octets,$check);
- $_[1] = $octets if $check;
- return $string;
-}
-
-sub from_to
-{
- my ($string,$from,$to,$check) = @_;
- my $f = find_encoding($from);
- croak("Unknown encoding '$from'") unless defined $f;
- my $t = find_encoding($to);
- croak("Unknown encoding '$to'") unless defined $t;
- my $uni = $f->decode($string,$check);
- return undef if ($check && length($string));
- $string = $t->encode($uni,$check);
- return undef if ($check && length($uni));
- return length($_[0] = $string);
-}
-
-sub encode_utf8
-{
- my ($str) = @_;
- utf8::encode($str);
- return $str;
-}
-
-sub decode_utf8
-{
- my ($str) = @_;
- return undef unless utf8::decode($str);
- return $str;
-}
-
-package Encode::Encoding;
-# Base class for classes which implement encodings
-
-sub Define
-{
- my $obj = shift;
- my $canonical = shift;
- $obj = bless { Name => $canonical },$obj unless ref $obj;
- # warn "$canonical => $obj\n";
- Encode::define_encoding($obj, $canonical, @_);
-}
-
-sub name { shift->{'Name'} }
-
-# Temporary legacy methods
-sub toUnicode    { shift->decode(@_) }
-sub fromUnicode  { shift->encode(@_) }
-
-sub new_sequence { return $_[0] }
-
-package Encode::XS;
-use base 'Encode::Encoding';
-
-package Encode::Internal;
-use base 'Encode::Encoding';
-
-# Dummy package that provides the encode interface but leaves data
-# as UTF-X encoded. It is here so that from_to() works.
-
-__PACKAGE__->Define('Internal');
-
-Encode::define_alias( 'Unicode' => 'Internal' ) if ord('A') == 65;
-
-sub decode
-{
- my ($obj,$str,$chk) = @_;
- utf8::upgrade($str);
- $_[1] = '' if $chk;
- return $str;
-}
-
-*encode = \&decode;
+    my ($class,$name,$skip_external) = @_;
+    my $enc;
+    if (ref($name) && $name->can('new_sequence'))
+    {
+       return $name;
+    }
+    my $lc = lc $name;
+    if (exists $encoding{$name})
+    {
+       return $encoding{$name};
+    }
+    if (exists $encoding{$lc})
+    {
+       return $encoding{$lc};
+    }
 
-package Encoding::Unicode;
-use base 'Encode::Encoding';
+    my $oc = $class->findAlias($name);
+    return $oc if defined $oc;
 
-__PACKAGE__->Define('Unicode') unless ord('A') == 65;
+    $oc = $class->findAlias($lc) if $lc ne $name;
+    return $oc if defined $oc;
 
-sub decode
-{
- my ($obj,$str,$chk) = @_;
- my $res = '';
- for (my $i = 0; $i < length($str); $i++)
-  {
-   $res .= chr(utf8::unicode_to_native(ord(substr($str,$i,1))));
-  }
- $_[1] = '' if $chk;
- return $res;
-}
+    if (!$skip_external and exists $external_tables{$lc})
+    {
+       require $external_tables{$lc};
+       return $encoding{$name} if exists $encoding{$name};
+    }
 
-sub encode
-{
- my ($obj,$str,$chk) = @_;
- my $res = '';
- for (my $i = 0; $i < length($str); $i++)
-  {
-   $res .= chr(utf8::native_to_unicode(ord(substr($str,$i,1))));
-  }
- $_[1] = '' if $chk;
- return $res;
+    return;
 }
 
-
-package Encode::utf8;
-use base 'Encode::Encoding';
-# package to allow long-hand
-#   $octets = encode( utf8 => $string );
-#
-
-__PACKAGE__->Define(qw(UTF-8 utf8));
-
-sub decode
+sub find_encoding
 {
- my ($obj,$octets,$chk) = @_;
- my $str = Encode::decode_utf8($octets);
- if (defined $str)
-  {
-   $_[1] = '' if $chk;
-   return $str;
-  }
- return undef;
+    my ($name,$skip_external) = @_;
+    return __PACKAGE__->getEncoding($name,$skip_external);
 }
 
 sub encode
 {
- my ($obj,$string,$chk) = @_;
- my $octets = Encode::encode_utf8($string);
- $_[1] = '' if $chk;
- return $octets;
+    my ($name,$string,$check) = @_;
+    my $enc = find_encoding($name);
+    croak("Unknown encoding '$name'") unless defined $enc;
+    my $octets = $enc->encode($string,$check);
+    return undef if ($check && length($string));
+    return $octets;
 }
 
-package Encode::iso10646_1;
-use base 'Encode::Encoding';
-# Encoding is 16-bit network order Unicode (no surogates)
-# Used for X font encodings
-
-__PACKAGE__->Define(qw(UCS-2 iso-10646-1));
-
 sub decode
 {
- my ($obj,$str,$chk) = @_;
- my $uni   = '';
- while (length($str))
-  {
-   my $code = unpack('n',substr($str,0,2,'')) & 0xffff;
-   $uni .= chr($code);
-  }
- $_[1] = $str if $chk;
- utf8::upgrade($uni);
- return $uni;
+    my ($name,$octets,$check) = @_;
+    my $enc = find_encoding($name);
+    croak("Unknown encoding '$name'") unless defined $enc;
+    my $string = $enc->decode($octets,$check);
+    $_[1] = $octets if $check;
+    return $string;
 }
 
-sub encode
+sub from_to
 {
- my ($obj,$uni,$chk) = @_;
- my $str   = '';
- while (length($uni))
-  {
-   my $ch = substr($uni,0,1,'');
-   my $x  = ord($ch);
-   unless ($x < 32768)
-    {
-     last if ($chk);
-     $x = 0;
-    }
-   $str .= pack('n',$x);
-  }
- $_[1] = $uni if $chk;
- return $str;
+    my ($string,$from,$to,$check) = @_;
+    my $f = find_encoding($from);
+    croak("Unknown encoding '$from'") unless defined $f;
+    my $t = find_encoding($to);
+    croak("Unknown encoding '$to'") unless defined $t;
+    my $uni = $f->decode($string,$check);
+    return undef if ($check && length($string));
+    $string = $t->encode($uni,$check);
+    return undef if ($check && length($uni));
+    return length($_[0] = $string);
 }
 
-package Encode::ucs_2le;
-use base 'Encode::Encoding';
-
-__PACKAGE__->Define(qw(UCS-2le UCS-2LE ucs-2le));
-
-sub decode
+sub encode_utf8
 {
- my ($obj,$str,$chk) = @_;
- my $uni   = '';
- while (length($str))
- {
-  my $code = unpack('v',substr($str,0,2,'')) & 0xffff;
-  $uni .= chr($code);
- }
- $_[1] = $str if $chk;
- utf8::upgrade($uni);
- return $uni;
+    my ($str) = @_;
+  utf8::encode($str);
+    return $str;
 }
 
-sub encode
+sub decode_utf8
 {
- my ($obj,$uni,$chk) = @_;
- my $str   = '';
- while (length($uni))
- {
-  my $ch = substr($uni,0,1,'');
-  my $x  = ord($ch);
-  unless ($x < 32768)
-  {
-   last if ($chk);
-   $x = 0;
-  }
-  $str .= pack('v',$x);
- }
- $_[1] = $uni if $chk;
- return $str;
+    my ($str) = @_;
+    return undef unless utf8::decode($str);
+    return $str;
 }
 
-# switch back to Encode package in case we ever add AutoLoader
-package Encode;
+require Encode::Encoding;
+require Encode::XS;
+require Encode::Internal;
+require Encode::Unicode;
+require Encode::utf8;
+require Encode::iso10646_1;
+require Encode::ucs2_le;
 
 1;
 
@@ -474,6 +356,13 @@ When Perl is processing "binary data" the programmer wants Perl to process
 "sequences of bytes". This is not a problem for Perl - as a byte has 256
 possible values it easily fits in Perl's much larger "logical character".
 
+Due to size concerns, each of B<CJK> (Chinese, Japanese & Korean) modules
+are not loaded in memory until the first time they're used. Although you
+don't have to C<use> the corresponding B<Encode::>(B<TW>|B<CN>|B<JP>|B<KR>)
+modules first, be aware that those encodings will not be in C<%encodings>
+until their module is loaded (either implicitly through using encodings
+contained in the same module, or via an explicit C<use>).
+
 =head2 TERMINOLOGY
 
 =over 4
@@ -569,7 +458,9 @@ repertoire.  See L</"Encoding Names">.
 
 =item 2. As an object
 
-Encoding objects are returned by C<find_encoding($name)>.
+Encoding objects are returned by C<find_encoding($name, [$skip_external])>.
+If the second parameter is true, Encode will refrain from loading external
+modules for CJK encodings.
 
 =back
 
@@ -582,11 +473,11 @@ the encoding by picking the first in the following sequence:
 
 =over 4
 
-=item * The MIME name as defined in IETF RFC-XXXX.
+=item * The MIME name as defined in IETF RFCs.
 
 =item * The name in the IANA registry.
 
-=item * The name used by the the organization that defined it.
+=item * The name used by the organization that defined it.
 
 =back
 
@@ -594,6 +485,93 @@ Because of all the alias issues, and because in the general case
 encodings have state C<Encode> uses the encoding object internally
 once an operation is in progress.
 
+As of Perl 5.8.0, at least the following encodings are recognized
+(the => marks aliases):
+
+  ASCII
+
+  US-ASCII => ASCII
+
+The Unicode:
+
+  UTF-8
+  UTF-16
+  UCS-2
+
+  ISO 10646-1 => UCS-2
+
+The ISO 8859 and KOI:
+
+  ISO 8859-1  ISO 8859-6   ISO 8859-11         KOI8-F
+  ISO 8859-2  ISO 8859-7   (12 doesn't exist)  KOI8-R
+  ISO 8859-3  ISO 8859-8   ISO 8859-13         KOI8-U
+  ISO 8859-4  ISO 8859-9   ISO 8859-14
+  ISO 8859-5  ISO 8859-10  ISO 8859-15
+                           ISO 8859-16
+
+  Latin1  => 8859-1  Latin6  => 8859-10
+  Latin2  => 8859-2  Latin7  => 8859-13
+  Latin3  => 8859-3  Latin8  => 8859-14
+  Latin4  => 8859-4  Latin9  => 8859-15
+  Latin5  => 8859-9  Latin10 => 8859-16
+
+  Cyrillic => 8859-5
+  Arabic   => 8859-6
+  Greek    => 8859-7
+  Hebrew   => 8859-8
+  Thai     => 8859-11
+  TIS620   => 8859-11
+
+The CJKV: Chinese, Japanese, Korean, Vietnamese:
+
+  ISO 2022     ISO 2022 JP-1  JIS 0201  GB 1988   Big5       EUC-CN
+  ISO 2022 CN  ISO 2022 JP-2  JIS 0208  GB 2312   HZ         EUC-JP
+  ISO 2022 JP  ISO 2022 KR    JIS 0210  GB 12345  CNS 11643  EUC-JP-0212
+  Shift-JIS                            GBK       Big5-HKSCS EUC-KR
+  VISCII                               ISO-IR-165
+
+(Due to size concerns, additional Chinese encodings including C<GB 18030>,
+C<EUC-TW> and C<BIG5PLUS> are distributed separately on CPAN, under the name
+L<Encode::HanExtra>.)
+
+The PC codepages:
+
+  CP37   CP852  CP861  CP866  CP949   CP1251  CP1256
+  CP424  CP855  CP862  CP869  CP950   CP1252  CP1257
+  CP737  CP856  CP863  CP874  CP1006  CP1253  CP1258
+  CP775  CP857  CP864  CP932  CP1047  CP1254
+  CP850  CP860  CP865  CP936  CP1250  CP1255
+
+  WinLatin1     => CP1252
+  WinLatin2     => CP1250
+  WinCyrillic   => CP1251
+  WinGreek      => CP1253
+  WinTurkiskh   => CP1254
+  WinHebrew     => CP1255
+  WinArabic     => CP1256
+  WinBaltic     => CP1257
+  WinVietnamese => CP1258
+
+(All the CPI<NNN...> are available also as IBMI<NNN...>.)
+
+The Mac codepages:
+
+  MacCentralEuropean   MacJapanese
+  MacCroatian          MacRoman
+  MacCyrillic          MacRomanian
+  MacDingbats          MacSami
+  MacGreek             MacThai
+  MacIcelandic         MacTurkish
+                       MacUkraine
+
+Miscellaneous:
+
+  7bit-greek  IR-197
+  7bit-kana   NeXTstep
+  7bit-latin1 POSIX-BC
+  DingBats    Roman8
+  GSM 0338    Symbol
+
 =head1 PERL ENCODING API
 
 =head2 Generic Encoding Interface
@@ -607,6 +585,11 @@ once an operation is in progress.
 Encodes string from Perl's internal form into I<ENCODING> and returns
 a sequence of octets.  For CHECK see L</"Handling Malformed Data">.
 
+For example to convert (internally UTF-8 encoded) Unicode data
+to octets:
+
+       $octets = encode("utf8", $unicode);
+
 =item *
 
         $string = decode(ENCODING, $bytes[, CHECK])
@@ -615,6 +598,10 @@ Decode sequence of octets assumed to be in I<ENCODING> into Perl's
 internal form and returns the resulting string.  For CHECK see
 L</"Handling Malformed Data">.
 
+For example to convert ISO 8859-1 data to UTF-8:
+
+       $utf8 = decode("latin1", $latin1);
+
 =item *
 
        from_to($string, FROM_ENCODING, TO_ENCODING[, CHECK])
@@ -728,9 +715,21 @@ For CHECK see L</"Handling Malformed Data">.
 =head2 Other Encodings of Unicode
 
 UTF-16 is similar to UCS-2, 16 bit or 2-byte chunks.  UCS-2 can only
-represent 0..0xFFFF, while UTF-16 has a "surrogate pair" scheme which
+represent 0..0xFFFF, while UTF-16 has a I<surrogate pair> scheme which
 allows it to cover the whole Unicode range.
 
+Surrogates are code points set aside to encode the 0x01000..0x10FFFF
+range of Unicode code points in pairs of 16-bit units.  The I<high
+surrogates> are the range 0xD800..0xDBFF, and the I<low surrogates>
+are the range 0xDC00..0xDFFFF.  The surrogate encoding is
+
+       $hi = ($uni - 0x10000) / 0x400 + 0xD800;
+       $lo = ($uni - 0x10000) % 0x400 + 0xDC00;
+
+and the decoding is
+
+       $uni = 0x10000 + ($hi - 0xD8000) * 0x400 + ($lo - 0xDC00);
+
 Encode implements big-endian UCS-2 aliased to "iso-10646-1" as that
 happens to be the name used by that representation when used with X11
 fonts.
@@ -899,14 +898,6 @@ implementation.  As such they are efficient, but may change.
 If CHECK is true, also checks the data in STRING for being well-formed
 UTF-8.  Returns true if successful, false otherwise.
 
-=item * valid_utf8(STRING)
-
-[INTERNAL] Test whether STRING is in a consistent state.  Will return
-true if string is held as bytes, or is well-formed UTF-8 and has the
-UTF-8 flag on.  Main reason for this routine is to allow Perl's
-testsuite to check that operations have left strings in a consistent
-state.
-
 =item *
 
         _utf8_on(STRING)
@@ -1092,7 +1083,9 @@ to be rationalized.
 
 =head1 SEE ALSO
 
-L<perlunicode>, L<perlebcdic>, L<perlfunc/open>, L<PerlIO>, L<encoding>
+L<perlunicode>, L<perlebcdic>, L<perlfunc/open>, L<PerlIO>, L<encoding>,
+L<utf8>
+
 
 =cut