#ifndef __ERROR_CONTROL_H #define __ERROR_CONTROL_H #pragma once // // //================================================================================================== // (FlowControl) // (WAVERIX) (071103) // @history // 0x0100 - ErrorControl // 0x0110 - Change ErrorControl->FlowControl // 0x0120 - Update StateControl, Assert Handler // 0x0130 - Trim unused StateControl, // Change 'FCCheckFail -> IfFailThenBreak, IfFailThen' compare routine // 0x0140 - fit in coding style and changes condition block class FlowControl { public: static const DWORD Version = 0x0140; static const bool FAIL = false; static const bool SUCCESS = true; static const DWORD LOGIC_BLOCK = 0x01110000; static const DWORD ERROR_BLOCK = 0x00001111; FlowControl() : CurrentState(current_state_), current_state_(SUCCESS), error_code_(0), error_string_(0) {} inline BOOLEAN IsSuccess() const { return current_state_ != FAIL; } inline BOOLEAN IsErrorOccured() const { return current_state_ == FAIL; } inline DWORD GetErrorCode() const { return error_code_; } inline const char* GetErrorString() const { return error_string_; } //---------------------------------------------------------------------------------------------- // (Interface #1) // (Description) // expect_true - ´ÙÀ½ ´Ü°è·Î ³Ñ¾î°¡±â À§Çؼ­´Â True¿©¾ß ÇÏ´Â Á¶°Ç // (Format) // IfFailThenBreak(condition, error_code); // (Pseudo) // if(expect_true == false) { // { Set Error code & Error string } // break; // } // Next step; // // (Side-Effect) // errorCode, errorString - condition == falseÀÏ °æ¿ì ¼³Á¤µÇ´Â °ª #pragma warning(push) #pragma warning(disable : 4706) __forceinline BOOLEAN __IsFailFc(bool expect_true, DWORD if_fail_then_fail_reason_code, const char* fail_string = 0) { if(current_state_ && !(current_state_ = expect_true)) { error_code_ = if_fail_then_fail_reason_code; error_string_ = fail_string; } return !current_state_; } #pragma warning(pop) //---------------------------------------------------------------------------------------------- // (INTERFACE #2) // (Description) // °­Á¦·Î Error Control 󸮸¦ ¼öÇàÇϱâ À§ÇÔ. // FCAssertÀÇ °æ¿ì, º°µµ FlowControlÀÌ´Ù. ¿¹¸¦ µé¾î Release¸ðµå¿¡¼­ AssertÀε¥µµ // Assert°¡ ¾Æ´Ñ »óȲÀÌ ¹ß»ýÇßÀ» °æ¿ì, »ç¿ëÀÌ °¡´ÉÇÏ´Ù. // (Sample) // if(FALSE == flow.FCAssert(failCase)) { // SetFailFc(failCase, error_code); // break; // } __forceinline void SetFailFc(DWORD fail_reason_code, char* fail_string = NULL) { current_state_ = FAIL; error_code_ = fail_reason_code; error_string_ = fail_string; } #if defined(_DEBUG) || defined(_SERVER) // µð¹ö±ë ¹®ÀÚ¿­ º¸¾È ¹®Á¦ ¶«½Ã #define IfFailThen(expect_true, if_fail_then_fail_reason_code) \ if (flow.CurrentState == FlowControl::FAIL || \ flow.__IsFailFc(!!(expect_true), if_fail_then_fail_reason_code, ###expect_true)) #define IfFailThenBreak(expect_true, if_fail_then_fail_reason_code) \ if (flow.CurrentState == FlowControl::FAIL || \ flow.__IsFailFc(!!(expect_true), if_fail_then_fail_reason_code, ###expect_true)) break #define SetFailFc(expect_true_but_fail_state, fail_reason_code) \ flow.SetFailFc(fail_reason_code, #expect_true_but_fail_state) #else #define IfFailThen(expect_true, if_fail_then_fail_reason_code) \ if (flow.CurrentState == FlowControl::FAIL || \ flow.__IsFailFc(!!(expect_true), if_fail_then_fail_reason_code)) #define IfFailThenBreak(expect_true, if_fail_then_fail_reason_code) \ if (flow.CurrentState == FlowControl::FAIL || \ flow.__IsFailFc(!!(expect_true), if_fail_then_fail_reason_code)) break #define SetFailFc(expect_true_but_fail_state, fail_reason_code) \ flow.SetFailFc(fail_reason_code) #endif ////////////////////////////////////////////////////////////////////////// // (INTERFACE #3) // (Description) // ÀϹÝÀûÀ¸·Î _ASSERT¿Í °°Àº °ÍÀº release¸ðµå¿¡¼­´Â »ç¿ëµÇÁö ¾Ê´Â´Ù. // ÇÏÁö¸¸ _ASSERTÀÓ¿¡µµ _ASSERT°¡ ¾Æ´Ñ »óȲÀÌ ¹ß»ýÇÑ´Ù. ´ÙÀ½ ·ÎÁ÷µé¿¡ ¹®Á¦°¡ ¹ß»ýÇÔ¿¡µµ // µð¹ö±ëÀÌ ¾ÈµÇ´Â ¹®Á¦°¡ ¹ß»ýÇÑ´Ù. Release¿¡¼­µµ redirectµÈ Çڵ鸵¿¡ ÀÇÇØ º°µµ µ¿ÀÛÀ» ¼öÇàÇÒ ¼ö ÀÖµµ·Ï ±¸¼º // FlowControl::RegisterAssertionHandler »ç¿ëÇÏ¸é µÈ´Ù. // (Sample) // if(FALSE == flow.FCAssert(failCase)) { <- ±âº» Çڵ鷯´Â ÄÜ¼Ö Ãâ·Â, redirectÇÔÀ¸·Î½á º°µµ ·Î±ëÀÌ °¡´É // // error control // } #if _MSC_VER <= 1310 #if defined(_DEBUG) inline static BOOLEAN FCAssert(BOOLEAN must_be_true) { return must_be_true != false; } // (INTERFACE #3.1.1) #define FCAssert(must_be_true) \ FCAssert(( (!!(must_be_true)) || (_assert(###must_be_true, __FILE__, __LINE__), 0) )) #else inline static BOOLEAN FCAssert(char* msg, char* file_name, DWORD line_number) { ms_AssertionHandler(msg, file_name, line_number); return false; } inline static BOOLEAN _Interceptor(BOOLEAN intercept) { return intercept; } // (INTERFACE #3.1.2) #ifdef _SUNGAME_VER //client side¿¡¼­ »ç¿ëÇÏ´Â ¸ÅÅ©·Î (À¯Àú¹èÆ÷¿ë) #define FCAssert(must_be_true) \ _Interceptor(!!(must_be_true)) #else //!defined(_SUNGAME_VER) //client side¿¡¼­ »ç¿ëÇÏ´Â ¸ÅÅ©·Î (À¯Àú¹èÆ÷¿ëÀ» Á¦¿ÜÇÑ ¸ðµç ¹öÀüÀ» ÀǹÌ) #define FCAssert(must_be_true) \ _Interceptor( !!(must_be_true) || FlowControl::FCAssert(###must_be_true, __FILE__, __LINE__) ) #endif #endif #else // to support VS2008 #if defined(_DEBUG) inline static BOOLEAN FCAssert(BOOLEAN must_be_true) { return must_be_true != false; } // (INTERFACE #3.1.1) #define FCAssert(must_be_true) \ FCAssert(( (!!(must_be_true)) || (_wassert(_CRT_WIDE(#must_be_true), _CRT_WIDE(__FILE__), __LINE__), 0) )) #else // to support VS2008 inline static BOOLEAN FCAssert(char* msg, char* file_name, DWORD line_number) { ms_AssertionHandler(msg, file_name, line_number); return false; } inline static BOOLEAN _Interceptor(BOOLEAN intercept) { return intercept; } // (INTERFACE #3.1.2) #ifdef _SUNGAME_VER //client side¿¡¼­ »ç¿ëÇÏ´Â ¸ÅÅ©·Î (À¯Àú¹èÆ÷¿ë) #define FCAssert(must_be_true) \ _Interceptor(!!(must_be_true)) #else //!defined(_SUNGAME_VER) //client side¿¡¼­ »ç¿ëÇÏ´Â ¸ÅÅ©·Î (À¯Àú¹èÆ÷¿ëÀ» Á¦¿ÜÇÑ ¸ðµç ¹öÀüÀ» ÀǹÌ) #define FCAssert(must_be_true) \ _Interceptor( !!(must_be_true) || FlowControl::FCAssert(###must_be_true, __FILE__, __LINE__) ) #endif #endif #endif // ////////////////////////////////////////////////////////////////////////// // typedef void (*AssertionHandler_t)(char* msg, char* file_name, DWORD line_number); static void RegisterAssertionHandler(AssertionHandler_t funcAssertionHandler) { funcAssertionHandler && (ms_AssertionHandler = funcAssertionHandler); } ////////////////////////////////////////////////////////////////////////// // const bool& CurrentState; private: bool current_state_; DWORD error_code_; const char* error_string_; static AssertionHandler_t ms_AssertionHandler; // can't change name to support library dependency __DISABLE_COPY(FlowControl); }; #define FLOWCONTROL_START() switch(FlowControl::LOGIC_BLOCK) { case FlowControl::LOGIC_BLOCK: #define FLOWCONTROL_END } #define ERRORCONTROL_START(flow) switch(flow.GetErrorCode()) #define ERRORCONTROL_END // // //================================================================================================== // // class FlowControl2 { public: FlowControl2() : is_error_(false) , error_code_(0) {} public: void Init() { is_error_ = false, error_code_ = 0; } void SetErrorCode(int n) { SetError(); error_code_ = n; } void GetErrorCode(int& n) { n = (int)error_code_; } void SetErrorCode(DWORD dw) { SetError(); error_code_ = dw; } void GetErrorCode(DWORD& dw) { dw = (DWORD)error_code_; } bool IsError() { return is_error_; } void SetError() { is_error_ = true; } private: bool is_error_; __int64 error_code_; }; #define _S_TRY_SWITCH FLOWCONTROL_START() #define S_TRY FlowControl2 f; _S_TRY_SWITCH #define S_TRY_ f.Init(); _S_TRY_SWITCH #define S_CATCH0() break; } if(f.IsError()) #define S_CATCH(type, e) break; } type e; f.GetErrorCode(e); if(f.IsError()) #define S_THROW0() { f.SetError(); break; } #define S_THROW(e) { f.SetErrorCode(e); break; } #endif //__ERROR_CONTROL_H