New git HEAD version
[libdai.git] / include / dai / exceptions.h
1 /* This file is part of libDAI - http://www.libdai.org/
2 *
3 * Copyright (c) 2006-2011, The libDAI authors. All rights reserved.
4 *
5 * Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
6 */
7
8
9 /// \file
10 /// \brief Defines the Exception class and macros for throwing exceptions and doing assertions
11
12
13 #ifndef __defined_libdai_exceptions_h
14 #define __defined_libdai_exceptions_h
15
16
17 #include <exception>
18 #include <stdexcept>
19 #include <string>
20 #include <iostream>
21
22
23 /// Used by DAI_THROW
24 #define DAI_QUOTE(x) #x
25
26 /// Used by DAI_THROW
27 #define DAI_TOSTRING(x) DAI_QUOTE(x)
28
29 /// Macro that simplifies throwing an exception with a useful default error message.
30 /** The error message consists of a description of the exception, the source
31 * code file and line number where the exception has been thrown.
32 * \param cod Corresponds to one of the enum values of dai::Exception::Code
33 *
34 * \par Example:
35 * \code
36 * DAI_THROW(NOT_IMPLEMENTED);
37 * \endcode
38 */
39 #if defined __GNUG__ // GNU C++
40 #define FUNCTION_NAME __PRETTY_FUNCTION__
41 #elif defined _MSC_VER // Visual Studio
42 #define FUNCTION_NAME __FUNCTION__
43 #else // other compilers
44 #define FUNCTION_NAME __func__
45 #endif
46 #define DAI_THROW(cod) throw dai::Exception(dai::Exception::cod, __FILE__, FUNCTION_NAME, DAI_TOSTRING(__LINE__), "")
47
48 /// Macro that simplifies throwing an exception with a user-defined error message.
49 /** \param cod Corresponds to one of the enum values of dai::Exception::Code
50 * \param msg Detailed error message that will be written to std::cerr.
51 *
52 * \par Example:
53 * \code
54 * DAI_THROWE(NOT_IMPLEMENTED,"Detailed error message");
55 * \endcode
56 */
57 #define DAI_THROWE(cod,msg) throw dai::Exception(dai::Exception::cod, __FILE__, FUNCTION_NAME, DAI_TOSTRING(__LINE__), msg)
58
59 /// Assertion mechanism, similar to the standard assert() macro. It is always active, even if NDEBUG is defined
60 #define DAI_ASSERT(condition) ((condition) ? ((void)0) : DAI_THROWE(ASSERTION_FAILED, std::string("Assertion \"" #condition "\" failed")))
61
62 // Assertion only if DAI_DEBUG is defined
63 #ifdef DAI_DEBUG
64 /// Assertion mechanism similar to DAI_ASSERT which is only active if DAI_DEBUG is defined
65 #define DAI_DEBASSERT(x) do {DAI_ASSERT(x);} while(0)
66 #else
67 #define DAI_DEBASSERT(x) do {} while(0)
68 #endif
69
70
71 namespace dai {
72
73
74 /// Error handling in libDAI is done by throwing an instance of the Exception class.
75 /** The Exception class inherits from std::runtime_error. It defines several types of exceptions
76 * and corresponding error messages. The recommended way to throw an instance of the Exception
77 * class is by using the #DAI_THROW or #DAI_THROWE macros.
78 */
79 class Exception : public std::runtime_error {
80 public:
81 /// Enumeration of exceptions used in libDAI
82 enum Code {NOT_IMPLEMENTED,
83 ASSERTION_FAILED,
84 IMPOSSIBLE_TYPECAST,
85 OBJECT_NOT_FOUND,
86 BELIEF_NOT_AVAILABLE,
87 UNKNOWN_ENUM_VALUE,
88 UNKNOWN_DAI_ALGORITHM,
89 UNKNOWN_PARAMETER_ESTIMATION_METHOD,
90 UNKNOWN_PROPERTY_TYPE,
91 UNKNOWN_PROPERTY,
92 MALFORMED_PROPERTY,
93 NOT_ALL_PROPERTIES_SPECIFIED,
94 INVALID_ALIAS,
95 CANNOT_READ_FILE,
96 CANNOT_WRITE_FILE,
97 INVALID_FACTORGRAPH_FILE,
98 INVALID_EVIDENCE_FILE,
99 INVALID_EMALG_FILE,
100 NOT_NORMALIZABLE,
101 MULTIPLE_UNDO,
102 FACTORGRAPH_NOT_CONNECTED,
103 INTERNAL_ERROR,
104 RUNTIME_ERROR,
105 OUT_OF_MEMORY,
106 NUM_ERRORS}; // NUM_ERRORS should be the last entry
107
108 /// Constructor
109 Exception( Code code, const char *filename, const char *function, const char *line, const std::string& detailedMsg ) :
110 std::runtime_error(ErrorStrings[code] + (detailedMsg.empty() ? "" : (": " + detailedMsg)) + " [File " + filename + ", line " + line + ", function: " + function + "]"),
111 _errorcode(code), _detailedMsg(detailedMsg), _filename(filename), _function(function), _line(line) {}
112
113 /// Destructor
114 ~Exception() throw () {}
115
116 /// Returns error code of this exception
117 Code getCode() const { return _errorcode; }
118
119 /// Returns error code of this exception
120 /** \deprecated Please use dai::Exceptions::getCode() instead
121 */
122 Code code() const { return getCode(); }
123
124 /// Returns short error message of this exception
125 const std::string& getMsg() const { return ErrorStrings[_errorcode]; }
126
127 /// Returns detailed error message of this exception
128 const std::string& getDetailedMsg() const { return _detailedMsg; }
129
130 /// Returns filename where this exception was thrown
131 const std::string& getFilename() const { return _filename; }
132
133 /// Returns function name in which this exception was thrown
134 const std::string& getFunction() const { return _function; }
135
136 /// Returns line number where this exception was thrown
137 const std::string& getLine() const { return _line; }
138
139 /// Returns error message corresponding to an error code
140 const std::string& message( const Code c ) const { return ErrorStrings[c]; }
141
142 private:
143 /// Contains the error code of this exception
144 Code _errorcode;
145
146 /// Contains the detailed message of this exception, if any
147 std::string _detailedMsg;
148
149 /// Contains the filename where this exception was thrown
150 std::string _filename;
151
152 /// Contains the function name in which this exception was thrown
153 std::string _function;
154
155 /// Contains the line number where this exception was thrown
156 std::string _line;
157
158 /// Error messages corresponding to the exceptions enumerated above
159 static std::string ErrorStrings[NUM_ERRORS];
160 };
161
162
163 }
164
165
166 #endif