Ruby 1.9 における replica と alias の違い
端的にいえば以下の通り。
- replica
- 「encoding」を定義する
- alias
- 「encoding *名*」を定義する
図にすると以下のような感じ。
鬼車(CES) OnigEncodingSJIS │←────────────────┐ ───┼─────────────────┼────────────── │ │ Encoding (文字集合+CES) │ │ #<Encoding:Shift_JIS> ─(replica)→ #<Encoding:Windows-31J> │ │ │ │ ───┼─────┼───────────┼─────┼──────── │ (alias) │ (alias) Encoding名 │ ↓ │ ↓ (charset名) "Shift_JIS" "SJIS" "Windows-31J" "CP932"
(鬼車層とEncoding層の区別は正確ではないのですが便宜上こうしておきます。実際には Encoding 層 での #
鬼車層では文字単位の操作を行っています。具体的には str[n] が何を返すか、str.length はどのくらいか。また String#valid_encoding? の true/false 判定もこのレベルです。鬼車層の実体は、文字の最小バイト数と最大バイト数の指定や、文字列の長さを算出する関数、大文字を小文字に変換する関数等をひとまとめにした構造体 OnigEncodingType で、具体的には ONIG_ENCODING_ASCII やONIG_ENCODING_SJIS 等があります。
Encoding 層では文字列操作全般を司ります。具体的には文字列の結合可能・比較可能、正規表現のマッチ可能判定がこの層で行われています。この層での実体は rb_encoding です。Encoding 層における実体は 鬼車が native に対応している encoding から直結している original encoding、original encoding からreplicate された replica encoding、鬼車が対応していない encoding に便宜的に与えられる dummy encoding の3種類に分けることができます。これらを見分けるには Encoding#base_encoding や Encoding#dummy? を見るわけですが、見たからどうということでもありません。
これらの区別を超越する存在が 7bit のみで構成された文字列で、String#ascii_only? で判定可能です。これが真になる文字列はいかなるencoding の文字列とも結合・比較可能となります。
なお、rb_encoding は OnigEncodingType の同じもののため、Encoding 層でのreplica でも、鬼車レベルの諸関数、例えば文字群に Unicode Property Nameを与えたり、valid なバイト列の範囲を定義し直すことが可能です。([ruby-dev:32947] での「レプリカはコピーをした後で関数のいくつかを上書きすることも可能」とはたぶんこのこと)
Encoding名層は、Encoding.find() するためのテーブルです。実際の構造は以下のようになっていると考えればいいでしょう。alias で追加された名前は、文字列から rb_encoding を検索する際にのみに用いられます。
ENC_TABLE = { 'Shift_JIS' => Encoding::Shift_JIS, 'Windows-31J' => Encoding::Windows_31J, 'EUC-JP' => Encoding::EUC_JP } ENC_TABLE_ALIAS = { 'SJIS' => Encoding::Shift_JIS, 'CP932' => Encoding::Windows_31J, 'EUCJP' => Encoding::EUC_JP } def rb_enc_alias(alias, orig) ENC_TABLE_ALIAS[alias] = orig end def Encoding.find(name) return ENC_TABLE[name] if ENC_TABLE[encname] return ENC_TABLE_ALIAS[name] if ENC_TABLE_ALIAS[encname] return -1 end