1 // Copyright (C) 2009-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #ifndef EXCEPTIONS_H
8 #define EXCEPTIONS_H 1
9 
10 #include <stdexcept>
11 #include <string>
12 #include <sstream>
13 
14 namespace isc {
15 
16 ///
17 /// This is a base class for exceptions thrown from the DNS library module.
18 /// Normally, the exceptions are thrown via a convenient shortcut macro,
19 /// @ref isc_throw, which automatically gives trivial parameters for the
20 /// exception such as the file name and line number where the exception is
21 /// triggered.
22 ///
23 class Exception : public std::exception {
24 public:
25     ///
26     /// \name Constructors and Destructor
27     ///
28     //@{
29     /// \brief Constructor for a given type for exceptions with file name and
30     /// file line number.
31     ///
32     /// @param file the file name where the exception was thrown.
33     /// @param line the line in \a file where the exception was thrown.
34     /// @param what a description (type) of the exception.
35     Exception(const char* file, size_t line, const char* what);
36 
37     /// \brief Constructor for a given type for exceptions with file name and
38     /// file line number.
39     ///
40     /// @param file the file name where the exception was thrown.
41     /// @param line the line in \a file where the exception was thrown.
42     /// @param what a description (type) of the exception.
43     Exception(const char* file, size_t line, const std::string& what);
44 
45     /// The destructor
~Exception()46     virtual ~Exception() throw() {}
47     //@}
48 private:
49     ///
50     /// The assignment operator is intentionally disabled.
51     ///
52     void operator=(const Exception& src);
53 
54 public:
55     ///
56     /// \name Methods Reimplemented against the Standard Exception Class
57     ///
58     //@{
59     /// \brief Returns a C-style character string of the cause of the exception.
60     ///
61     /// Note: we normally don't use exception specifications, but this is an
62     /// "exception" to that policy as it's enforced by the base class.
63     ///
64     /// @return A C-style character string of the exception cause.
65     virtual const char* what() const throw();
66 
67     /// \brief Returns a C-style character string of the cause of exception.
68     ///
69     /// With verbose set to true, also returns file name and line numbers.
70     /// Note that we can't simply define a single what() method with parameters,
71     /// as the compiler would complain that it shadows the base class method.
72     ///
73     /// \param verbose if set to true, filename and line number will be added.
74     /// \return A C-style character string of the exception cause.
75     virtual const char* what(bool verbose) const throw();
76     //@}
77 
78     ///
79     /// \name Getter Methods
80     ///
81     //@{
82     /// \brief Gets a string describing the cause of the exception.
83     ///
84     /// @return the cause string.
getMessage()85     const std::string& getMessage() const { return (what_); }
86 
87     /// \brief Gets the file name where the exception was thrown.
88     ///
89     /// @return a C-style string of the file name.
getFile()90     const char* getFile() const { return (file_); }
91 
92     /// \brief Gets the line number of the file where the exception was thrown.
93     ///
94     /// @return an integer specifying the line number.
getLine()95     size_t getLine() const { return (line_); }
96     //@}
97 
98 private:
99 
100     /// Specifies the filename where this exception was raised
101     const char* const file_;
102 
103     /// Specifies the line number where this exception was raised
104     size_t line_;
105 
106     /// Specifies actual content of the exception
107     const std::string what_;
108 
109     /// Specifies actual context of the exception (with file:line added)
110     std::string verbose_what_;
111 };
112 
113 /// \brief A generic exception that is thrown if a parameter given
114 /// to a method would refer to or modify out-of-range data.
115 class OutOfRange : public Exception {
116 public:
OutOfRange(const char * file,size_t line,const char * what)117     OutOfRange(const char* file, size_t line, const char* what) :
118         isc::Exception(file, line, what) {}
119 };
120 
121 /// \brief A generic exception that is thrown if a parameter given
122 /// to a method or function is considered invalid and no other specific
123 /// exceptions are suitable to describe the error.
124 class InvalidParameter : public Exception {
125 public:
InvalidParameter(const char * file,size_t line,const char * what)126     InvalidParameter(const char* file, size_t line, const char* what) :
127         isc::Exception(file, line, what) {}
128 };
129 
130 /// \brief A generic exception that is thrown if a parameter given
131 /// to a method is considered invalid in that context.
132 class BadValue : public Exception {
133 public:
BadValue(const char * file,size_t line,const char * what)134     BadValue(const char* file, size_t line, const char* what) :
135         isc::Exception(file, line, what) {}
136 };
137 
138 /// \brief A generic exception that is thrown if a function is called
139 /// in a prohibited way.
140 ///
141 /// For example, this can happen if a class method is called when the object's
142 /// state does not allow that particular method.
143 class InvalidOperation : public Exception {
144 public:
InvalidOperation(const char * file,size_t line,const char * what)145     InvalidOperation(const char* file, size_t line, const char* what) :
146         isc::Exception(file, line, what) {}
147 };
148 
149 ///
150 /// \brief A generic exception that is thrown when an unexpected
151 /// error condition occurs.
152 ///
153 class Unexpected : public Exception {
154 public:
Unexpected(const char * file,size_t line,const char * what)155     Unexpected(const char* file, size_t line, const char* what) :
156         isc::Exception(file, line, what) {}
157 };
158 
159 ///
160 /// \brief A generic exception that is thrown when a function is
161 /// not implemented.
162 ///
163 /// This may be due to unfinished implementation or in case the
164 /// function isn't even planned to be provided for that situation,
165 /// i.e. not yet implemented or not supported.
166 class NotImplemented : public Exception {
167 public:
NotImplemented(const char * file,size_t line,const char * what)168     NotImplemented(const char* file, size_t line, const char* what) :
169         isc::Exception(file, line, what) {}
170 };
171 
172 ///
173 /// \brief A generic exception that is thrown when an object can
174 /// not be found.
175 class NotFound : public Exception {
176 public:
NotFound(const char * file,size_t line,const char * what)177     NotFound(const char* file, size_t line, const char* what) :
178         isc::Exception(file, line, what) {}
179 };
180 
181 /// \brief Exception thrown when a worker thread is trying to stop or pause the
182 /// respective thread pool (which would result in a dead-lock).
183 class MultiThreadingInvalidOperation : public Exception {
184 public:
MultiThreadingInvalidOperation(const char * file,size_t line,const char * what)185     MultiThreadingInvalidOperation(const char* file, size_t line, const char* what) :
186         isc::Exception(file, line, what) {};
187 };
188 
189 ///
190 /// A shortcut macro to insert known values into exception arguments.
191 ///
192 /// It allows the \c stream argument to be part of a statement using an
193 /// \c ostream object and its \c operator<<.  For example,
194 /// \code int x = 10;
195 /// isc_throw(SomeException, "Error happened, parameter: " << x);
196 /// \endcode
197 /// will throw an exception of class \c SomeException whose \c what string
198 /// will be <code>"Error happened, parameter: 10"</code>.
199 ///
200 /// Note: the stream related operations or creation of the exception object
201 /// may itself throw an exception (specifically \c std::bad_alloc).
202 /// Even though it should be very rare, we may have to address this issue later.
203 ///
204 /// Note: in general we hate macros and avoid using it in the code.  This is
205 /// one of few exceptions to that policy.  inline functions cannot be used
206 /// for embedding \c __FILE__ and \c __LINE__.  This is the main reason why
207 /// this is defined as a macro.  The convenience for the ostream is a secondary
208 /// purpose (if that were the only possible reason we should rather avoid
209 /// using a macro).
210 #define isc_throw(type, stream) \
211     do { \
212         std::ostringstream oss__; \
213         oss__ << stream; \
214         throw type(__FILE__, __LINE__, oss__.str().c_str()); \
215     } while (1)
216 
217 ///
218 /// Similar as isc_throw, but allows the exception to have one additional
219 /// parameter (the stream/text goes first)
220 #define isc_throw_1(type, stream, param1) \
221     do { \
222         std::ostringstream oss__; \
223         oss__ << stream; \
224         throw type(__FILE__, __LINE__, oss__.str().c_str(), param1); \
225     } while (1)
226 
227 ///
228 /// Similar as isc_throw, but allows the exception to have two additional
229 /// parameters (the stream/text goes first)
230 #define isc_throw_2(type, stream, param1, param2) \
231     do { \
232         std::ostringstream oss__; \
233         oss__ << stream; \
234         throw type(__FILE__, __LINE__, oss__.str().c_str(), param1, param2); \
235     } while (1)
236 
237 ///
238 /// Similar as isc_throw, but allows the exception to have three additional
239 /// parameters (the stream/text goes first)
240 #define isc_throw_3(type, stream, param1, param2, param3) \
241     do { \
242         std::ostringstream oss__; \
243         oss__ << stream; \
244         throw type(__FILE__, __LINE__, oss__.str().c_str(), param1, param2,\
245                    param3); \
246     } while (1)
247 
248 ///
249 /// Similar as isc_throw, but allows the exception to have four additional
250 /// parameters (the stream/text goes first)
251 #define isc_throw_4(type, stream, param1, param2, param3, param4) \
252     do { \
253         std::ostringstream oss__; \
254         oss__ << stream; \
255         throw type(__FILE__, __LINE__, oss__.str().c_str(), param1, param2,\
256                    param3, param4); \
257     } while (1)
258 
259 }
260 #endif // EXCEPTIONS_H
261 
262 // Local Variables:
263 // mode: c++
264 // End:
265