Skip to content

Commit

Permalink
エラー処理を改善する
Browse files Browse the repository at this point in the history
  • Loading branch information
berryzplus committed Feb 26, 2022
1 parent ba7cb21 commit faad1e4
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 15 deletions.
60 changes: 45 additions & 15 deletions sakura_core/util/string_ex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
#include "StdAfx.h"
#include "string_ex.h"

#include <errno.h>
#include <stdarg.h>
#include <array>
#include <memory>
#include <stdexcept>

#include "charset/charcode.h"
#include "charset/codechecker.h"
Expand All @@ -36,6 +39,21 @@

int __cdecl my_internal_icmp( const char *s1, const char *s2, unsigned int n, unsigned int dcount, bool flag );

/*!
* va_list型のスマートポインタを実現するためのdeleterクラス
*/
struct vaList_ender
{
void operator()(va_list argList) const
{
va_end(argList);
}
};

//! va_list型のスマートポインタ
using vaListHolder = std::unique_ptr<std::remove_pointer<va_list>::type, vaList_ender>;


// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
// 文字 //
// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
Expand Down Expand Up @@ -253,9 +271,8 @@ int vstrprintf(std::wstring& strOut, const WCHAR* pszFormat, va_list& argList)
{
// _vscwprintf() はフォーマットに必要な文字数を返す。
const int cchOut = ::_vscwprintf(pszFormat, argList);
// 出力文字数が0なら後続処理は要らない。
if (!cchOut) {
return 0;
if (cchOut <= 0) {
return cchOut;
}

// 必要なバッファを確保する
Expand Down Expand Up @@ -295,9 +312,8 @@ int vstrprintf(std::string& strOut, const CHAR* pszFormat, va_list& argList)
{
// _vscwprintf() はフォーマットに必要な文字数を返す。
const int cchOut = ::_vscprintf(pszFormat, argList);
// 出力文字数が0なら後続処理は要らない。
if (!cchOut) {
return 0;
if (cchOut <= 0) {
return cchOut;
}

// 必要なバッファを確保する
Expand Down Expand Up @@ -374,11 +390,16 @@ int strprintf(std::string& strOut, const CHAR* pszFormat, ...)
@param[in] pszFormat フォーマット文字列
@param[in] ... 引数リスト
@returns フォーマットされた文字列
@throws invalid_argument フォーマット文字列が正しくないとき
*/
std::wstring vstrprintf(const WCHAR* pszFormat, va_list& argList)
{
// 出力バッファを確保する
std::wstring strOut;

// 戻り値が0未満ならエラーだが、再現させられないのでハンドルしない
vstrprintf(strOut, pszFormat, argList);

return strOut;
}

Expand All @@ -388,11 +409,22 @@ std::wstring vstrprintf(const WCHAR* pszFormat, va_list& argList)
@param[in] pszFormat フォーマット文字列
@param[in] ... 引数リスト
@returns フォーマットされた文字列
@throws invalid_argument フォーマット文字列が正しくないとき
*/
std::string vstrprintf(const CHAR* pszFormat, va_list& argList)
{
// 出力バッファを確保する
std::string strOut;
vstrprintf(strOut, pszFormat, argList);

// 戻り値が0未満ならエラー
if (const int nRet = vstrprintf(strOut, pszFormat, argList);
0 > nRet)
{
std::array<char, 1024> msg;
::strerror_s(msg.data(), msg.size(), nRet);
throw std::invalid_argument(msg.data());
}

return strOut;
}

Expand All @@ -402,17 +434,16 @@ std::string vstrprintf(const CHAR* pszFormat, va_list& argList)
@param[in] pszFormat フォーマット文字列
@param[in] ... 引数リスト
@returns フォーマットされた文字列
@throws invalid_argument フォーマット文字列が正しくないとき
*/
std::wstring strprintf(const WCHAR* pszFormat, ...)
{
va_list argList;
va_start(argList, pszFormat);

const auto strOut = vstrprintf(pszFormat, argList);

va_end(argList);
vaListHolder holder(argList);

return strOut;
return vstrprintf(pszFormat, argList);
}

/*!
Expand All @@ -421,17 +452,16 @@ std::wstring strprintf(const WCHAR* pszFormat, ...)
@param[in] pszFormat フォーマット文字列
@param[in] ... 引数リスト
@returns フォーマットされた文字列
@throws invalid_argument フォーマット文字列が正しくないとき
*/
std::string strprintf(const CHAR* pszFormat, ...)
{
va_list argList;
va_start(argList, pszFormat);

const auto strOut = vstrprintf(pszFormat, argList);
vaListHolder holder(argList);

va_end(argList);

return strOut;
return vstrprintf(pszFormat, argList);
}

// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- //
Expand Down
21 changes: 21 additions & 0 deletions tests/unittests/test-string_ex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include <tchar.h>
#include <Windows.h>

#include <stdexcept>

#include "basis/primitive.h"
#include "util/string_ex.h"

Expand Down Expand Up @@ -238,6 +240,25 @@ TEST(string_ex, strprintfA_small_output)
EXPECT_STREQ("1234567890123456", text.c_str());
}

/*!
@brief 独自定義のフォーマット関数(C-Style風)。
Cロケールを設定し忘れた場合、SJISバイナリから標準文字列への変換は失敗する。
テスト作成時に混乱する可能性があるので、例外を投げるようにしてある。
CRT関数が「フォーマットが不正ならクラッシュさせる」という設計なので、
フォーマットチェック機構としては役立たずである点に注意すること。
*/
TEST(string_ex, strprintfA_throws)
{
// Cのロケールを設定し忘れた場合、エラーが返る
setlocale(LC_ALL, "English");
EXPECT_THROW(strprintf("%ls", L"てすと"), std::invalid_argument);

// Cのロケールを日本語にした場合、正しく変換できる
setlocale(LC_ALL, "Japanese");
EXPECT_STREQ("てすと", strprintf("%ls", L"てすと").data());
}

/*!
@brief 独自定義の文字列比較関数。
*/
Expand Down

0 comments on commit faad1e4

Please sign in to comment.