Skip to content

Commit 0bda859

Browse files
authored
Merge pull request #2191 from berryzplus/feature/omit_is_bad_string_ptr
IsBadStringPtrAの呼出を除去する
2 parents eda9b45 + c207a80 commit 0bda859

File tree

9 files changed

+204
-69
lines changed

9 files changed

+204
-69
lines changed

sakura_core/_main/global.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "StdAfx.h"
1919
#include "_main/global.h"
2020

21+
#include "_main/CCommandLine.h"
2122
#include "_main/CNormalProcess.h"
2223
#include "basis/CErrorInfo.h"
2324
#include "config/app_constants.h"
@@ -55,6 +56,15 @@ HINSTANCE G_AppInstance()
5556
return CProcess::getInstance()->GetProcessInstance();
5657
}
5758

59+
/*!
60+
* 起動時に指定されたプロファイル名を取得する
61+
*/
62+
LPCWSTR GetProfileName() noexcept
63+
{
64+
const auto cmdline = CCommandLine::getInstance();
65+
return cmdline ? cmdline->GetProfileName() : L"";
66+
}
67+
5868
/*!
5969
* コンストラクタ
6070
*/

sakura_core/_main/global.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,4 +170,7 @@ struct SSearchOption{
170170
};
171171

172172
HINSTANCE G_AppInstance();
173+
174+
LPCWSTR GetProfileName() noexcept;
175+
173176
#endif /* SAKURA_GLOBAL_BD124BE7_A850_41F3_9F5D_8A4F0E45A4C9_H_ */

sakura_core/env/CShareData.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ bool CShareData::InitShareData()
113113

114114
/* ファイルマッピングオブジェクト */
115115
{
116-
const auto pszProfileName = CCommandLine::getInstance()->GetProfileName();
116+
const auto pszProfileName = GetProfileName();
117117
std::wstring strShareDataName = GSTR_SHAREDATA;
118118
strShareDataName += pszProfileName;
119119
m_hFileMap = ::CreateFileMapping(

sakura_core/macro/CPPA.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,24 @@ void __stdcall CPPA::stdStrObj(const char* ObjName, int Index, BYTE GS_Mode, int
299299
}
300300
}
301301

302+
/*!
303+
* CPPAエラー情報コールバックをテストできるようI/Fを公開する関数。
304+
*
305+
* 既存コードをできるだけ改変せずにテストできるよう作成。
306+
* 可能であれば、そのうち消す。
307+
*/
308+
/* static */ void CPPA::CallErrorProc(PpaExecInfo& info, int Err_CD, _In_opt_z_ LPCSTR Err_Mes)
309+
{
310+
// PPA実行情報をセットする
311+
m_CurInstance = &info;
312+
313+
// CPPAエラー情報コールバックを呼び出す
314+
stdError(Err_CD, Err_Mes);
315+
316+
// PPA実行情報をクリアする
317+
m_CurInstance = nullptr;
318+
}
319+
302320
/*! ユーザー定義関数のエラーメッセージの作成
303321
304322
stdProc, stdIntFunc, stdStrFunc がエラーコードを返した場合、PPAから呼び出される。
@@ -346,9 +364,8 @@ void __stdcall CPPA::stdError( int Err_CD, const char* Err_Mes )
346364
auto_sprintf( szMes, LS(STR_ERR_DLGPPA3), FuncID );
347365
}
348366
}else{
349-
// 2007.07.26 genta : ネスト実行した場合にPPAが不正なポインタを渡す可能性を考慮.
350-
// 実際には不正なエラーは全てPPA.DLL内部でトラップされるようだが念のため.
351-
if( IsBadStringPtrA( Err_Mes, 256 )){
367+
if( !Err_Mes ){
368+
// "エラー情報が不正"
352369
pszErr = LS(STR_ERR_DLGPPA6);
353370
}else{
354371
switch( Err_CD ){

sakura_core/macro/CPPA.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -252,21 +252,24 @@ class CPPA : public CDllImp {
252252
// メンバ変数
253253
char m_szMsg[80]; //!< CPPAからのメッセージを保持する
254254

255+
public:
255256
// 2007.07.26 genta : PPAのネストを許容するために,別データ構造とする.
256257

257258
struct PpaExecInfo {
258-
CNativeA m_cMemRet; //!< コールバックからDLLに渡す文字列を保持
259-
CEditView* m_pcEditView; // 2003.06.01 Moca
260-
DLLSHAREDATA* m_pShareData; // 2003.06.01 Moca
261-
bool m_bError; //!< エラーが2回表示されるのを防ぐ 2003.06.01 Moca
262-
CNativeA m_cMemDebug; //!< デバッグ用変数UserErrorMes 2003.06.01 Moca
259+
CNativeA m_cMemRet = ""; //!< コールバックからDLLに渡す文字列を保持
260+
CEditView* m_pcEditView = nullptr; // 2003.06.01 Moca
261+
DLLSHAREDATA* m_pShareData = nullptr; // 2003.06.01 Moca
262+
bool m_bError = false; //!< エラーが2回表示されるのを防ぐ 2003.06.01 Moca
263+
CNativeA m_cMemDebug = ""; //!< デバッグ用変数UserErrorMes 2003.06.01 Moca
263264
/** オプションフラグ
264265
265266
CEditView::HandleCommand()にコマンドと一緒に渡すことで
266267
コマンドの素性を教える.
267268
*/
268-
int m_commandflags; //!<
269+
int m_commandflags = 0;
269270
};
271+
272+
private:
270273
// 2007.07.26 genta : 現在実行中のインスタンス
271274
static PpaExecInfo* m_CurInstance;
272275
//PPAの多重起動禁止 2008.10.22 syat
@@ -276,5 +279,9 @@ class CPPA : public CDllImp {
276279
static struct MacroFuncInfo S_Table[];
277280
static int m_nFuncNum; // SAKURAエディタ用関数の数
278281
*/
282+
283+
public:
284+
static void CallErrorProc(PpaExecInfo& info, int Err_CD, _In_opt_z_ LPCSTR Err_Mes);
279285
};
286+
280287
#endif /* SAKURA_CPPA_FB41BBAE_DFBC_449D_9342_5D9424CFE086_H_ */

sakura_core/util/relation_tool.cpp

Lines changed: 62 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,38 +11,53 @@
1111
// CSubject //
1212
// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
1313

14-
CSubject::CSubject()
15-
{
16-
}
14+
CSubject::CSubject() = default;
1715

1816
CSubject::~CSubject()
1917
{
2018
//リスナを解除
21-
for(int i=0;i<(int)m_vListenersRef.size();i++){
22-
m_vListenersRef[i]->Listen(nullptr);
19+
while (!m_vListenersRef.empty()) {
20+
_RemoveListener(m_vListenersRef.back());
2321
}
24-
m_vListenersRef.clear();
2522
}
2623

24+
/*!
25+
* リスナーを追加する
26+
*/
2727
void CSubject::_AddListener(CListener* pcListener)
2828
{
29+
//NULLは追加できない
30+
assert(pcListener);
31+
2932
//既に追加済みなら何もしない
30-
for(int i=0;i<(int)m_vListenersRef.size();i++){
31-
if(m_vListenersRef[i]==pcListener){
32-
return;
33-
}
33+
if (auto found = std::find(m_vListenersRef.cbegin(), m_vListenersRef.cend(), pcListener); found != m_vListenersRef.cend()) {
34+
return;
3435
}
36+
3537
//追加
3638
m_vListenersRef.push_back(pcListener);
3739
}
3840

39-
void CSubject::_RemoveListener(CListener* pcListener)
41+
/*!
42+
* リスナーを削除する
43+
*/
44+
void CSubject::_RemoveListener(CListener* pcListener) noexcept
4045
{
46+
//NULLは追加できないので、削除も想定しない
47+
assert(pcListener);
48+
49+
//削除前のリスナー数を記録
50+
const auto llisteners = m_vListenersRef.size();
51+
4152
//配列から削除
42-
for(int i=0;i<(int)m_vListenersRef.size();i++){
43-
if(m_vListenersRef[i]==pcListener){
44-
m_vListenersRef.erase(m_vListenersRef.begin()+i);
45-
break;
53+
if (auto found = std::find(m_vListenersRef.begin(), m_vListenersRef.end(), pcListener); found != m_vListenersRef.end()) {
54+
//確実に解除するため、リスナー側の終了メソッドを呼び出す
55+
pcListener->_EndListen();
56+
57+
//リスナー数が代わってないときだけ削除に進む
58+
if (llisteners == m_vListenersRef.size()) {
59+
//リスナー配列から削除
60+
m_vListenersRef.erase(found);
4661
}
4762
}
4863
}
@@ -51,31 +66,48 @@ void CSubject::_RemoveListener(CListener* pcListener)
5166
// CListener //
5267
// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
5368

54-
CListener::CListener()
55-
: m_pcSubjectRef(nullptr)
56-
{
57-
}
69+
CListener::CListener() = default;
5870

5971
CListener::~CListener()
6072
{
61-
Listen(nullptr);
73+
_EndListen();
6274
}
6375

64-
CSubject* CListener::Listen(CSubject* pcSubject)
76+
/*!
77+
* 監視を開始する
78+
*/
79+
CSubject* CListener::Listen(
80+
CSubject* pcSubject //!< [in] 監視するサブジェクト。NULLで監視終了
81+
)
6582
{
66-
CSubject* pOld = GetListeningSubject();
83+
//操作前の参照を取得
84+
auto pOld = GetListeningSubject();
6785

68-
//古いサブジェクトを解除
69-
if(m_pcSubjectRef){
70-
m_pcSubjectRef->_RemoveListener(this);
71-
m_pcSubjectRef = nullptr;
72-
}
86+
//古いサブジェクトを解放
87+
_EndListen();
7388

7489
//新しく設定
75-
m_pcSubjectRef = pcSubject;
76-
if(m_pcSubjectRef){
77-
m_pcSubjectRef->_AddListener(this);
90+
if (pcSubject) {
91+
//サブジェクト側にリスナー追加を要求する
92+
pcSubject->_AddListener(this);
93+
94+
//参照を保存
95+
m_pcSubjectRef = pcSubject;
7896
}
7997

8098
return pOld;
8199
}
100+
101+
/*!
102+
* 監視を終了する
103+
*/
104+
void CListener::_EndListen() noexcept
105+
{
106+
if (auto pcSubject = m_pcSubjectRef) {
107+
//構造的に再帰呼出なので、先に参照を消しておく
108+
m_pcSubjectRef = nullptr;
109+
110+
//サブジェクト側にリスナー削除を要求する
111+
pcSubject->_RemoveListener(this);
112+
}
113+
}

sakura_core/util/relation_tool.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class CSubject{
3636
public:
3737
//管理用
3838
void _AddListener(CListener* pcListener);
39-
void _RemoveListener(CListener* pcListener);
39+
void _RemoveListener(CListener* pcListener) noexcept;
4040

4141
private:
4242
std::vector<CListener*> m_vListenersRef;
@@ -58,8 +58,11 @@ class CListener{
5858
CSubject* Listen(CSubject* pcSubject); //!< 直前にウォッチしていたサブジェクトを返す
5959
CSubject* GetListeningSubject() const{ return m_pcSubjectRef; }
6060

61+
//管理用
62+
void _EndListen() noexcept;
63+
6164
private:
62-
CSubject* m_pcSubjectRef;
65+
CSubject* m_pcSubjectRef = nullptr;
6366
};
6467

6568
template <class LISTENER> class CSubjectT : public CSubject{

tests/unittests/test-cppa.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88

99
#include "macro/CPPA.h"
1010

11+
#include "doc/CEditDoc.h"
12+
#include "env/CShareData.h"
13+
#include "macro/CSMacroMgr.h"
14+
#include "view/CEditView.h"
15+
16+
#include "eval_outputs.hpp"
17+
1118
/*!
1219
CPPA::GetDllNameImpのテスト
1320
*/
@@ -76,3 +83,73 @@ TEST(CPPA, GetDeclarations)
7683
cPpa.GetDeclarations(funcInfo8, buffer.data());
7784
EXPECT_STREQ("function S_Func4(i0: Integer; s1: string; i2: Integer; s3: string; i4: Integer; s5: string; i6: Integer; s7: string): string; index 8;", buffer.data());
7885
}
86+
87+
/*!
88+
* CPPAエラー情報コールバックのテスト
89+
*
90+
* 実装が想定するメッセージを出力できるかチェックする
91+
* 本来は確認ケースを分割すべきだが、初期化に手間がかかるため1つにまとめている
92+
*/
93+
TEST(CPPA, ppaErrorProc)
94+
{
95+
// 共有メモリのインスタンスを生成する
96+
const auto pcShareData = std::make_unique<CShareData>();
97+
98+
// 共有メモリを初期化する
99+
pcShareData->InitShareData();
100+
101+
// ドキュメントの初期化前に文字幅キャッシュの生成が必要
102+
SelectCharWidthCache(CWM_FONT_EDIT, CWM_CACHE_SHARE);
103+
InitCharWidthCache(GetDllShareData().m_Common.m_sView.m_lf);
104+
105+
// CEditViewをインスタンス化するにはドキュメントのインスタンスが必要
106+
const auto pcEditDoc = std::make_unique<CEditDoc>(nullptr);
107+
108+
// CEditViewを用意する
109+
const auto pcEditView = std::make_unique<CEditView>();
110+
111+
// SMacroMgrを用意する
112+
const auto pcSMacroMgr = std::make_unique<CSMacroMgr>();
113+
114+
// PPA実行情報を用意する
115+
CPPA::PpaExecInfo info{};
116+
info.m_pShareData = &GetDllShareData();
117+
info.m_pcEditView = pcEditView.get();
118+
119+
// 既にエラーフラグが立っていたらメッセージは出さない
120+
info.m_bError = true;
121+
CPPA::CallErrorProc(info, int(F_FILENEW) + 1, nullptr);
122+
123+
// コマンドエラー
124+
info.m_bError = false;
125+
EXPECT_ERROUT(CPPA::CallErrorProc(info, int(F_FILENEW) + 1, nullptr), L"関数の実行エラー\nprocedure S_FileNew; index 30101;");
126+
127+
// 関数エラー
128+
info.m_bError = false;
129+
EXPECT_ERROUT(CPPA::CallErrorProc(info, int(F_GETFILENAME) + 1, nullptr), L"関数の実行エラー\nfunction S_GetFilename: string; index 40001;");
130+
131+
// 不明な関数エラー
132+
info.m_bError = false;
133+
EXPECT_ERROUT(CPPA::CallErrorProc(info, 1 + 1, nullptr), L"不明な関数の実行エラー(バグです)\nFunc_ID=1");
134+
135+
// エラー情報が不正
136+
info.m_bError = false;
137+
EXPECT_ERROUT(CPPA::CallErrorProc(info, 0, nullptr), L"エラー情報が不正");
138+
139+
// 詳細不明のPPAエラー
140+
info.m_bError = false;
141+
EXPECT_ERROUT(CPPA::CallErrorProc(info, 0, ""), L"詳細不明のエラー");
142+
143+
// 詳細ありのPPAエラー
144+
info.m_bError = false;
145+
EXPECT_ERROUT(CPPA::CallErrorProc(info, 0, "test"), L"test");
146+
147+
// 未定義のエラー
148+
info.m_bError = false;
149+
EXPECT_ERROUT(CPPA::CallErrorProc(info, -1, "test"), L"未定義のエラー\nError_CD=-1\ntest");
150+
151+
// デバッグ情報付きのエラー
152+
info.m_cMemDebug = "debug";
153+
info.m_bError = false;
154+
EXPECT_ERROUT(CPPA::CallErrorProc(info, 0, nullptr), L"エラー情報が不正\ndebug");
155+
}

0 commit comments

Comments
 (0)