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

[WIP] CDataProfileの通常変換からStaticStringを切り離す #1150

Closed

Conversation

berryzplus
Copy link
Contributor

PR の目的

CDataProfileの通常のデータ変換からStaticStringを切り離し、変換対象を分かりやすくします。

カテゴリ

  • その他
    ※戻り値の意味を追加したので、リファクタリングではありません。

PR の背景

CDataProfile はデータ変換クラスです。

変換に対応する型は IODataProfile のコメントにリストされている通りです。

/*!
* 設定値の入出力テンプレート
*
* 標準stringを介して設定値の入出力を行う。
*/
template <class T> //T=={bool, int, WORD, wchar_t, char, StringBufferW, StaticString}
bool IOProfileData(
const WCHAR* pszSectionName, //!< [in] セクション名
const WCHAR* pszEntryKey, //!< [in] エントリ名
T& tEntryValue //!< [in,out] エントリ値
) noexcept

変換に対応する型の中に、他と違う特性を持った型が2つあります。

  • StaticString<WCHAR, N> 変換対象型の中で唯一、テンプレートパラメータ要求する型です。
  • StringBufferW この型は typedef const StringBufferW_ StringBufferW; です(const型です)。

いずれも「文字列」を格納する型なので、ある意味で「無変換」です。
std::wstring とは異なり、バッファにサイズ上限があるので、
無変換でも「変換失敗」が起こりうるため「変換が必要」という奇妙な存在です。

今回は先に、StaticString<WCHAR, N> を通常変換から切り離します。

型がテンプレートパラメータを要求するということは、
「intやboolとは同列に扱えない」ということでもあります。

IOProfileData のオーバーロードテンプレートを用意して、
通常の入出力テンプレートから切り離します。
これにより、通常の入出力テンプレートが対応する変換型は
テンプレートパラメータを要求しない型のみとなります。

PR のメリット

  • ‘StaticString<WCHAR,N>` を切り離すことで通常の入出力テンプレートが分かりやすくなります。
  • ‘StaticString<WCHAR,N>` の変換処理が、他の型変換とは異なることが明確になります。
  • ‘IOProfileData‘ の戻り値で ‘StaticString<WCHAR,N>` を正しく読み込めたか判断できるようになります。
    • 変更前は桁溢れ時もtrueを返していました。
    • 変更後は桁溢れ時にfalseを返すようになります。
    • 変換失敗時(=桁溢れ)を検出できるようになります。
    • 変換失敗時(=桁溢れ)でも読める分だけのデータを読み込むのは変更前と同じです。

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

  • とくにありません。

PR の影響範囲

  • アプリ(=サクラエディタ)の機能に影響はありません。
  • 修正箇所は、共有メモリに格納する設定値(文字列型)の読み書き処理です。

関連チケット

参考資料

変換対象型の中で唯一、StaticStringだけがテンプレートパラメータを要求する。

この特徴をもって「intやboolと同列に扱えない型」と解釈して他と分離しておく。
@AppVeyorBot
Copy link

if( IOProfileData( pszSectionName, pszEntryKey, buf ) ){
//StaticString<WCHAR, N>に変換
szEntryValue = buf.c_str();
ret = buf.length() < _countof2(szEntryValue);
Copy link
Member

Choose a reason for hiding this comment

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

buf.length()_countof2(szEntryValue) は逆だったりしないですか?
単体テストが欲しい感じですね。

Copy link
Contributor Author

Choose a reason for hiding this comment

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

書くとこマチガッタ...

buf.length()_countof2(szEntryValue) は逆だったりしないですか?
単体テストが欲しい感じですね。

あるあるですねw
buf.length() = 代入しようとする文字列の文字列長(NUL終端含まない)
_countof2(szEntryValue) = 代入先バッファのサイズ(NUL終端含む)
で、「代入する文字列がバッファに収まったらtrue」としたいので合っています。

I/Oクラスなので単体テストを投入するとテスト所要時間が延びます。
CProfile側のチューニング(たぶん、パフォーマンスに難がある)もまだなので
単体テスト投入はギリギリまで先延ばししたいと思っています。

m-tmatma
m-tmatma previously approved these changes Jan 13, 2020
@KENCHjp KENCHjp added no-changelog 【ChangeLog除外】 specification change ■仕様変更 labels Jan 13, 2020
@m-tmatma
Copy link
Member

これは仕様変更ではなくリファクタリングだと思います

@KENCHjp
Copy link
Member

KENCHjp commented Jan 14, 2020

内部仕様変更と外部仕様変更(対チェンジログといういみで)とに分けた方がラベル付けは簡単な気もしてますが、ラベルにこだわる必要もあまりない気もしていて、とりあえずラベル付けられてないものを付けている格好です。
冒頭に「リファクタリングではない」との記載があったので、仕様変更にしてみましたが、リファクタリングでもかまいません。

//文字列読み込み
if( IOProfileData( pszSectionName, pszEntryKey, buf ) ){
//StaticString<WCHAR, N>に変換
szEntryValue = buf.c_str();
Copy link
Contributor

Choose a reason for hiding this comment

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

szEntryValue = buf.c_str();って要はwcscpy_sですよね。
これって従来のコメントの通り、_set_invalid_parameter_handlerを設定しないかぎり「後ろを切り詰める」わけでもなくabort/exitしますよね、確か。
その辺はどうする予定なんでしたっけ。

void Assign(const CHAR_TYPE* src){ if(!src) m_szData[0]=0; else wcscpy_s(m_szData,_countof(m_szData),src); }
Me& operator = (const CHAR_TYPE* src){ Assign(src); return *this; }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ncpyのtruncateに変えたいです。

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ncpyのtruncateに変えたいです。

このコメント残しておくと誤解が生まれそうなので補足します。

ここの意図は、 StaticString<WCHAR,N>::operator = (const WCHAR*) を呼び出した結果で、桁あふれabortが発生しないようにしたいってことです。

そうするために、(wcs)ncpy に文字数 _TRUNCATE を指定するようにしたいと言ってます。

どちらかと言うと、先に「設定ファイル読み取りの失敗を検知できるようにしたい」の issue を立てて CDataProfile の アーキテクチャ変更を進めていくのがよいかな、と思っています。

@berryzplus
Copy link
Contributor Author

せっかくapprove 頂きましたが、単なるリファクタリングに留まるように修正入れたいと思います。たぶん深夜に。

@berryzplus berryzplus changed the title CDataProfileの通常変換からStaticStringを切り離す [WIP] CDataProfileの通常変換からStaticStringを切り離す Jan 14, 2020
@berryzplus berryzplus changed the title [WIP] CDataProfileの通常変換からStaticStringを切り離す CDataProfileの通常変換からStaticStringを切り離す Jan 14, 2020
template <int N>
void profile_to_value(const wstring& profile, StaticString<WCHAR, N>* value)
{
wcscpy_s(value->GetBufferPointer(),value->GetBufferCount(),profile.c_str());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

う~ん。これ、abortするなぁ・・・。

//StringBufferW
void profile_to_value(const wstring& profile, StringBufferW* value)
{
wcscpy_s(value->pData,value->nDataCount,profile.c_str());
}

これもやっぱり abort するなぁ・・・。

#1145 でコメント消したの失敗だったかなぁ・・・。

変更をやめてリファクタリング(=処理は変えない)にしようと思ったのは、
現状で問題のないコードを問題ある感じにするのはまずい、と思ったからでした。

なんとなく、 wcsncpy_s + _TRUNCATE で「強制切り捨て」にする文化なのかと思っていましたが、思い違いで思い込んでたみたいです。

この辺を踏まえて、追加の修正をしようと思います。

Copy link
Contributor

Choose a reason for hiding this comment

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

僕もabortで処理するのは最終手段で安全側に倒した結果であるのは理解していますけど、それがテキストエディタに求められるものかと言われると、ちょっと。
要するに起動中にデータが壊れていて設定ファイルに長いデータが一か所でも書き込まれていたら、次回コントロールプロセスが起動中に死亡して、iniを削除しないかぎりエディタとして完全に死ぬということなので。
必要な範囲で、_TRANCATE系で無視するか、エラーを検出してデフォルト値を書き戻すようにするとか、対応がそれぞれあったほうが、より好ましいと思っています。
この辺は、もともとがいい加減だっただけで、新しい方針があるなら、それでいいと思います。

@AppVeyorBot
Copy link

@berryzplus berryzplus changed the title CDataProfileの通常変換からStaticStringを切り離す [WIP] CDataProfileの通常変換からStaticStringを切り離す Jan 18, 2020
@berryzplus
Copy link
Contributor Author

IODataProfileのコメント修正を先に済ませたいので一旦保留。

@berryzplus
Copy link
Contributor Author

TODO: issue立てて、全体として何をどうしたいかが分かるようにする。

@berryzplus
Copy link
Contributor Author

やりたいことの最終目標に関しての issue を立てました。

#1188 設定項目がなかったらデフォルト設定を使うようにしたい

で、当座の作業としては、設定が読み込めなかったことを検知する機能をCDataProfileに組み込みたいってことなんで、それが分かる感じのサブissueを立てたいと思っています。

しっくり来るissueタイトルが思いつかないので、今日は諦めて祝日(=建国記念日)に向けて考える感じっす。

@berryzplus
Copy link
Contributor Author

このPRの変更内容は評価のしようがないと思うので #1363 でやってるプレ・スモークテストの課題が解決してからの導入としたいです。

@berryzplus
Copy link
Contributor Author

モチベーションが尽きたので閉じてしまいます。 #1394

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no-changelog 【ChangeLog除外】 specification change ■仕様変更
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants