1 /* Copyright (C) 2013 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef INCLUDED_ERRORS 19 #define INCLUDED_ERRORS 20 21 /* 22 23 The overly-complex error system works as follows: 24 25 A source file (typically a .h) can declare errors as follows: 26 27 ERROR_GROUP(ModuleName); 28 ERROR_TYPE(ModuleName, FrobnificationFailed); 29 ERROR_SUBGROUP(ModuleName, ComponentName); 30 ERROR_TYPE(ModuleName_ComponentName, FileNotFound); 31 32 etc, to build up a hierarchy of error types. 33 34 Then you have to run the /build/errorlist/errorlist.pl script, to regenerate 35 the Errors.cpp file. 36 37 Then you can use the declared errors as an error code: 38 39 PSRETURN foo() { return PSRETURN_ModuleName_FrobnificationFailed; } 40 41 if (ret != PSRETURN_OK) 42 ... // something failed 43 44 if (ret) 45 ... // something failed 46 47 if (ret == PSRETURN_ModuleName_FrobnificationFailed) 48 ... // particular error 49 50 if (ERROR_IS(ret, PSRETURN_ModuleName)) 51 ... // matches any type PSRETURN_ModuleName_* (and PSRETURN_ModuleName_*_* etc) 52 53 And you can use it as an exception: 54 55 void foo() { throw PSERROR_ModuleName_FrobnificationFailed(); } 56 57 void bar() { throw PSERROR_ModuleName_FrobnificationFailed("More informative message"); } 58 59 try { 60 foo(); 61 } catch (PSERROR_ModuleName_FrobnificationFailed& e) { 62 // catches that particular error type 63 } catch (PSERROR_ModuleName& e) { 64 // catches anything in the hierarchy 65 } catch (PSERROR& e) { 66 std::cout << e.what(); 67 } 68 69 plus a few extra things for converting between error codes and exceptions. 70 71 */ 72 73 #include <exception> 74 75 typedef u32 PSRETURN; 76 77 class PSERROR : public std::exception 78 { 79 public: 80 PSERROR(const char* msg); 81 virtual const char* what() const throw (); 82 virtual PSRETURN getCode() const = 0; // for functions that catch exceptions then return error codes 83 private: 84 const char* m_msg; 85 }; 86 87 #define ERROR_GROUP(a) class PSERROR_##a : public PSERROR { protected: PSERROR_##a(const char* msg); }; \ 88 extern const PSRETURN MASK__PSRETURN_##a; \ 89 extern const PSRETURN CODE__PSRETURN_##a 90 91 #define ERROR_SUBGROUP(a,b) class PSERROR_##a##_##b : public PSERROR_##a { protected: PSERROR_##a##_##b(const char* msg); }; \ 92 extern const PSRETURN MASK__PSRETURN_##a##_##b; \ 93 extern const PSRETURN CODE__PSRETURN_##a##_##b 94 95 96 #define ERROR_TYPE(a,b) class PSERROR_##a##_##b : public PSERROR_##a { public: PSERROR_##a##_##b(); PSERROR_##a##_##b(const char* msg); PSRETURN getCode() const; }; \ 97 extern const PSRETURN MASK__PSRETURN_##a##_##b; \ 98 extern const PSRETURN CODE__PSRETURN_##a##_##b; \ 99 extern const PSRETURN PSRETURN_##a##_##b 100 101 #define ERROR_IS(a, b) ( ((a) & MASK__PSRETURN_##b) == CODE__PSRETURN_##b ) 102 103 const PSRETURN PSRETURN_OK = 0; 104 const PSRETURN MASK__PSRETURN_OK = 0xFFFFFFFF; 105 const PSRETURN CODE__PSRETURN_OK = 0; 106 107 const char* GetErrorString(PSRETURN code); 108 void ThrowError(PSRETURN code); 109 110 #endif 111