1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     Result.h
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 25607 $
14  *---------------------------------------------------------------------------*/
15 
16 /*!
17     @file
18     @brief    Result クラスの宣言
19 
20     :include nn/Result.h
21 */
22 
23 #ifndef NN_RESULT_H_
24 #define NN_RESULT_H_
25 
26 #include <nn/types.h>
27 #include <nn/util/util_StaticAssert.h>
28 
29 //-------------------------------------------------------------------
30 // for C / C++
31 
32 /*!
33   @addtogroup     nn_root
34   @{
35 */
36 
37 /*!
38   @defgroup       nn_Result_c       Result (C)
39 
40   @brief    処理の結果を示すnn::ResultのC インタフェースモジュールです。
41 
42   @{
43 */
44 
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif  // ifdef __cplusplus
49 
50 /*!
51     @brief  処理の結果を示す構造体です。C の API で使用します。
52 */
53 typedef struct nnResult
54 {
55     bit32   value;
56 }
57 nnResult;
58 
59 #ifdef __cplusplus
60 }
61 #endif  // ifdef __cplusplus
62 
63 /*!
64   @}
65 */
66 /*!
67   @}
68 */
69 
70 
71 //-------------------------------------------------------------------
72 // for C++
73 
74 #ifdef __cplusplus
75 
76 namespace nn {
77 
78 /*!
79     @brief        処理の結果を示すクラスです。
80 */
81 
82 class Result{
83 private:
84     static const bit32 MASK_FAIL_BIT        = 0x80000000u; // 最上位ビット
85 
86     static const s32 SIZE_DESCRIPTION       = 10;
87     static const s32 SIZE_MODULE            =  8;
88     static const s32 SIZE_RESERVE           =  3;
89     static const s32 SIZE_SUMMARY           =  6;
90     static const s32 SIZE_LEVEL             =  5;
91 
92     static const s32 SHIFTS_DESCRIPTION     = 0;
93     static const s32 SHIFTS_MODULE          = SHIFTS_DESCRIPTION + SIZE_DESCRIPTION;
94     static const s32 SHIFTS_RESERVE         = SHIFTS_MODULE      + SIZE_MODULE;
95     static const s32 SHIFTS_SUMMARY         = SHIFTS_RESERVE     + SIZE_RESERVE;
96     static const s32 SHIFTS_LEVEL           = SHIFTS_SUMMARY     + SIZE_SUMMARY;
97     NN_STATIC_ASSERT( SHIFTS_LEVEL + SIZE_LEVEL == 32 );
98 
99     static const bit32 MASK_NEGATIVE_LEVEL  = (~0u) << SIZE_LEVEL;
100 
101 #define NN_RESULT_H_MAKE_MASK(size, shift)  (((~0u) >> (32 - (size))) << (shift))
102 #define NN_RESULT_H_MAKE_MASK_HELPER(c)     \
103     static const bit32 MASK_ ## c           = NN_RESULT_H_MAKE_MASK(SIZE_ ## c, SHIFTS_ ## c)
104     NN_RESULT_H_MAKE_MASK_HELPER(DESCRIPTION);
105     NN_RESULT_H_MAKE_MASK_HELPER(MODULE);
106     NN_RESULT_H_MAKE_MASK_HELPER(SUMMARY);
107     NN_RESULT_H_MAKE_MASK_HELPER(LEVEL);
108 #undef NN_RESULT_H_MAKE_MASK_HELPER
109 #undef NN_RESULT_H_MAKE_MASK
110 
111 #define NN_RESULT_H_MAKE_MAX(size)          ((~0u) >> (32 - (size)))
112 #define NN_RESULT_H_MAKE_MAX_HELPER(c)      \
113     static const s32 MAX_ ## c              = NN_RESULT_H_MAKE_MAX(SIZE_ ## c)
114     NN_RESULT_H_MAKE_MAX_HELPER(DESCRIPTION);
115     NN_RESULT_H_MAKE_MAX_HELPER(MODULE);
116     NN_RESULT_H_MAKE_MAX_HELPER(SUMMARY);
117     NN_RESULT_H_MAKE_MAX_HELPER(LEVEL);
118 #undef NN_RESULT_H_MAKE_MAX_HELPER
119 #undef NN_RESULT_H_MAKE_MAX
120 
121 public:
122     /*!
123      * @brief エラーの重要度を示す列挙体です。
124      *
125      * Bug:   列挙体の定義は将来変更されます。
126      */
127     enum Level
128     {
129         //! 成功。追加情報あり。
130         LEVEL_INFO       =  1,
131         //! 成功。追加情報なし。
132         LEVEL_SUCCESS    =  0,
133         //! システムレベルの致命的なエラー。ソフトウェアでの復旧不可能。サポートセンター案内シーケンスへ移行。
134         LEVEL_FATAL      = -1,
135         //! 予想されていないエラー。リセットシーケンスへ移行すべき。モジュールの再初期化で回復する見込みはないがリセットで回復する可能性がある。
136         LEVEL_RESET      = -2,
137         //! モジュールの再初期化が必要なエラー。
138         LEVEL_REINIT     = -3,
139         //! プログラミング上のエラー。指定された引数では内部状態によらず必ずエラーである。
140         LEVEL_USAGE      = -4,
141         //! 通常のエラー。リトライできない。
142         LEVEL_PERMANENT  = -5,
143         //! 一時的な失敗。同じ引数で即リトライできる。比較的少ないリトライ回数で成功する。
144         LEVEL_TEMPORARY  = -6,
145         //! 予想された失敗。
146         LEVEL_STATUS     = -7,
147         //! この値は使用されません。
148         LEVEL_END
149     };
150 
151     /*!
152      * @brief エラーの概要を示す列挙体です。
153      *
154      * Bug:   列挙体の定義は将来変更されます。
155      */
156     enum Summary
157     {
158         SUMMARY_SUCCESS                 =   0,
159         SUMMARY_NOTHING_HAPPENED        =   1,
160         SUMMARY_WOULD_BLOCK             =   2,
161         SUMMARY_OUT_OF_RESOURCE         =   3,
162         SUMMARY_NOT_FOUND               =   4,
163         SUMMARY_INVALID_STATE           =   5,
164         SUMMARY_NOT_SUPPORTED           =   6,
165         SUMMARY_INVALID_ARGUMENT        =   7,
166         SUMMARY_WRONG_ARGUMENT          =   8,
167         SUMMARY_CANCELLED               =   9,
168         SUMMARY_STATUS_CHANGED          =  10,
169         SUMMARY_INTERNAL                =  11,
170 
171         SUMMARY_INVALID_RESULT_VALUE    = MAX_SUMMARY
172     };
173 
174     /*!
175      * @brief エラーが発生したモジュールを示す列挙体です。
176      *
177      * Bug:   列挙体の定義は将来変更されます。
178      */
179     enum Module
180     {
181         MODULE_COMMON                   = 0,
182         MODULE_NN_KERNEL                = 1,
183         MODULE_NN_UTIL,
184         MODULE_NN_FILE_SERVER,
185         MODULE_NN_LOADER_SERVER,
186         MODULE_NN_TCB,
187         MODULE_NN_OS,
188         MODULE_NN_DBG,
189         MODULE_NN_DMNT,
190         MODULE_NN_PDN,
191         MODULE_NN_GX,
192         MODULE_NN_I2C,
193         MODULE_NN_GPIO,
194         MODULE_NN_DD,
195         MODULE_NN_CODEC,
196         MODULE_NN_SPI,
197         MODULE_NN_PXI,
198         MODULE_NN_FS,
199         MODULE_NN_DI,
200         MODULE_NN_HID,
201         MODULE_NN_CAMERA,
202         MODULE_NN_PI,
203         MODULE_NN_PM,
204         MODULE_NN_PMLOW,
205         MODULE_NN_FSI,
206         MODULE_NN_SRV,
207         MODULE_NN_NDM,
208         MODULE_NN_NWM,
209         MODULE_NN_SOCKET,
210         MODULE_NN_LDR,
211         MODULE_NN_ACC,
212         MODULE_NN_ROMFS,
213         MODULE_NN_AM,
214         MODULE_NN_HIO,
215         MODULE_NN_UPDATER,
216         MODULE_NN_MIC,
217         MODULE_NN_FND,
218         MODULE_NN_MP,
219         MODULE_NN_MPWL,
220         MODULE_NN_AC,
221         MODULE_NN_HTTP,
222         MODULE_NN_DSP,
223         MODULE_NN_SND,
224         MODULE_NN_DLP,
225         MODULE_NN_HIOLOW,
226         MODULE_NN_CSND,
227         MODULE_NN_SSL,
228         MODULE_NN_AMLOW,
229         MODULE_NN_NEX,
230         MODULE_NN_FRIENDS,
231         MODULE_NN_RDT,
232         MODULE_NN_APPLET,
233         MODULE_NN_NIM,
234         MODULE_NN_PTM,
235         MODULE_NN_MIDI,
236         MODULE_NN_MC,
237         MODULE_NN_SWC,
238         MODULE_NN_FATFS,
239         MODULE_NN_NGC,
240         MODULE_NN_CARD,
241         MODULE_NN_CARDNOR,
242         MODULE_NN_SDMC,
243         MODULE_NN_BOSS,
244         MODULE_NN_DBM,
245         MODULE_NN_CFG,
246         MODULE_NN_PS,
247         MODULE_NN_CEC,
248         MODULE_NN_IR,
249         MODULE_NN_UDS,
250         MODULE_NN_PL,
251         MODULE_NN_CUP,
252         MODULE_INVALID_RESULT_VALUE     = MAX_MODULE
253     };
254 
255     enum Description
256     {
257         DESCRIPTION_SUCCESS                         =    0,
258 
259         DESCRIPTION_INVALID_SELECTION               = MAX_DESCRIPTION - 23,
260         DESCRIPTION_TOO_LARGE                       = MAX_DESCRIPTION - 22,
261         DESCRIPTION_NOT_AUTHORIZED                  = MAX_DESCRIPTION - 21,
262         DESCRIPTION_ALREADY_DONE                    = MAX_DESCRIPTION - 20,
263         DESCRIPTION_INVALID_SIZE                    = MAX_DESCRIPTION - 19,
264         DESCRIPTION_INVALID_ENUM_VALUE              = MAX_DESCRIPTION - 18,
265         DESCRIPTION_INVALID_COMBINATION             = MAX_DESCRIPTION - 17,
266         DESCRIPTION_NO_DATA                         = MAX_DESCRIPTION - 16,
267         DESCRIPTION_BUSY                            = MAX_DESCRIPTION - 15,
268         DESCRIPTION_MISALIGNED_ADDRESS              = MAX_DESCRIPTION - 14,
269         DESCRIPTION_MISALIGNED_SIZE                 = MAX_DESCRIPTION - 13,
270         DESCRIPTION_OUT_OF_MEMORY                   = MAX_DESCRIPTION - 12,
271         DESCRIPTION_NOT_IMPLEMENTED                 = MAX_DESCRIPTION - 11,
272         DESCRIPTION_INVALID_ADDRESS                 = MAX_DESCRIPTION - 10,
273         DESCRIPTION_INVALID_POINTER                 = MAX_DESCRIPTION -  9,
274         DESCRIPTION_INVALID_HANDLE                  = MAX_DESCRIPTION -  8,
275         DESCRIPTION_NOT_INITIALIZED                 = MAX_DESCRIPTION -  7,
276         DESCRIPTION_ALREADY_INITIALIZED             = MAX_DESCRIPTION -  6,
277         DESCRIPTION_NOT_FOUND                       = MAX_DESCRIPTION -  5,
278         DESCRIPTION_CANCEL_REQUESTED                = MAX_DESCRIPTION -  4,
279         DESCRIPTION_ALREADY_EXISTS                  = MAX_DESCRIPTION -  3,
280         DESCRIPTION_OUT_OF_RANGE                    = MAX_DESCRIPTION -  2,
281         DESCRIPTION_TIMEOUT                         = MAX_DESCRIPTION -  1,
282         DESCRIPTION_INVALID_RESULT_VALUE            = MAX_DESCRIPTION -  0
283     };
284 
285 private:
286 
287     bit32 m_Code;
288 
289     template <Result::Level TLevel, Result::Summary TSummary, Result::Module TModule, int TDescription> friend struct Const;
Result(bit32 code)290     explicit Result(bit32 code) : m_Code(code) {}
291 
292 public:
Result()293     Result()
294         : m_Code( static_cast<bit32>(
295                     ((static_cast<bit32>(LEVEL_USAGE)   << SHIFTS_LEVEL)         & MASK_LEVEL)        |
296                     ((SUMMARY_INVALID_RESULT_VALUE      << SHIFTS_SUMMARY)       & MASK_SUMMARY)      |
297                     ((MODULE_INVALID_RESULT_VALUE       << SHIFTS_MODULE)        & MASK_MODULE)       |
298                     ((DESCRIPTION_INVALID_RESULT_VALUE  << SHIFTS_DESCRIPTION)   & MASK_DESCRIPTION) ))
299     {
300     }
301 
Result(Level level,Summary summary,Module module,int description)302     Result(Level level, Summary summary, Module module, int description)
303         : m_Code( static_cast<bit32>(
304                     ((level        << SHIFTS_LEVEL)         & MASK_LEVEL)        |
305                     ((summary      << SHIFTS_SUMMARY)       & MASK_SUMMARY)      |
306                     ((module       << SHIFTS_MODULE)        & MASK_MODULE)       |
307                     ((description  << SHIFTS_DESCRIPTION)   & MASK_DESCRIPTION) ))
308     {
309     }
310 
Result(nnResult result)311     Result(nnResult result) : m_Code(result.value) {}
312 
313     /*!
314      * @brief 処理の結果が失敗なら true を、成功なら false を返します。
315      */
IsFailure()316     bool IsFailure() const
317     {
318         return (m_Code & MASK_FAIL_BIT) != 0;
319     }
320 
321     /*!
322      * @brief 処理の結果が成功なら true を、失敗なら false を返します。
323      */
IsSuccess()324     bool IsSuccess() const
325     {
326         return !IsFailure();
327     }
328 
329     /*!
330      * @brief エラーの深刻度を示す Level 列挙体を返します。
331      *
332      * Bug:   列挙体の定義は将来変更されます。現状では利用しないでください。
333      */
GetLevel()334     Level GetLevel() const
335     {
336         // TODO: プラットフォーム依存の算術シフトインライン関数を作ってそれを呼ぶべき
337         if(m_Code & MASK_FAIL_BIT)
338         {
339             return static_cast<Level>( GetCodeBits(MASK_LEVEL, SHIFTS_LEVEL) | MASK_NEGATIVE_LEVEL);
340         }
341         else
342         {
343             return static_cast<Level>( GetCodeBits(MASK_LEVEL, SHIFTS_LEVEL) );
344         }
345     }
346 
347     /*!
348      * @brief エラーの概要を示す Summary 列挙体を返します。
349      *
350      * Bug:   列挙体の定義は将来変更されます。現状では利用しないでください。
351      */
GetSummary()352     Summary GetSummary() const
353     {
354         return static_cast<Summary>( GetCodeBits(MASK_SUMMARY, SHIFTS_SUMMARY) );
355     }
356 
357     /*!
358      * @brief エラーが発生したモジュールを示す Module 列挙体を返します。
359      *
360      *
361      * Bug:   列挙体の定義は将来変更されます。現状では利用しないでください。
362      */
GetModule()363     Module GetModule() const
364     {
365         return static_cast<Module>( GetCodeBits(MASK_MODULE, SHIFTS_MODULE) );
366     }
367 
GetDescription()368     int GetDescription() const
369     {
370         return static_cast<int>( GetCodeBits(MASK_DESCRIPTION, SHIFTS_DESCRIPTION) );
371     }
372 
GetValue()373     bit32 GetValue() const { return m_Code; }
374 
GetPrintableBits()375     bit32 GetPrintableBits() const { return m_Code; }
376 
nnResult()377     operator nnResult() const
378     {
379         nnResult r = {m_Code};
380         return r;
381     }
382 
383     bool operator ==(const Result& rhs) const { return this->m_Code == rhs.m_Code; }
384     bool operator !=(const Result& rhs) const { return this->m_Code != rhs.m_Code; }
385 
386     template <Result::Level TLevel, Result::Summary TSummary, Result::Module TModule, int TDescription> struct Const;
387     template <Result::Level TLevel, Result::Summary TSummary, Result::Module TModule> struct Const_LSM;
388     template <Result::Level TLevel, Result::Module TModule> struct Const_LM;
389     template <Result::Level TLevel> struct Const_L;
390 
391 private:
GetCodeBits(bit32 mask,s32 shift)392     bit32 GetCodeBits(bit32 mask, s32 shift) const
393     {
394         return ((m_Code & mask) >> shift);
395     }
396 };
397 
398 template <Result::Level TLevel, Result::Summary TSummary, Result::Module TModule, int TDescription>
399 struct Result::Const : public Result
400 {
401     static const Result::Level Level = TLevel;
402     static const Result::Summary Summary = TSummary;
403     static const Result::Module Module = TModule;
404     static const int Description = TDescription;
405 
406     static const bit32 Value = static_cast<bit32>(
407                     ((static_cast<bit32>(TLevel) << SHIFTS_LEVEL) & MASK_LEVEL)        |
408                     ((TSummary     << SHIFTS_SUMMARY)             & MASK_SUMMARY)      |
409                     ((TModule      << SHIFTS_MODULE)              & MASK_MODULE)       |
410                     ((TDescription << SHIFTS_DESCRIPTION)         & MASK_DESCRIPTION) );
411 
ConstConst412     Const() : Result(Value) {}
413 };
414 
415 template <Result::Level TLevel, Result::Summary TSummary, Result::Module TModule>
416 struct Result::Const_LSM : public Result
417 {
418     static const Result::Level Level = TLevel;
419     static const Result::Summary Summary = TSummary;
420     static const Result::Module Module = TModule;
421 
422     template <int TDescription>
423     struct Const : public Result::Const<TLevel, TSummary, TModule, TDescription> {};
424 
Const_LSMConst_LSM425     Const_LSM(int description) : Result(TLevel, TSummary, TModule, description) {}
426 };
427 
428 template <Result::Level TLevel, Result::Module TModule>
429 struct Result::Const_LM : public Result
430 {
431     static const Result::Level Level = TLevel;
432     static const Result::Module Module = TModule;
433 
434     template <Result::Summary TSummary, int TDescription>
435     struct Const : public Result::Const<TLevel, TSummary, TModule, TDescription> {};
436 
Const_LMConst_LM437     Const_LM(Result::Summary summary, int description) : Result(TLevel, summary, TModule, description) {}
438 };
439 
440 template <Result::Level TLevel>
441 struct Result::Const_L : public Result
442 {
443     static const Result::Level Level = TLevel;
444 
445     template <Result::Summary TSummary, Result::Module TModule, int TDescription>
446     struct Const : public Result::Const<TLevel, TSummary, TModule, TDescription> {};
447 
Const_LConst_L448     Const_L(Result::Summary summary, Result::Module module, int description) : Result(TLevel, summary, module, description) {}
449 };
450 
451 #define NN_DEFINE_RESULT_CONST(name, level, summary, module, description) \
452     typedef ::nn::Result::Const<(level), (summary), (module), (description)> name
453 
454 NN_DEFINE_RESULT_CONST(ResultSuccess, Result::LEVEL_SUCCESS, Result::SUMMARY_SUCCESS, Result::MODULE_COMMON, Result::DESCRIPTION_SUCCESS);
455 
456 #define NN_DEFINE_RESULT_FUNC_LSM(name, level, summary, module) \
457     typedef ::nn::Result::Const_LSM<(level), (summary), (module)> name
458 
459 #define NN_DEFINE_RESULT_CONST_LSM(name, f, description) \
460     typedef f::Const<(description)> name
461 
462 #define NN_DEFINE_RESULT_FUNC_LM(name, level, module) \
463     typedef ::nn::Result::Const_LM<(level), (module)> name
464 
465 #define NN_DEFINE_RESULT_CONST_LM(name, f, summary, description) \
466     typedef f::Const<(summary), (description)> name
467 
468 #define NN_DEFINE_RESULT_FUNC_L(name, level) \
469     typedef ::nn::Result::Const_L<(level)> name
470 
471 #define NN_DEFINE_RESULT_CONST_L(name, f, summary, module, description) \
472     typedef f::Const<(summary), (module), (description)> name
473 
474 // 完全移行まではコメントアウト
475 //NN_DEFINE_RESULT_FUNC_L(MakeInfoResult, LEVEL_INFO);
476 //NN_DEFINE_RESULT_FUNC_L(MakeFatalResult, LEVEL_FATAL);
477 //NN_DEFINE_RESULT_FUNC_L(MakeResetResult, LEVEL_RESET);
478 //NN_DEFINE_RESULT_FUNC_L(MakeReInitResult, LEVEL_REINIT);
479 //NN_DEFINE_RESULT_FUNC_L(MakeUsageResult, LEVEL_USAGE);
480 //NN_DEFINE_RESULT_FUNC_L(MakePermanentResult, LEVEL_PERMANENT);
481 //NN_DEFINE_RESULT_FUNC_L(MakeTemporaryResult, LEVEL_TEMPORARY);
482 //NN_DEFINE_RESULT_FUNC_L(MakeStatusResult, LEVEL_STATUS);
483 
MakeInfoResult(Result::Summary summary,Result::Module module,int description)484 inline Result MakeInfoResult(Result::Summary summary, Result::Module module, int description)
485     { return Result(Result::LEVEL_INFO, summary, module, description); }
MakeFatalResult(Result::Summary summary,Result::Module module,int description)486 inline Result MakeFatalResult(Result::Summary summary, Result::Module module, int description)
487     { return Result(Result::LEVEL_FATAL, summary, module, description); }
MakeResetResult(Result::Summary summary,Result::Module module,int description)488 inline Result MakeResetResult(Result::Summary summary, Result::Module module, int description)
489     { return Result(Result::LEVEL_RESET, summary, module, description); }
MakeReInitResult(Result::Summary summary,Result::Module module,int description)490 inline Result MakeReInitResult(Result::Summary summary, Result::Module module, int description)
491     { return Result(Result::LEVEL_REINIT, summary, module, description); }
MakeUsageResult(Result::Summary summary,Result::Module module,int description)492 inline Result MakeUsageResult(Result::Summary summary, Result::Module module, int description)
493     { return Result(Result::LEVEL_USAGE, summary, module, description); }
MakePermanentResult(Result::Summary summary,Result::Module module,int description)494 inline Result MakePermanentResult(Result::Summary summary, Result::Module module, int description)
495     { return Result(Result::LEVEL_PERMANENT, summary, module, description); }
MakeTemporaryResult(Result::Summary summary,Result::Module module,int description)496 inline Result MakeTemporaryResult(Result::Summary summary, Result::Module module, int description)
497     { return Result(Result::LEVEL_TEMPORARY, summary, module, description); }
MakeStatusResult(Result::Summary summary,Result::Module module,int description)498 inline Result MakeStatusResult(Result::Summary summary, Result::Module module, int description)
499     { return Result(Result::LEVEL_STATUS, summary, module, description); }
500 
501 }
502 
503 
504 #endif // __cplusplus
505 
506 #ifdef __cplusplus
507 extern "C" {
508 #endif
509 
510 int nnResultFailureHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...);
511 int nnResultTFailureHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...);
512 
513 int nnResultPanicHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...);
514 int nnResultTPanicHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...);
515 
516 nnResult nnMakeInvalidResult(void);
517 
518 #ifdef __cplusplus
519 }
520 #endif
521 
522 #endif /* NN_RESULT_H_ */
523