Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICU4Cによる文字コード検出機能を追加する #1104

Merged

Conversation

berryzplus
Copy link
Contributor

PR の目的

ICU4Cによる文字コード検出機能を追加

カテゴリ

  • 機能追加

PR の背景

ICU というライブラリがあります。
http://site.icu-project.org/home

IBMが作ったライブラリで、ほぼすべての文明国のローカル言語を表現できる文字コードセット群をサポートしています。一応、何年も前に IBM の手を離れていて、現在は Unicode コンソーシアムが仕切りをやっているので、最新のUNICODE規格にも対応しているはずです。

c++規格がwchar_tをUNICODE規格に準拠させる対応を積極的に行わない理由。
UNICODE規格は、1プログラム言語の仕様として取り込むには複雑すぎる、らしいです。
その「複雑すぎる仕様」をコードの形に落とし込んであるのが ICU4C です。

試食版として、とりあえず動くように組み込んでみました。
最新版DLL(icuin66.dll, icudt66.dll, icuuc66.dll) はまだダウンロードできないっぽいので、動作させるには https://github.com/unicode-org/icu からソースを落としてビルドする必要があります。

PR のメリット

  • 文字コード判別に ICU4C の DLL を使えるようになります。

PR のデメリット (トレードオフとかあれば)

  • ICU4C はUNIX由来のプロジェクトなので、Windows向けポートが「雑」です。
  • ICU4C の DLL には インターフェース関数 がないので、対応バージョンは固定にせざるを得ませんでした。PRの変更では、現時点の最新版(=66)のみに対応するようになっています。
  • ICU4C の DLL はインターネットで配布するには巨大すぎる (約20MB) ので、インストーラーに同梱する予定はありません。これにより次の問題が発生します。
  • この PR による変更を確認するために必要な ICU4C の DLL は icuin66.dll, icudt66.dll, icuuc66.dll の 3つ ですが、これらを github から落としてきて使える状態にする作業は「一般向け」としては難易度が高すぎるように思います。

メリットは ICU4Cが使えるようになること なんですが、デメリットは ICU4Cを使わざるを得ないこと だったりします。

PR の影響範囲

  • この PR の恩恵を得るには、ICU4C の DLL が必要です。
    • ICU4C の DLL を入手しない場合、アプリ(=サクラエディタ)の機能に影響はありません。
    • 入手した DLL は sakura.exe と同じフォルダに配置する必要があります。。
  • (ICU4C の DLL を用意した場合のみ) 文字コード判別に ICU4C が使われるようになります。
    • 主に通常用途(テキストの編集など) では ICU4C のコード判別のほうが有利です。
    • 変態用途(バイナリファイルの編集など) では サクラエディタ のコード判別でないと使い物にならないと考えられます。

関連チケット

#487 文字コード自動判定(UTF-8をSJISと誤認)
#989 C++の準拠規格をC++17に更新する

参考資料

Mediatorパターン

CCodeMediator.hからCESI.h依存を追い出して仲介者としての役割を果たせるようにする。
@AppVeyorBot
Copy link

@beru
Copy link
Contributor

beru commented Nov 30, 2019

説明に試食版と書かれてますが merge 先が master ブランチになっています。

気になる点としてはオプショナルな実装になっているかですね。

  • ICU4Cが無くてもビルド出来るかどうか
  • ICU4Cが無くても生成物が動作するか
  • ICU4Cが存在する環境でも使わないように設定する事で従来通りの動作に出来るか
    • dllファイルを配置するかどうかで制御みたいですが。。

あとメリットの説明にはICU4Cを使うことで判別精度が良くなるとかは書かれていないので、使うことが目的に見えてしまいます、手段が目的になるのはよくあることですが。PRの影響範囲には利点が少し書かれてますね。

@berryzplus
Copy link
Contributor Author

説明に試食版と書かれてますが merge 先が master ブランチになっています。

意図通りです。現状では、マージしても一般の人が使うのは難しい実装になっています。
ビルドにも実行にもICU4Cは不要なので、masterにマージしても問題ないと考えています。
なお、CIのMinGWビルドが失敗しているのは #1108 の影響です。

気になる点としてはオプショナルな実装になっているかですね。
•ICU4Cが無くてもビルド出来るかどうか
•ICU4Cが無くても生成物が動作するか
•ICU4Cが存在する環境でも使わないように設定する事で従来通りの動作に出来るか
◦dllファイルを配置するかどうかで制御みたいですが。。

設定項目は既に飽和していると思うので、設定により無効化する機能は投入していません。
隠し設定(=GUIなし)で無効化する機能ならば入れても良いかも知れません。
いずれにしろ、現状は「有効にする」のが非常に難しいと思うので本体に入っても「お試し」に過ぎない認識です。

あとメリットの説明にはICU4Cを使うことで判別精度が良くなるとかは書かれていないので、使うことが目的に見えてしまいます、手段が目的になるのはよくあることですが。PRの影響範囲には利点が少し書かれてますね。

バイナリファイルを読み込ませたときの挙動をどうすべきかで迷いがあったのでメリットには書きませんでした。先頭数文字がASCIIでファイルの途中にNULバイトが含まれるようなファイル(BMPやEXEなど)を読み込ませた場合とか、現状だと LATIN1 になっちゃうのを対策したほうがいいんじゃないか?みたいな迷いが。

テキストファイルの判別精度は上がると考えられます。
ただし、判別したキャラクタセットをすべて拾い切れるわけではないので、変換部をもう少し詰める必要があると思います。

現状の実装ではサクラエディタの内部コードに変換できなかった場合は、従来通りの判別ロジックが走るようにしています。

@berryzplus
Copy link
Contributor Author

Oh....

g++ -finput-charset=utf-8 -fexec-charset=cp932 -I. -DWIN32 -D_WIN32_WINNT=_WIN32_WINNT_WIN7 -D_UNICODE -DUNICODE -D_DEBUG -g -O0 -std=c++17  -o charset/CEuc.o -c charset/CEuc.cpp
   43 |  typedef UCharsetDetector*  (_cdecl *ucsdet_open_t)(UErrorCode *status);
      |                             ~      ^~
      |                                    )

ローカルで再現しそうなビルドエラーが出ていたことに気付くなど...orz

誤) _cdecl
正) __cdecl
呼出規約を表すキーワード__cdeclはアンダースコア2つが正しいです。
@AppVeyorBot
Copy link

@berryzplus
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@berryzplus
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@berryzplus
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@beru
Copy link
Contributor

beru commented Dec 1, 2019

文字コード判定で libguess というのもあるみたいなので、巨大な ICU4C を使うより出来るだけ小規模なライブラリを取り込む方が良いように思えます。どちらも使った事無いので無責任な発言ですけど。。

@berryzplus
Copy link
Contributor Author

「嫌」ですかね?w

一応世間的には、ICU4Cを使うやり方がもっともド真ん中正攻法なやり方なはずです。

PR出しといてアレですが、個人的な見解としては「他に選択肢がなくて仕方なく採用」というのがICU4Cへの評価です。可能ならば使いたくはない、でもUNICODE規格への完全対応を視野にいれるなら避けては通れない、それがICU4Cだと思っています。GitHubのプロジェクトをウォッチしてますけど、まともなDLLを作れるようになるまでにあと10年はかかりそうな気配を感じています。

で、このPRをどうするか?

  • このPRはICU4Cの文字コード判別機構をサクラエディタで使えるようにします。
  • このPRによる変更で、ICU4Cのヘッダ・ライブラリへの依存は発生しません。
  • このPRによる機能追加は「とりあえず使う」には十分ですが、改善点がたくさんあります。

「とりあえず入れちゃっても害はない」と思うので入れちゃいたい感じですが、rejectでもよいです。rejectなら前提として作った CCodeMediator のリファクタリングを切り離して別出ししたい感じですが、他のライブラリ参照系機能のベースとして参考になるソースだと思うので、PR自体はしばらく放置しとく感じにすると思います。

@beru
Copy link
Contributor

beru commented Dec 1, 2019

  • icudt66.dll
  • icuin66.dll
  • icuuc66.dll

ですが、合計して 3.67 MB ぐらいでした。

文字コード判別だけならもっと規模が小さいライブラリで実現した方が良いと思いますが、追加したいならOKだと思います。

ICU4Cによる文字コード検出機能を追加、以外の変更も含まれているのでちょっと比較しなきゃいけない差分が多いのが面倒に感じますね。。

@berryzplus
Copy link
Contributor Author

すんません、頂いたコメントへのレスは明日になりそうです。

@berryzplus berryzplus changed the title ICU4Cによる文字コード検出機能を追加する [WIP] ICU4Cによる文字コード検出機能を追加する Dec 7, 2019
BOMコードが間違っていたのをこっそり修正。
@berryzplus berryzplus changed the title [WIP] ICU4Cによる文字コード検出機能を追加する ICU4Cによる文字コード検出機能を追加する Dec 7, 2019
@AppVeyorBot
Copy link

@berryzplus
Copy link
Contributor Author

•icudt66.dll
•icuin66.dll
•icuuc66.dll

ですが、合計して 3.67 MB ぐらいでした。

これなんですけど、うちのローカルビルドで生成された数字を参考で載せときます。

Release | Win32 = 30.3 MB (31,835,648 bytes)
Release | x64 = 31.0 MB (32,508,416 bytes)

@beru
Copy link
Contributor

beru commented Dec 7, 2019

•icudt66.dll
•icuin66.dll
•icuuc66.dll
ですが、合計して 3.67 MB ぐらいでした。

これなんですけど、うちのローカルビルドで生成された数字を参考で載せときます。

Release | Win32 = 30.3 MB (31,835,648 bytes)
Release | x64 = 31.0 MB (32,508,416 bytes)

およ、不思議ですね…。

ちなみに自分がビルドしたのは 873e2db78070d3015a54f9d9aa81e97095cd9dba の icu4c/source/allinone.sln の Win32 Release です。生成物は icu4c/bin に作られました。

Copy link
Contributor

@beru beru left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

多分問題無いと思います。

PRの件名や説明に書かれていないリファクタリングの変更が事前に行われてるのでちょっと確認しづらいですが、まぁ問題があれば後で直せば良いと思います。

@berryzplus
Copy link
Contributor Author

およ、不思議ですね…。

ちなみに自分がビルドしたのは 873e2db78070d3015a54f9d9aa81e97095cd9dba の icu4c/source/allinone.sln の Win32 Release です。生成物は icu4c/bin に作られました。

コミットハッシュ ⇒ 3b99d07581fb38a68b9a786abab0785b4e3d3749
使ったソリューションと出力先は同じっぽいです。
vs2017だから?・・・いや、10倍になるのは流石におかしいか。
あ、 python3 入れてないと icudt66.dll がデータを含まないダミーになるのでそれが原因かもです。

@berryzplus
Copy link
Contributor Author

多分問題無いと思います。

PRの件名や説明に書かれていないリファクタリングの変更が事前に行われてるのでちょっと確認しづらいですが、まぁ問題があれば後で直せば良いと思います。

あざっす。

やったこと全部書かないとレビューしてもらえない感じだとつらくなってきたので、敢えて説明を端折ってみてる部分もありました。何かあったら「なる早」で対応するのは、どうレビューしても変わらないはずなので、あまり負荷にならない範囲で端折っていきたいと思っています。

@beru
Copy link
Contributor

beru commented Dec 8, 2019

やったこと全部書かないとレビューしてもらえない感じだとつらくなってきたので、敢えて説明を端折ってみてる部分もありました。何かあったら「なる早」で対応するのは、どうレビューしても変わらないはずなので、あまり負荷にならない範囲で端折っていきたいと思っています。

リファクタとそれ以外でPRを分けた方がレビューする上では良かったかもですね。

@k-takata
Copy link
Member

k-takata commented Dec 8, 2019

4年くらい前、ICU 54の頃に試したときには、Data Library Customizerという機能があって、フルビルドすると数十MBのDLLが、Base Dataのみでビルドすると0.5MB程度に抑えることができました。(最新版でCustomizerが提供されているのか、されているとすれば文字コード検出のためにはどこまでデータを削れるのか…)
もし、データを削って数MB程度に抑えることができるのであれば、インストーラーに同梱するのも選択肢に入るでしょう。

あと、ICU 66はまだリリースされていないので、現時点で採用するならICU 65.1ではないでしょうか。
https://github.com/unicode-org/icu/releases/tag/release-65-1 (バイナリもちゃんと提供されているようですし)

@beru
Copy link
Contributor

beru commented Dec 8, 2019

文字コード検出の為だけにインストーラーのサイズが数MBも増えるのは富豪的な気がしますが、今の人の感覚では数MBなんてブロードリンク元社員の遵法精神より軽いかもしれないですね。

@berryzplus
Copy link
Contributor Author

レビューありがとうございます。
何か問題ありましたら別PRで対処していきたいと思います。

具体的な課題について個別対処できそうな雰囲気になってきたので、一旦マージしてしまいます。

@berryzplus berryzplus merged commit 2c6612c into sakura-editor:master Dec 8, 2019
@berryzplus berryzplus deleted the feature/add_icu4c_charsetdetector branch December 8, 2019 06:33
@berryzplus
Copy link
Contributor Author

文字コード検出の為だけにインストーラーのサイズが数MBも増えるのは富豪的な気がしますが、今の人の感覚では数MBなんてブロードリンク元社員の遵法精神より軽いかもしれないですね。

よくよく考えてみると Visual Studio 2017 のインストーラーがダウンロードするパッケージのサイズを合計すると テラバイト単位 なんですよね。そこを考えると、インターネット配布で数十MBなんてあり得ない って発想が適切なのかどうかは怪しい気がしてきます。

icu4cのバージョンアップ頻度は結構高いので、何にもしなくてもver66(未リリース)はそのうち公開されると思っています。たぶん「単一バージョンのみに対応」って方式はキッツイ感じだと思います。そこを発展させてデュアルバージョン対応にすると、他のexmoduleと乖離していくので一旦そのままにしてしまったんですが。

@beru
Copy link
Contributor

beru commented Dec 8, 2019

え、テラバイトって 1024GB ですよね?
最近になって1TBの容量のSSDの値段が1万円くらいになりましたが…。

まぁでも最近の開発環境って数10GB消費するのも珍しくないし、そのうち10TBじゃドライブの容量が足りないとかいう時代が来るんでしょうか…。

@berryzplus
Copy link
Contributor Author

ギガでしたね。

最大で40GB、ブルーレイディスク1枚にぎりぎり入るサイズだったような。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement ■機能追加
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants