Encode::Encoding - Encode 實作基礎類別
package Encode::MyEncoding;
use parent qw(Encode::Encoding);
__PACKAGE__->Define(qw(myCanonical myAlias));
如 Encode 中所述,編碼(至少在目前的實作中)定義為物件。編碼名稱與物件的對應是透過 %Encode::Encoding
hash。雖然您可以直接操作此 hash,但強烈建議使用此基礎類別模組並新增 encode() 和 decode() 方法。
強烈建議您實作以下方法,至少 encode() 或 decode() 之一。
必須傳回代表 $string 的八位元組序列。
如果 $check 為真,它應修改 $string 以移除已轉換的部分(即整個字串,除非有錯誤)。如果 perlio_ok() 為真,應修改為必須修改。
如果發生錯誤,它應傳回已轉換字串片段的八位元組序列,並修改 $string 以移除已轉換的部分,使其從問題片段開始。如果 perlio_ok() 為真,應修改為必須修改。
如果 $check 為假,則 encode
必須盡力轉換字串,例如使用替換字元。
必須傳回 $octets 所代表的字串。
如果 $check 為真,它應修改 $octets 以移除已轉換的部分(即整個序列,除非有錯誤)。如果 perlio_ok() 為真,應修改為必須修改。
如果發生錯誤,它應傳回已轉換的字串片段,並修改 $octets 以移除已轉換的部分,使其從問題片段開始。如果 perlio_ok() 為真,應修改為必須修改。
如果 $check 為假,則 decode
應盡力轉換字串,例如使用 Unicode 的「\x{FFFD}」作為替換字元。
如果您希望編碼與 編碼 實用程式一起使用,您還應實作以下方法。
必須使用 $offset 解碼 $octets,並將其串接至 $destination。當 $terminator(一個字串)出現在輸出中時,解碼將會終止。$offset 將會修改為解碼結束時 $octets 的最後位置。如果 $terminator 出現在輸出中,則傳回 true,否則傳回 false。
除非必要,否則您不必覆寫以下顯示的方法。
預定義為
sub name { return shift->{'Name'} }
必須傳回代表編碼標準名稱的字串。
預定義為
sub mime_name{
return Encode::MIME::Name::get_mime_name(shift->name);
}
必須傳回代表編碼的 IANA 字元集名稱的字串。
預定義為
sub renew {
my $self = shift;
my $clone = bless { %$self } => ref($self);
$clone->{renewed}++;
return $clone;
}
此方法會在必要時重建編碼物件。如果您需要在編碼期間儲存狀態,可以在這裡複製您的物件。
PerlIO 永遠會呼叫此方法,以確保它有自己的私人編碼物件。
預定義為
sub renewed { $_[0]->{renewed} || 0 }
表示物件是否已更新(以及更新幾次)。某些模組會發出「在空運算中使用未初始化值」警告,除非值是數字,因此對於 false 傳回 0。
預定義為
sub perlio_ok {
return eval { require PerlIO::encoding } ? 1 : 0;
}
如果您的編碼由於某些原因不支援 PerlIO,只需;
sub perlio_ok { 0 }
預定義為
sub needs_lines { 0 };
如果您的編碼可以使用 PerlIO 但需要行緩衝,您必須定義此方法,讓它傳回 true。7bit ISO-2022 編碼就是需要此功能的一個範例。如果缺少此方法,會假設為 false。
package Encode::ROT13;
use strict;
use parent qw(Encode::Encoding);
__PACKAGE__->Define('rot13');
sub encode($$;$){
my ($obj, $str, $chk) = @_;
$str =~ tr/A-Za-z/N-ZA-Mn-za-m/;
$_[1] = '' if $chk; # this is what in-place edit means
return $str;
}
# Jr pna or ynml yvxr guvf;
*decode = \&encode;
1;
請注意,$check 行為與外部公開 API 不同。邏輯是當編碼是可能報告錯誤的串流(例如 STDERR)的一部分時,「未檢查」案例會很有用。在這種情況下,希望在不造成會模糊原始錯誤的其他錯誤的情況下,以某種方式傳遞所有內容。此外,編碼最適合知道正確的替換字元是什麼,因此如果那是所需的行為,讓低階層級程式碼執行是最有效率的。
相比之下,如果 $check 為 true,上述架構允許編碼盡可能執行,並告訴上層執行多少。目前缺少的是報告錯誤的機制。最可能的介面將是對物件的額外方法呼叫,或者(為了避免在其他無狀態編碼上強制使用每個串流物件)額外的參數。
強烈建議編碼類別繼承自 Encode::Encoding
作為基底類別。這允許該類別為所有編碼物件定義額外的行為。
package Encode::MyEncoding;
use parent qw(Encode::Encoding);
__PACKAGE__->Define(qw(myCanonical myAlias));
使用 bless {Name => ...}, $class
建立物件,並呼叫 define_encoding。它們從 Encode::Encoding
繼承其 name
方法。
為了速度和效率,現在大多數編碼都透過編譯形式提供支援:從 UCM 檔案產生的 XS 模組。Encode 提供 enc2xs 工具來達成此目的。請參閱 enc2xs 以取得更多詳細資料。