/*---------------------------------------------------------------------------* Project: Horizon File: Result.h Copyright (C)2009 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 33694 $ *---------------------------------------------------------------------------*/ /*! @file @brief Result クラスの宣言 :include nn/Result.h */ #ifndef NN_RESULT_H_ #define NN_RESULT_H_ #include #include //------------------------------------------------------------------- // for C / C++ /*! @addtogroup nn_root @{ */ /*! @defgroup nn_Result_c Result (C) @brief 処理の結果を示すnn::ResultのC インタフェースモジュールです。 @{ */ #ifdef __cplusplus extern "C" { #endif // ifdef __cplusplus /*! @brief 処理の結果を示す構造体です。C の API で使用します。 */ typedef struct nnResult { bit32 value; } nnResult; #ifdef __cplusplus } #endif // ifdef __cplusplus /*! @} */ /*! @} */ //------------------------------------------------------------------- // for C++ #ifdef __cplusplus namespace nn { /*! @brief 処理の結果を示すクラスです。 */ class Result{ private: static const bit32 MASK_FAIL_BIT = 0x80000000u; // 最上位ビット static const s32 SIZE_DESCRIPTION = 10; static const s32 SIZE_MODULE = 8; static const s32 SIZE_RESERVE = 3; static const s32 SIZE_SUMMARY = 6; static const s32 SIZE_LEVEL = 5; static const s32 SHIFTS_DESCRIPTION = 0; static const s32 SHIFTS_MODULE = SHIFTS_DESCRIPTION + SIZE_DESCRIPTION; static const s32 SHIFTS_RESERVE = SHIFTS_MODULE + SIZE_MODULE; static const s32 SHIFTS_SUMMARY = SHIFTS_RESERVE + SIZE_RESERVE; static const s32 SHIFTS_LEVEL = SHIFTS_SUMMARY + SIZE_SUMMARY; NN_STATIC_ASSERT( SHIFTS_LEVEL + SIZE_LEVEL == 32 ); static const bit32 MASK_NEGATIVE_LEVEL = (~0u) << SIZE_LEVEL; #define NN_RESULT_H_MAKE_MASK(size, shift) (((~0u) >> (32 - (size))) << (shift)) #define NN_RESULT_H_MAKE_MASK_HELPER(c) \ static const bit32 MASK_ ## c = NN_RESULT_H_MAKE_MASK(SIZE_ ## c, SHIFTS_ ## c) NN_RESULT_H_MAKE_MASK_HELPER(DESCRIPTION); NN_RESULT_H_MAKE_MASK_HELPER(MODULE); NN_RESULT_H_MAKE_MASK_HELPER(SUMMARY); NN_RESULT_H_MAKE_MASK_HELPER(LEVEL); #undef NN_RESULT_H_MAKE_MASK_HELPER #undef NN_RESULT_H_MAKE_MASK #define NN_RESULT_H_MAKE_MAX(size) ((~0u) >> (32 - (size))) #define NN_RESULT_H_MAKE_MAX_HELPER(c) \ static const s32 MAX_ ## c = NN_RESULT_H_MAKE_MAX(SIZE_ ## c) NN_RESULT_H_MAKE_MAX_HELPER(DESCRIPTION); NN_RESULT_H_MAKE_MAX_HELPER(MODULE); NN_RESULT_H_MAKE_MAX_HELPER(SUMMARY); NN_RESULT_H_MAKE_MAX_HELPER(LEVEL); #undef NN_RESULT_H_MAKE_MAX_HELPER #undef NN_RESULT_H_MAKE_MAX public: /*! * @brief エラーの重要度を示す列挙体です。(この列挙体を利用してエラーのハンドリングをしないでください。) */ enum Level { //! 成功。追加情報あり。 LEVEL_INFO = 1, //! 成功。追加情報なし。 LEVEL_SUCCESS = 0, //! システムレベルの致命的なエラー。ソフトウェアでの復旧不可能。サポートセンター案内シーケンスへ移行。 LEVEL_FATAL = -1, //! 予想されていないエラー。リセットシーケンスへ移行すべき。モジュールの再初期化で回復する見込みはないがリセットで回復する可能性がある。 LEVEL_RESET = -2, //! モジュールの再初期化が必要なエラー。 LEVEL_REINIT = -3, //! プログラミング上のエラー。指定された引数では内部状態によらず必ずエラーである。 LEVEL_USAGE = -4, //! 通常のエラー。リトライできない。 LEVEL_PERMANENT = -5, //! 一時的な失敗。同じ引数で即リトライできる。比較的少ないリトライ回数で成功する。 LEVEL_TEMPORARY = -6, //! 予想された失敗。 LEVEL_STATUS = -7, //! この値は使用されません。 LEVEL_END }; /*! * @brief エラーの概要を示す列挙体です。(この列挙体を利用してエラーのハンドリングをしないでください。) */ enum Summary { SUMMARY_SUCCESS = 0, //!< 成功しました。 SUMMARY_NOTHING_HAPPENED = 1, //!< 何も置きませんでした。 SUMMARY_WOULD_BLOCK = 2, //!< 処理がブロックする可能性があります。 SUMMARY_OUT_OF_RESOURCE = 3, //!< 処理に必要なリソースが確保できませんでした。 SUMMARY_NOT_FOUND = 4, //!< 対象が存在しません。 SUMMARY_INVALID_STATE = 5, //!< 要求された処理は、現在の内部状態では実行できません。 SUMMARY_NOT_SUPPORTED = 6, //!< 現在の SDK では未対応です。 SUMMARY_INVALID_ARGUMENT = 7, //!< 引数が不正です。 SUMMARY_WRONG_ARGUMENT = 8, //!< 引数以外のパラメータが不正です。 SUMMARY_CANCELLED = 9, //!< 処理はキャンセルされました。 SUMMARY_STATUS_CHANGED = 10, //!< 状態が変化しました。(例: 処理を実行中に内部状態が変化した) SUMMARY_INTERNAL = 11, //!< ライブラリ内部で使用されるエラーです。 SUMMARY_INVALID_RESULT_VALUE = MAX_SUMMARY }; /*! * @brief エラーが発生したモジュールを示す列挙体です。(この列挙体を利用してエラーのハンドリングをしないでください。) * * 列挙体の定義は将来変更される可能性があります。 */ enum Module { MODULE_COMMON = 0, MODULE_NN_KERNEL = 1, MODULE_NN_UTIL, MODULE_NN_FILE_SERVER, MODULE_NN_LOADER_SERVER, MODULE_NN_TCB, MODULE_NN_OS, MODULE_NN_DBG, MODULE_NN_DMNT, MODULE_NN_PDN, MODULE_NN_GX, MODULE_NN_I2C, MODULE_NN_GPIO, MODULE_NN_DD, MODULE_NN_CODEC, MODULE_NN_SPI, MODULE_NN_PXI, MODULE_NN_FS, MODULE_NN_DI, MODULE_NN_HID, MODULE_NN_CAMERA, MODULE_NN_PI, MODULE_NN_PM, MODULE_NN_PMLOW, MODULE_NN_FSI, MODULE_NN_SRV, MODULE_NN_NDM, MODULE_NN_NWM, MODULE_NN_SOCKET, MODULE_NN_LDR, MODULE_NN_ACC, MODULE_NN_ROMFS, MODULE_NN_AM, MODULE_NN_HIO, MODULE_NN_UPDATER, MODULE_NN_MIC, MODULE_NN_FND, MODULE_NN_MP, MODULE_NN_MPWL, MODULE_NN_AC, MODULE_NN_HTTP, MODULE_NN_DSP, MODULE_NN_SND, MODULE_NN_DLP, MODULE_NN_HIOLOW, MODULE_NN_CSND, MODULE_NN_SSL, MODULE_NN_AMLOW, MODULE_NN_NEX, MODULE_NN_FRIENDS, MODULE_NN_RDT, MODULE_NN_APPLET, MODULE_NN_NIM, MODULE_NN_PTM, MODULE_NN_MIDI, MODULE_NN_MC, MODULE_NN_SWC, MODULE_NN_FATFS, MODULE_NN_NGC, MODULE_NN_CARD, MODULE_NN_CARDNOR, MODULE_NN_SDMC, MODULE_NN_BOSS, MODULE_NN_DBM, MODULE_NN_CFG, MODULE_NN_PS, MODULE_NN_CEC, MODULE_NN_IR, MODULE_NN_UDS, MODULE_NN_PL, MODULE_NN_CUP, MODULE_NN_GYROSCOPE, MODULE_NN_MCU, MODULE_NN_NS, MODULE_NN_NEWS, MODULE_NN_RO, MODULE_NN_GD, MODULE_APPLICATION = MAX_MODULE - 1, MODULE_INVALID_RESULT_VALUE = MAX_MODULE }; /*! * @brief エラーの詳細を示す列挙体です。(この列挙体を利用してエラーのハンドリングをしないでください。) * * 負の値は SDK 全体で共通しており、正の値は各ライブラリが独自に定義する値です。 */ enum Description { DESCRIPTION_SUCCESS = 0, //!< 成功しました。 DESCRIPTION_INVALID_SELECTION = MAX_DESCRIPTION - 23, //!< (指定可能な値が離散的な場合に、) 不正な値が指定されました。 DESCRIPTION_TOO_LARGE = MAX_DESCRIPTION - 22, //!< 値が大きすぎます。 DESCRIPTION_NOT_AUTHORIZED = MAX_DESCRIPTION - 21, //!< 許可されていない操作です。 DESCRIPTION_ALREADY_DONE = MAX_DESCRIPTION - 20, //!< 内部状態が既に指定された状態になっています。 DESCRIPTION_INVALID_SIZE = MAX_DESCRIPTION - 19, //!< 値が無効なサイズです。 DESCRIPTION_INVALID_ENUM_VALUE = MAX_DESCRIPTION - 18, //!< enum 値の範囲外の値です。 DESCRIPTION_INVALID_COMBINATION = MAX_DESCRIPTION - 17, //!< 引数間の組み合わせが不正です。 DESCRIPTION_NO_DATA = MAX_DESCRIPTION - 16, //!< データがありません。 DESCRIPTION_BUSY = MAX_DESCRIPTION - 15, //!< 既に他の処理が行われていたため、実行できませんでした。 DESCRIPTION_MISALIGNED_ADDRESS = MAX_DESCRIPTION - 14, //!< アドレスに関するアライメントが不正です。 DESCRIPTION_MISALIGNED_SIZE = MAX_DESCRIPTION - 13, //!< サイズに関するアライメントが不正 DESCRIPTION_OUT_OF_MEMORY = MAX_DESCRIPTION - 12, //!< メモリが足りません。 DESCRIPTION_NOT_IMPLEMENTED = MAX_DESCRIPTION - 11, //!< 未実装です。 DESCRIPTION_INVALID_ADDRESS = MAX_DESCRIPTION - 10, //!< 不正なアドレスです。 DESCRIPTION_INVALID_POINTER = MAX_DESCRIPTION - 9, //!< 不正なポインタです。 DESCRIPTION_INVALID_HANDLE = MAX_DESCRIPTION - 8, //!< 不正なハンドルです。 DESCRIPTION_NOT_INITIALIZED = MAX_DESCRIPTION - 7, //!< 初期化されていません。 DESCRIPTION_ALREADY_INITIALIZED = MAX_DESCRIPTION - 6, //!< 既に初期化されています。 DESCRIPTION_NOT_FOUND = MAX_DESCRIPTION - 5, //!< 対象が存在しません。 DESCRIPTION_CANCEL_REQUESTED = MAX_DESCRIPTION - 4, //!< 要求がキャンセルされました。 DESCRIPTION_ALREADY_EXISTS = MAX_DESCRIPTION - 3, //!< 対象は既に存在します。 DESCRIPTION_OUT_OF_RANGE = MAX_DESCRIPTION - 2, //!< 値が定義域の範囲外です。 DESCRIPTION_TIMEOUT = MAX_DESCRIPTION - 1, //!< 処理がタイムアウトしました。 DESCRIPTION_INVALID_RESULT_VALUE = MAX_DESCRIPTION - 0 }; private: bit32 m_Code; template friend struct Const; template friend struct ConstRange; explicit Result(bit32 code) : m_Code(code) {} public: Result() : m_Code( static_cast( ((static_cast(LEVEL_USAGE) << SHIFTS_LEVEL) & MASK_LEVEL) | ((SUMMARY_INVALID_RESULT_VALUE << SHIFTS_SUMMARY) & MASK_SUMMARY) | ((MODULE_INVALID_RESULT_VALUE << SHIFTS_MODULE) & MASK_MODULE) | ((DESCRIPTION_INVALID_RESULT_VALUE << SHIFTS_DESCRIPTION) & MASK_DESCRIPTION) )) { } Result(Level level, Summary summary, Module module, int description) : m_Code( static_cast( ((level << SHIFTS_LEVEL) & MASK_LEVEL) | ((summary << SHIFTS_SUMMARY) & MASK_SUMMARY) | ((module << SHIFTS_MODULE) & MASK_MODULE) | ((description << SHIFTS_DESCRIPTION) & MASK_DESCRIPTION) )) { } Result(nnResult result) : m_Code(result.value) {} /*! @name 判定 @{ */ /*! * @brief 処理の結果が失敗なら true を、成功なら false を返します。 */ bool IsFailure() const { return (m_Code & MASK_FAIL_BIT) != 0; } /*! * @brief 処理の結果が成功なら true を、失敗なら false を返します。 */ bool IsSuccess() const { return !IsFailure(); } /*! @} */ /*! * :private * @brief エラーの深刻度を示す Level 列挙体を返します。 * * Bug: 列挙体の定義は将来変更されます。開発時のエラー内容確認の用途以外では利用しないでください。 */ Level GetLevel() const { // TODO: プラットフォーム依存の算術シフトインライン関数を作ってそれを呼ぶべき if(m_Code & MASK_FAIL_BIT) { return static_cast( GetCodeBits(MASK_LEVEL, SHIFTS_LEVEL) | MASK_NEGATIVE_LEVEL); } else { return static_cast( GetCodeBits(MASK_LEVEL, SHIFTS_LEVEL) ); } } /*! * :private * @brief エラーの概要を示す Summary 列挙体を返します。 * * Bug: 列挙体の定義は将来変更されます。開発時のエラー内容確認の用途以外では利用しないでください。 */ Summary GetSummary() const { return static_cast( GetCodeBits(MASK_SUMMARY, SHIFTS_SUMMARY) ); } /*! * :private * @brief エラーが発生したモジュールを示す Module 列挙体を返します。 * * Bug: 列挙体の定義は将来変更されます。開発時のエラー内容確認の用途以外では利用しないでください。 */ Module GetModule() const { return static_cast( GetCodeBits(MASK_MODULE, SHIFTS_MODULE) ); } /*! * :private * @brief エラーの詳細を示す Description 列挙体を返します。 * * Bug: 列挙体の定義は将来変更されます。開発時のエラー内容確認の用途以外では利用しないでください。 */ int GetDescription() const { return static_cast( GetCodeBits(MASK_DESCRIPTION, SHIFTS_DESCRIPTION) ); } bit32 GetValue() const { return m_Code; } /*! @name 開発サポート @{ */ /*! * @brief Result を 32bit のビット列に変換します。 * * @return @ref Level, @ref Summary, @ref Module, @ref Description をまとめた 32bit のビット列です。 */ bit32 GetPrintableBits() const { return m_Code; } operator nnResult() const { nnResult r = {m_Code}; return r; } /*! @} */ /*! @name 判定 @{ */ /*! * @brief 一致判定を行います。 * * @ref nn::fs 以外のライブラリで、特定のエラーをハンドリングする際にご利用下さい。なお、 @ref nn::fs ライブラリでの * エラーハンドリングについては @ref nn::fs ライブラリのリファレンスを参照下さい。 * @return 一致した場合に true を、一致しない場合に false を返します。 */ bool operator ==(const Result& rhs) const { return this->m_Code == rhs.m_Code; } /*! * @brief 不一致判定を行います。 * * @ref nn::fs 以外のライブラリで、特定のエラーをハンドリングする際にご利用下さい。なお、 @ref nn::fs ライブラリでの * エラーハンドリングについては @ref nn::fs ライブラリのリファレンスを参照下さい。 * @return 一致しない場合に true を、一致する場合に false を返します。 */ bool operator !=(const Result& rhs) const { return this->m_Code != rhs.m_Code; } /*! @} */ template struct Const; template struct ConstRange; template struct Const_LSM; template struct Const_LM; template struct Const_L; private: bit32 GetCodeBits(bit32 mask, s32 shift) const { return ((m_Code & mask) >> shift); } template bool operator==(ConstRange) const; template bool operator!=(ConstRange) const; }; template struct Result::Const : public Result { static const Result::Level Level = TLevel; static const Result::Summary Summary = TSummary; static const Result::Module Module = TModule; static const int Description = TDescription; static const bit32 Value = static_cast( ((static_cast(TLevel) << SHIFTS_LEVEL) & MASK_LEVEL) | ((TSummary << SHIFTS_SUMMARY) & MASK_SUMMARY) | ((TModule << SHIFTS_MODULE) & MASK_MODULE) | ((TDescription << SHIFTS_DESCRIPTION) & MASK_DESCRIPTION) ); Const() : Result(Value) {} static bool Includes(Result result) { return result.GetModule() == TModule && result.GetDescription() == TDescription; } }; template struct Result::ConstRange : public Result { static const Result::Level Level = TLevel; static const Result::Summary Summary = TSummary; static const Result::Module Module = TModule; static const int Description = TDescription; static const int DescriptionMin = TDescriptionMin; static const int DescriptionMax = TDescriptionMax; static const bit32 Value = static_cast( ((static_cast(TLevel) << SHIFTS_LEVEL) & MASK_LEVEL) | ((TSummary << SHIFTS_SUMMARY) & MASK_SUMMARY) | ((TModule << SHIFTS_MODULE) & MASK_MODULE) | ((TDescription << SHIFTS_DESCRIPTION) & MASK_DESCRIPTION) ); ConstRange() : Result(Value) {} static bool Includes(Result result) { return result.GetModule() == TModule && (TDescriptionMin <= result.GetDescription() && result.GetDescription() <= TDescriptionMax); } friend bool operator<=(Result lhs, ConstRange) { return ConstRange::Includes(lhs); } friend bool operator>=(ConstRange, Result rhs) { return ConstRange::Includes(rhs); } private: bool operator==(Result) const; bool operator!=(Result) const; }; template struct Result::Const_LSM : public Result { static const Result::Level Level = TLevel; static const Result::Summary Summary = TSummary; static const Result::Module Module = TModule; template struct Const : public Result::Const {}; Const_LSM(int description) : Result(TLevel, TSummary, TModule, description) {} }; template struct Result::Const_LM : public Result { static const Result::Level Level = TLevel; static const Result::Module Module = TModule; template struct Const : public Result::Const {}; Const_LM(Result::Summary summary, int description) : Result(TLevel, summary, TModule, description) {} }; template struct Result::Const_L : public Result { static const Result::Level Level = TLevel; template struct Const : public Result::Const {}; Const_L(Result::Summary summary, Result::Module module, int description) : Result(TLevel, summary, module, description) {} }; #define NN_DEFINE_RESULT_CONST(name, level, summary, module, description) \ typedef ::nn::Result::Const<(level), (summary), (module), (description)> name #define NN_DEFINE_RESULT_CONST_RANGE(name, level, summary, module, description, descriptionMin, descriptionMax) \ typedef ::nn::Result::ConstRange<(level), (summary), (module), (description), (descriptionMin), (descriptionMax)> name NN_DEFINE_RESULT_CONST(ResultSuccess, Result::LEVEL_SUCCESS, Result::SUMMARY_SUCCESS, Result::MODULE_COMMON, Result::DESCRIPTION_SUCCESS); #define NN_DEFINE_RESULT_FUNC_LSM(name, level, summary, module) \ typedef ::nn::Result::Const_LSM<(level), (summary), (module)> name #define NN_DEFINE_RESULT_CONST_LSM(name, f, description) \ typedef f::Const<(description)> name #define NN_DEFINE_RESULT_FUNC_LM(name, level, module) \ typedef ::nn::Result::Const_LM<(level), (module)> name #define NN_DEFINE_RESULT_CONST_LM(name, f, summary, description) \ typedef f::Const<(summary), (description)> name #define NN_DEFINE_RESULT_FUNC_L(name, level) \ typedef ::nn::Result::Const_L<(level)> name #define NN_DEFINE_RESULT_CONST_L(name, f, summary, module, description) \ typedef f::Const<(summary), (module), (description)> name inline Result MakeInfoResult(Result::Summary summary, Result::Module module, int description) { return Result(Result::LEVEL_INFO, summary, module, description); } inline Result MakeFatalResult(Result::Summary summary, Result::Module module, int description) { return Result(Result::LEVEL_FATAL, summary, module, description); } inline Result MakeResetResult(Result::Summary summary, Result::Module module, int description) { return Result(Result::LEVEL_RESET, summary, module, description); } inline Result MakeReInitResult(Result::Summary summary, Result::Module module, int description) { return Result(Result::LEVEL_REINIT, summary, module, description); } inline Result MakeUsageResult(Result::Summary summary, Result::Module module, int description) { return Result(Result::LEVEL_USAGE, summary, module, description); } inline Result MakePermanentResult(Result::Summary summary, Result::Module module, int description) { return Result(Result::LEVEL_PERMANENT, summary, module, description); } inline Result MakeTemporaryResult(Result::Summary summary, Result::Module module, int description) { return Result(Result::LEVEL_TEMPORARY, summary, module, description); } inline Result MakeStatusResult(Result::Summary summary, Result::Module module, int description) { return Result(Result::LEVEL_STATUS, summary, module, description); } } #endif // __cplusplus #ifdef __cplusplus extern "C" { #endif typedef void (*nnResultHandlerImpl)(nnResult result, const char* filename, int lineno, const char* fmt, va_list vlist); int nnResultFailureHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...); int nnResultTFailureHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...); int nnResultPanicHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...); int nnResultTPanicHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...); nnResult nnMakeInvalidResult(void); #ifdef __cplusplus } #endif #endif /* NN_RESULT_H_ */