Top > Programming > .NetFramework > Others > Convert CShrp to PHP
Last-modified: Mon, 07 Apr 2014 23:06:41 JST
Counter:3558 Today:1 Yesterday:2 Online:7
このエントリーをはてなブックマークに追加

C# のソースコードを PHP に変換する

作業記録です。

フィールド

  • "static readonly" を "const" に変換する。
  • "readonly" を削除する。
  • "([^a-z])(int|float|double|bool|string)\s+?" を "$1" に変換する。

メソッド/関数

  • "private static\s.*?\s" を "public static function " に変換する。
  • "private static\s.*?\s" を "private static function " に変換する。
    • 戻り値(返り値)の型を取り除く
  • "([^a-z])(int|float|double|bool|string)\s+?" を "$1$" に変換する。
    • 基本の型をすべて取り除く、配列と独自定義のクラスは手作業のため後回し。
      • [] が残るので、配列は目視でも判別できる。
  • 関数内での const 宣言はできないので削除する。

文字列処理

  • "( *)([^ ]*?)\.Replace\((.*?),(.*?)\)" を "$1str_replace($3,$4, $2)" に変換する。
    • Regex.Replace が含まれてしまうかもしれないので注意する。
    • マルチバイト文字で不具合を起こす可能性がある。マルチバイト向けの同種の関数が用意されていないので、各所で公開されている "mb_str_replace" を実装するか、あるいは、"mb_ereg_replace" を使う。ただし、mb_ereg_replace は正規表現パターンに書き直す必要があるので、不特定の文字列が与えられる可能性がある場合は、mb_str_replace を実装した方が良い。
  • "( *)([^ ]*?)\.Trim\(\)" を "$1trim($2)" に変換する。
  • 文字列の結合演算子 "+" をすべて "." に変換しなければならないが、構文解析でもしない限り、"+" と "." を自動変換するのは難しい。
  • "([a-zA-Z1-9]+?)\.Length" を "mb_strlen($1)" に変換する。
    • 配列長の ".Length" と混在しないように注意する必要がある。
    • 正規表現の ".Length" より後に行う必要がある。
  • "([a-zA-Z1-9]+?)\.Substring\((.*?)\)" を "mb_substr($1, $2)" に変換する。

Contains

ある文字列が含まれているかどうかを確認するための .Contains は php には用意されていない。代わりに、mb_strpos が用意されていて、マッチするときにその index を、マッチしないときに FALSE を返す。したがって、".Contains" は "mb_strpos === false" または "mb_strpos !== false" などで置き換えることが出来る。

Split

Split に該当する関数はいくつかある。1つは mb_split(split)、もう1つはexplode、パフォーマンスに差が出るようなので、使い分けが必要かもしれない。mb_split は正規表現を使うため explode と比較してやや速度面で劣る様子。一方で explode の場合には、C# でいう空白文字での分割ができないので、空白文字の分割の場合だけ、split を使うなどの使い分けになる。

Remove と Insert

Remove と Insert に該当する関数は用意されていないので、"mb_substr" を駆使して置き換えるしかない。

  • "text.Remove(index)" パターンは、指定した index 以降の文字を削除する。
    • = 指定した index までの文字を取得する。
    • = "mb_substr($text, 0, $index)" に置き換えられる。
  • "text.Remove(index, length)" パターンは、指定した index から length 文字だけ削除する。
    • = (0 から index までの文字) + (index + length から 最後までの文字)
    • = mb_substr($text, 0, $index) . mb_substr($text, $index + $length)

正規表現

結果を取得する場合には、PREG_OFFSET_CAPTURE オプションが必須になる。

  • パターン文字列は "/pattern/" として "/" で閉じる。
  • オプションは"/pattern/option" として パターンの後につける。
    • "RegexOptions.Multiline" は "m" オプション
    • "RegexOptions.Singleline" は "s" オプション
    • "RegexOptions.IgnoreCase" は "i" オプション
  • "new Regex\((.*?)\)\;" を "$1;" に変換する。
  • "match = regex.Match(subject, offset);" のパターンは次のように変換できる。
    • "([^ ]*?)\s*=\s*(.*?)\.Match\((.*?),\s*(.*?)\);"
    • "preg_match($2, $3, $1, PREG_OFFSET_CAPTURE, $4);"

結果の置き換え

  • "\.Groups\[(.*?)\].Index" を "[$1][1]" に変換する。
  • "([\$,a-z,0-9]*)\.Groups\[(.*?)\].Length" を "mb_strlen($1[$2][0])" に変換する。
  • "\.Groups\[(.*?)\].Value" を "[$1][0]" に変換する。
  • "\.Groups\[(.*?)\]" を [$1][0]" に変換する。

Replace

正規表現による変換、"Regex.Replace(subject, replacement)" パターンは "mb_ereg_replace($pattern, $replacement, $subject)" に置き換えられる。

演算結果

  • "match.Success" のように正規表現の成否を確認するものは php では存在しない。代わりの方法は2つある。
    • preg_match の戻り値で判定する。1のときマッチした、0のときマッチしない、ただしFALSE が返る可能性がある。
      • $match_is_success = preg_match のようにするのが無難か。
      • 比較するときは "$match_is_success ===" のように厳密比較演算子を使う。
    • $matches として結果を受け取る際に、その配列の長さが 0 であるかを確認する方法

false による結果の比較
true の時だけ処理するような条件文を書くときは問題が起こりませんが、マッチングの結果を false と比較するようなときは注意が必要であると警告されています。なぜならば、マッチングにエラーが発生したときは、false が戻りますが、それ以外の時にも、理論値として、false と判断される値が戻る可能性があるためです。

この問題を解決するために、演算子 == ではなく === を使うことが推奨されています。したがって、もしも正規表現によるマッチングに失敗したケースを処理したければ、"== false" ではなく、"=== 0" と書く必要があります。"=== false" の場合には、型と値の一致が求められます。 "=== false" と書くときは、エラーが発生したときのみ真になり、一致しないときには偽となります。

Stack

  • "new Stack<.*?>\((.*?)\)" を "new SplStack()" に変換する。
    • SplStack は 5.3 以降に実装されているので、それより以前のバージョンと互換を持たせるときは、array を使う必要がある。
  • ".Pop\(\)" を "->pop()" に変換する。
  • ".Push\((.*?)\)" を "->push($1)" に変換する。
    • array を使うときは注意する必要がある。push/pop の代わりに、unshift/shiftを使う。PHP における push/pop は末尾に追加し、末尾から取り出す。一方で、C#における push/pop は、先頭に追加し、先頭から取り出す。

List

  • List は Stack や Queue のような代替クラスは用意されず、Array で実現する。
  • \.Add\((.*?)\) を "[] = $1" に変換する。

foreach

  • "foreach(each in array)" パターンは、"foreach(array as each)" で置き換えられる。

その他

  • 定数参照は、"Class.Const" から "Class::Const" へ変換する。