-
Notifications
You must be signed in to change notification settings - Fork 168
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
ファイルを開く、で _MAX_PATH (260) より長いパスのファイルの場合はエラーメッセージを出して処理を中断 #409
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
対応ありがとうございます。LGTMです。
例によって、主題と関係ないツッコミがいくつかあるので、適宜課題化するなりスルーするなりで進めていきたい感じです。
@@ -136,6 +136,16 @@ void CViewCommander::Command_FILEOPEN( const WCHAR* filename, ECodeType nCharCod | |||
); | |||
if(!bDlgResult)return; | |||
|
|||
for(size_t i = 0; i < files.size(); i++ ){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::for_eachで書くのとfor文で書くのとどちらが見やすいですかねぇ。
他と合わせるなら
for(int I =0; I<file.size(); I++)
と書いてsignedとunsignedの比較で怒られるパターンだと思います。
サイズ値にはintで十分なものとそうでないものがあると思っていますが、これの場合前者だと思います。
「ファイルを開く」ダイアログで2億ファイルを選択できるか?ってことです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::for_eachで書くのとfor文で書くのとどちらが見やすいですかねぇ。
std::for_eachで書く場合はFunctorとかLambda functionと組み合わせる事になると思うので読みにくくなると思います。
Range-based for loop が見た目が一番すっきりすると思いますが、自分がRange-based for loopを書きなれていないので読みにくいです。
再起とかで無理やり処理するのは書きにくいし読みにくいです。数を限定してFall-throughなswitch文で書く方法も出来そうですが…。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あまりc++やらない人のためにc++のforeachの例を書くとこんなんです。
std::for_each(files.cbegin(), files.cend(),
[] (const auto& file) { // ←繰り返す処理をラムダ式で指定している
...
});
たしかにちょっと見辛いかも知れませんね。
「いちばんすっきりする」という C++11の 範囲 forだとこんなんになります。
for (const auto& file : files) {
... // ← 普通のfor文と同じに書ける
}
すっきりしすぎてて違う言語みたくなってますが、
実はこれ、昔から使える定石パターンを生成するだけの糖衣構文らしいです。
for (const auto &iter = files.cbegin(); iter != files.cend(); ++iter) {
const auto &file = *iter;
...
}
ちなみに、自分はこの書き方が好きです。
「それ、std::for_eachじゃないじゃんw」ってツッコミはスルーします。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for (const auto &iter = files.cbegin(); iter != files.cend(); ++iter) {
const auto &file = *iter;
...
}
この書き方ですが実際には、
for (auto it = files.cbegin(); it != files.cend(); ++it) {
auto &file = *it;
...
}
になると思います。
便利な Iterator ですが自分はstaticおじさん指向なので出来るだけ使用を回避しています。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この書き方ですが実際には、
実用コードになると色々変形すると思ってます。
auto beg = files.begin(); // 開始位置を記憶
auto end = files.end(); // 終了位置を記憶
for (auto it = beg; it != end; ++it) {
auto file = *it; // 変更できないのは嫌なのでconst外しちゃう
auto idx = it - beg; // 「staticおじさん」はおおむね配列思考
...
}
こんなんするくらいなら
for (int i = 0; i < files.size(); i++)
でよくね?
って見方は分からんでもないです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
きっとループの書き方が将来のC++では何十種類もバリエーションが増えて、いつかシンプルなgotoが評価される日が来ると思います。
for(size_t i = 0; i < files.size(); i++ ){ | ||
if (files[i].length() >= _MAX_PATH){ | ||
ErrorMessage( | ||
CEditWnd::getInstance()->GetHwnd(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
このカスタム関数の第一引数は省略可能です。
省略した場合は CEditWnd::getinstance()->GetWnd()
になります。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
省略可能というのは、オーバーロードが有るわけでは無くて NULL 指定したら、って事のようですね。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
そうです。省略(=NULLを指定)しても同じ動きになります。
ここに CEditWnd::getinstance()->GetWnd()
を書いてしまうと、
この関数を単体テストするときに CEditWnd
のインスタンスが必須になります。
NULL 指定にしておけば ErrorMessage
自体をマクロで置き換えたりして、
コード単体での動作検証がラクになります。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
現状ではGUI絡むところは単体テスト書かれてないみたいですね。
単体テスト記述する時になってから手直しすれば良いかなぁと思います。
ErrorMessage( | ||
CEditWnd::getInstance()->GetHwnd(), | ||
LS(STR_ERR_FILEPATH_TOO_LONG), | ||
files[i].c_str() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
複数のファイルを開こうとしてうち1つが制限にかかった場合、制限にかかったファイル名のみが表示されそうな書き方です。いったんはこれで問題ないと考えますが、他のファイルは処理しなくていいんでしたっけ?という細かいツッコミ。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ファイルダイアログで同じフォルダにあるファイルを複数選択して開こうとすると下記のメッセージが表示されました。
[Window Title]
ファイルを開く
[Content]
複数の項目の選択は、項目がすべて同じフォルダーにある場合にのみできます。
[OK]
適切なエラーメッセージじゃないと思います。OS側の対応が不十分ですし、とりあえず1つでも制限に引っかかったらまとめて却下という対応でも良いかなと判断しました。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
適切なエラーメッセージじゃないと思います。
Documents
みたいな仮想フォルダでフォルダを跨いだファイル選択すると再現可能ですね・・・。
これはこれで正しい気がしています。
OS側として「ファイルを開く」で選択される複数ファイルは、同じディレクトリに存在している前提なので、どのファイルが他と違う、というより、選択方法に誤りがある、を指摘したいんだと思うからです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
同じフォルダにあるファイルを複数選択した場合(そしてその中の1つ以上のファイル名が MAX_PATH を超えて長い特殊例)なのに、そのエラーメッセージが出てしまうので不適切だと思っています。天に唾してもしょうがないのですが…。
>> どのファイルが他と違う、というより、選択方法に誤りがある、を指摘したいんだと思うからです。
複数の項目は全て同じフォルダーにあるのに、そうなってないよ、というエラーメッセージが出るので、おかしい、と言っています。なんか話が噛み合ってない気がしますが、限りなく黒に近いグレーに細かいツッコミをしてはいけないという事でしょうか…。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
何の話してたかようやく把握です。
それはおかしいw
(複数ファイル選択のうち1つがMAX_PATHを超えたときに「フォルダが違う」と言われる)
なんか話が噛み合ってない気がしますが、限りなく黒に近いグレーに細かいツッコミをしてはいけないという事でしょうか…。
理解できてませんでした。
ぼく基本スペックはアフォなので。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
そもそも MAX_PATH を超えるようなファイルを扱うユーザーが悪いんですよね。そんな事言ったらこのPRの意味 Nothing ですが…。
); | ||
return; | ||
} | ||
} | ||
sLoadInfo.cFilePath = files[0].c_str(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
本質的にはここの左辺の型の問題なんですよね。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
左様です。
@@ -4121,6 +4121,8 @@ GDI リソース\t残り %d%%\n\n" | |||
STR_FILETREE_REPLACE_PATH_FROM "置換元パスを指定してください" | |||
STR_FILETREE_REPLACE_PATH_TO "置換先文字列を指定してください" | |||
|
|||
STR_ERR_FILEPATH_TOO_LONG "%ls\nというファイルを開けません。\nファイルのパスが長すぎます。" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%ls
なんですね。
プロジェクト標準的には %ts
だと思っています。
個人的には %s
でよいと考えております。
ちらっと思ったことですが、このメッセージってwindows標準でありませんでしたっけ?(ちゃんと調べてないですが)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%ls
とか %ts
とか良く分からなくてコピペしてました。
こんなページに遭遇しました。
https://sourceforge.net/p/sakura-editor/wiki/%E4%B8%8D%E5%AE%89%E7%AE%87%E6%89%80/
sourceforge側のWikiに結構色々なページがあるのでgithub側に移行した方が良さそうですね。
https://sourceforge.net/p/sakura-editor/wiki/browse_pages/?limit=250
ちらっと思ったことですが、このメッセージってwindows標準でありませんでしたっけ?(ちゃんと調べてないですが)
FormatMessage に ERROR_FILENAME_EXCED_RANGE を渡して取ってくると良いかも知れないですね。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
独自記法 %ts
の発生経緯については把握しています。
UNICODE 一本化により存在意義が薄れた認識です。
今後、auto_sprintf(char*, char*, ...)
をwchar_t*版に置き換える活動を画策していて、
それが終わったら s/%ts/%s/g
の全置換を行いたいと考えています。
その後、auto_sprintf(wchar_t*, wchar_t*, ...)
の内部で使っているCRT関数を
sprintf_s → sprintf_p として言語によって埋め文字の位置が変わるケースに対応したいです。
FormatMessage に ERROR_FILENAME_EXCED_RANGE を渡して取ってくると良いかも知れないですね。
あとで検証してみまっす 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto_sprintf を整備する場合は、出力先が固定長配列の場合のオーバーロードを用意して、配列要素数を引数に記述しないでも良くなると良いですね。
ソースコードの規模が大きいのでリファクタ色々しても焼け石に水的な感じはありますが…。
@@ -4132,6 +4132,9 @@ GDI Resource\tRemaining %d%%\n\n" | |||
STR_FILETREE_REPLACE_PATH_FROM "Please Input Replace 'From' Path" | |||
STR_FILETREE_REPLACE_PATH_TO "Please Input Replace 'To' Path" | |||
|
|||
STR_ERR_FILEPATH_TOO_LONG "'%ts'\nCannot open the file.\nThe filepath is too long." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%ts
なんですね・・・。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
英語メッセージではファイルパスをシングルクォートで囲っているけれど、日本語メッセージでは囲っていないという違いもありますね。
これってなんでマージしないんでしたっけ。 |
PR出した 当人が Merge はどうかなと思うので自分ではやってません。 |
う、反応が無いですね。 このまま放置しててもしょうがないので自分で Merge してしまいます。 |
ここ最近忙しかったので、流してしまいました。
ぼくは GitHub の文化にはあまり詳しくないんですけど、 他プロジェクトもちょこちょこ見てるんですが、 |
ファイルを開く、で _MAX_PATH (260) より長いパスのファイルの場合はエラーメッセージを出して処理を中断
#401 で検討中ですが、アプリが落ちないようにする対策を入れました。
本当は扱えるようにした方が良いですがすぐには直せないので暫定的な対応です。