MyMiniCity踏んでください!!

ただいま絶賛MyMiniCity参加中です.是非リンクを踏んでください!!(笑
June 19th, 2006

『「ますさんのパッチをどうか? と思う点について」への返信』への返信

(Read: 3507)
Add to Hatena Bookmark

参照: ます’s Diary - どうでもいい事100選
実際にどういうケースで問題になるかという例が欲しいと言うことなので書いてみました
一部実際に動かしていないのでニュアンスで読んでください(苦笑
というか若干走り書きっぽくていやん.
OSSのi18nをやってるときにmbstringはなんだかんだ言って有益なので(iconv拡張モジュールの関数群が残念ながら少なすぎ
使うのですが,日本語だけ対応とかアホなことをしたくないので,最低限

・mbstring拡張モジュールが使用できるか?
・mbstringが対応している言語か
・mbstringが対応している文字エンコードか?

を調べます.
それぞれ旧来からだと

・extension_loaded( "mbstring")
・@mb_langauge( "");
・@mb_internal_encoding( "");

で調べています.これがPHP 5からは

・extension_loaded( "mbstring")
・@mb_langauge( "");
・in_array( "",mb_list_encoding());

を期待していましたが,mb_list_encoding()がエイリアスを返さないため,例えば日本語で特に"Shift_JIS"を用いた場合,FALSEになります.


$ php -r 'var_dump( in_array( "Shift_JIS", mb_list_encodings()));'
bool(false)
これは単純に「mbstringはShift_JISをサポートしていません」に見えます.
ただしこの時点で実装通りの結果であり,マニュアルの記述が実装と一致していないだけともいえます.
以後特に"Shift_JIS"をベースに記述していきます.

次にmb_list_encodings_alias_names()を使用することを検討できるわけですが,この関数の実行結果は下記の通りです.


$ ./php -r 'var_dump( mb_list_encodings_alias_names());'
array(62) {
["pass"]=>
array(1) {
[0]=>
string(4) "none"
}
["auto"]=>
array(1) {
[0]=>
string(7) "unknown"
}
["wchar"]=>
array(0) {
}
["byte2be"]=>
array(0) {
}
["byte2le"]=>
array(0) {
}
["byte4be"]=>
array(0) {
}
["byte4le"]=>
array(0) {
}
["BASE64"]=>
array(0) {
}
["UUENCODE"]=>
array(0) {
}
["HTML-ENTITIES"]=>
array(2) {
[0]=>
string(4) "HTML"
[1]=>
string(4) "html"
}
["Quoted-Printable"]=>
array(1) {
[0]=>
string(6) "qprint"
}
["7bit"]=>
array(0) {
}
["8bit"]=>
array(1) {
[0]=>
string(6) "binary"
}
["UCS-4"]=>
array(2) {
[0]=>
string(15) "ISO-10646-UCS-4"
[1]=>
string(4) "UCS4"
}
["UCS-4BE"]=>
array(0) {
}
["UCS-4LE"]=>
array(0) {
}
["UCS-2"]=>
array(3) {
[0]=>
string(15) "ISO-10646-UCS-2"
[1]=>
string(4) "UCS2"
[2]=>
string(7) "UNICODE"
}
["UCS-2BE"]=>
array(0) {
}
["UCS-2LE"]=>
array(0) {
}
["UTF-32"]=>
array(1) {
[0]=>
string(5) "utf32"
}
["UTF-32BE"]=>
array(0) {
}
["UTF-32LE"]=>
array(0) {
}
["UTF-16"]=>
array(1) {
[0]=>
string(5) "utf16"
}
["UTF-16BE"]=>
array(0) {
}
["UTF-16LE"]=>
array(0) {
}
["UTF-8"]=>
array(1) {
[0]=>
string(4) "utf8"
}
["UTF-7"]=>
array(1) {
[0]=>
string(4) "utf7"
}
["UTF7-IMAP"]=>
array(0) {
}
["ASCII"]=>
array(10) {
[0]=>
string(14) "ANSI_X3.4-1968"
[1]=>
string(8) "iso-ir-6"
[2]=>
string(14) "ANSI_X3.4-1986"
[3]=>
string(16) "ISO_646.irv:1991"
[4]=>
string(8) "US-ASCII"
[5]=>
string(9) "ISO646-US"
[6]=>
string(2) "us"
[7]=>
string(6) "IBM367"
[8]=>
string(5) "cp367"
[9]=>
string(7) "csASCII"
}
["EUC-JP"]=>
array(4) {
[0]=>
string(3) "EUC"
[1]=>
string(6) "EUC_JP"
[2]=>
string(5) "eucJP"
[3]=>
string(8) "x-euc-jp"
}
["SJIS"]=>
array(2) {
[0]=>
string(6) "x-sjis"
[1]=>
string(9) "SHIFT-JIS"
}
["eucJP-win"]=>
array(1) {
[0]=>
string(10) "eucJP-open"
}
["SJIS-win"]=>
array(4) {
[0]=>
string(9) "SJIS-open"
[1]=>
string(5) "CP932"
[2]=>
string(11) "Windows-31J"
[3]=>
string(8) "MS_Kanji"
}
["JIS"]=>
array(0) {
}
["ISO-2022-JP"]=>
array(0) {
}
["Windows-1252"]=>
array(1) {
[0]=>
string(6) "cp1252"
}
["ISO-8859-1"]=>
array(2) {
[0]=>
string(10) "ISO_8859-1"
[1]=>
string(6) "latin1"
}
["ISO-8859-2"]=>
array(2) {
[0]=>
string(10) "ISO_8859-2"
[1]=>
string(6) "latin2"
}
["ISO-8859-3"]=>
array(2) {
[0]=>
string(10) "ISO_8859-3"
[1]=>
string(6) "latin3"
}
["ISO-8859-4"]=>
array(2) {
[0]=>
string(10) "ISO_8859-4"
[1]=>
string(6) "latin4"
}
["ISO-8859-5"]=>
array(2) {
[0]=>
string(10) "ISO_8859-5"
[1]=>
string(8) "cyrillic"
}
["ISO-8859-6"]=>
array(2) {
[0]=>
string(10) "ISO_8859-6"
[1]=>
string(6) "arabic"
}
["ISO-8859-7"]=>
array(2) {
[0]=>
string(10) "ISO_8859-7"
[1]=>
string(5) "greek"
}
["ISO-8859-8"]=>
array(2) {
[0]=>
string(10) "ISO_8859-8"
[1]=>
string(6) "hebrew"
}
["ISO-8859-9"]=>
array(2) {
[0]=>
string(10) "ISO_8859-9"
[1]=>
string(6) "latin5"
}
["ISO-8859-10"]=>
array(2) {
[0]=>
string(11) "ISO_8859-10"
[1]=>
string(6) "latin6"
}
["ISO-8859-13"]=>
array(1) {
[0]=>
string(11) "ISO_8859-13"
}
["ISO-8859-14"]=>
array(2) {
[0]=>
string(11) "ISO_8859-14"
[1]=>
string(6) "latin8"
}
["ISO-8859-15"]=>
array(1) {
[0]=>
string(11) "ISO_8859-15"
}
["ISO-8859-16"]=>
array(1) {
[0]=>
string(11) "ISO_8859-16"
}
["EUC-CN"]=>
array(5) {
[0]=>
string(5) "CN-GB"
[1]=>
string(6) "EUC_CN"
[2]=>
string(5) "eucCN"
[3]=>
string(8) "x-euc-cn"
[4]=>
string(6) "gb2312"
}
["CP936"]=>
array(2) {
[0]=>
string(6) "CP-936"
[1]=>
string(3) "GBK"
}
["HZ"]=>
array(0) {
}
["EUC-TW"]=>
array(3) {
[0]=>
string(6) "EUC_TW"
[1]=>
string(5) "eucTW"
[2]=>
string(8) "x-euc-tw"
}
["BIG-5"]=>
array(4) {
[0]=>
string(7) "CN-BIG5"
[1]=>
string(8) "BIG-FIVE"
[2]=>
string(7) "BIGFIVE"
[3]=>
string(5) "CP950"
}
["EUC-KR"]=>
array(3) {
[0]=>
string(6) "EUC_KR"
[1]=>
string(5) "eucKR"
[2]=>
string(8) "x-euc-kr"
}
["UHC"]=>
array(1) {
[0]=>
string(5) "CP949"
}
["ISO-2022-KR"]=>
array(0) {
}
["Windows-1251"]=>
array(3) {
[0]=>
string(6) "CP1251"
[1]=>
string(7) "CP-1251"
[2]=>
string(12) "WINDOWS-1251"
}
["CP866"]=>
array(3) {
[0]=>
string(5) "CP866"
[1]=>
string(6) "CP-866"
[2]=>
string(7) "IBM-866"
}
["KOI8-R"]=>
array(2) {
[0]=>
string(6) "KOI8-R"
[1]=>
string(5) "KOI8R"
}
["ArmSCII-8"]=>
array(4) {
[0]=>
string(9) "ArmSCII-8"
[1]=>
string(8) "ArmSCII8"
[2]=>
string(9) "ARMSCII-8"
[3]=>
string(8) "ARMSCII8"
}
}

$ ./php -r 'var_dump( mb_list_encodings_alias_names( "Shift_JIS"));'
array(2) {
[0]=>
string(6) "x-sjis"
[1]=>
string(9) "SHIFT-JIS"
}
上記に書いた実装でShift_JISを導き出すには下記のようなコードになります.


function check_mbstring( $language, $encoding) {
$mb_encodings = mb_list_encodings();
$mb_encodings = array_map( "strtoupper", $encodings);

$mb_alias_encodings = @mb_list_encodings_alias_names( $encoding);

if ( @mb_language( $language) !== FALSE &&
( in_array( strtoupper( $encoding), $encodings) !== FALSE ||
is_array( $mb_alias_encodings) === FALSE)) {
$mb_support = TRUE;
} else {
$mb_support = FALSE;
}
}
・言語のサポートをしているか
・文字エンコードのサポートをしているか(直接サポート? エイリアスサポート?)
すごいややこしくないですか?

そこでmb_list_encodings()に引数が追加されたので,


$ ./php -r 'var_dump( mb_list_encodings( "Shift_JIS"));'
string(4) "SJIS"
下記のように書くこともできます.


function check_mbstring( $language, $encoding) {
return @mb_language( $language) !== FALSE &&
@mb_list_encodings( $encoding) !== FALSE;
}
しかしよく見てください.上記コードはエラー抑制しています.

mbstringは全体的に

「範囲外の文字エンコードが指定されるとE_NOTICEにする」

という実装が行われているので演算子「@」を外すのはおかしいでしょう.
ということで結局1つめの長い実装になります.
こういうケースはどういう場合で出てくるか?

・i18nでどんな言語,文字エンコードが来るかわからないアプリケーション
・Shift_JISのHTMLを解析しないといけない場合(crowlerなど)

となるでしょう.前者はあまり日本ローカルでは関係ないですが,後者は大ありです.

#まぁ適当でいい加減なコードでいいなら好きに書いてくれって感じですけど.

というところで理想的なスクリプトは


function check_mbstring( $language, $encoding) {
$mb_languages = mb_list_languages();
$mb_encodings = mb_list_language();

// しないでいいならなおうれしい
$mb_languages = array_map( "strtoupper", $mb_languages);
$mb_encodings = array_map( "strtoupper", $mb_encodings);

return in_array( strtoupper( $language), $mb_languages) == TRUE &&
in_array( strtoupper( $encoding), $mb_encodings) == TRUE
}
という形であり,とても自然な話だと思います.

#mb_list_languages()がないので,@mb_language( $language)で今は書かざるをえませんが.

個人的にポイントは

・ある程度慣れていれば関数名からコードをおおよそ正確に推測できる
・他言語でのi18nのある程度でいいので,知識があればmbstringの内部実装をしら縛手もおおよそ正確に推測ができる

辺りです.「マニュアル読めばわかる」ってのも最終的にはありでしょうけど,
「マニュアル読まなければさっぱりわからない」というのも問題だと思います.
特に今回実体文字エンコード名(でいいんだっけ)とエイリアスを分けなければPHPスクリプトを書く上で問題はないという認識なので,
「マニュアル読まなければさっぱりわからない」は全く不必要だと考えます.

当然1から書こうと思ったら引数と返値についてマニュアルを引かなければいけない場面はあるでしょう.
しかしいくつかのケースでそういう場面ではなく,例えば私はある問題が発生し,mailmanのソースを読まなければいけなくなった,
yumのソースを読まなければいけなくなったというとき,大まかな流れをしるというレベルではpythonのマニュアルは引いていません.
そういうますがたさんパッチと私の提案はスレッショルドのあちら側とこちら側という感覚がしています.
#感覚なのでスレッショルドの上下について言い出すとキリないので一旦そう思ってる位でお願いします;)

逆にますがたさんパッチではこういうコードで書けば「スマートに読める」というコードがあれば提示していただければと思います.

ちなみに


少なくとも幸せになれる人がココにいます。:)

というのはさておき、以前の日記にも書いたのですが、全ての値をMIXしてしまうと「どれがエイリアスなのか実体なのか」を判別するのが戻り値を見ただけでは判別できません。分かれていた方が全然幸せですね。


ということですが,PHPスクリプトで実装をする上で,

・mbstringの実体文字エンコード名
・mbstringのエイリアス文字エンコード名

が「わからなければいけない」場面はあるのでしょうか?
全く想像がつきませんので,逆に例を提示していただければと思います.

「mb_list_*」関数群はlibmbfl内で定義されている(それぞれの)情報を返しているので、取捨選択(というか個人の勝手な判断)をモジュール内で行なうのは流石にマズいのかと。


でもMIMEと名乗りつつMIMEにないものを返すのもおかしくないですか?
Contenty-Type: text/plain charset=BASE64
とか解析できちゃうのはそれはそれで問題になりませんか?
つまり「mbstringの仕様的バグと考えられるものを露出させることに問題がないのか」ともいえると考えます.

ちなみに返事には入っていませんでしたが,


$ ./php -r 'var_dump( mb_list_encodings( "Shift_JIS"));'
string(4) "SJIS"
で「SJIS」が返る必要ないんじゃね? というのと
「mb_list_encodings()の仕様変更について」

#というか冷静に考えるとこれ関数名の「list」から逸脱してませんか?

mb_list_encodings_alias_names()の最後の「names」要らないんじゃね?
ってのもリマインダーで書いておきます;)

#で,どうしてもphp-dev@php.gr.jpではやりたくないんですね(苦笑

最後にがっつりなんで食いついているかと言うことですが,
ソフトウェア開発でありがちなパターンです.

・欲しいと思われる機能がサクっと実装できそうなので実装した
・やっぱまずいよねって雰囲気になってきた
・でももう仕様変えられない

今はこの第1ステージにいると思っています.申し訳ないですけど.

トピックの参照元

▼最近のトピック

▼ 人気のトピック


< 過去の記事 [ 10All Categories ] 新しい記事 >
Powered by gsblog (customize)

[ POST ] [ AddLink ] [ CtlPanel ]

Subscribe blog

Bookmark blog

About me

about me

応援しています

我が息子が産まれたアクア・バースハウス(東京都世田谷区にある助産院)を応援しています.

翻訳のお仕事

腕に自信がある方,修行をしたい方はこちらをどうぞ.

2019 calendar

10月
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
| Day | Month | Year |

Powered by RRDTOOL.

Archives

Categories

Links


Mail to admin

人気ブログランキングへ RSS feed meter for http://blog.poyo.jp/ Search Engine Optimization
blogpeople.netに登録!! スカウター : よくきたblog

My Google news

My Google News

Related site

ころんころん♪ べびぽよ フォト蔵Wiki
string(14) "/id-1150686182"