Branch data Line data Source code
1 : : /******************************************************************************
2 : : ------------- Copyright (c) 2009-2023 H a r a l d A c h i t z ---------------
3 : : ---------- < h a r a l d dot a c h i t z at g m a i l dot c o m > ------------
4 : : ---- This Source Code Form is subject to the terms of the Mozilla Public -----
5 : : ---- License, v. 2.0. If a copy of the MPL was not distributed with this -----
6 : : ---------- file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------
7 : : ******************************************************************************/
8 : :
9 : : #ifndef SL3__ERROR_HPP_
10 : : #define SL3__ERROR_HPP_
11 : :
12 : : #include <exception>
13 : : #include <iosfwd>
14 : : #include <stdexcept>
15 : : #include <string>
16 : :
17 : : #include <sl3/config.hpp>
18 : :
19 : : namespace sl3
20 : : {
21 : : /**
22 : : * \brief Error codes
23 : : *
24 : : * These enum values are used to create ErrType objects.
25 : : *
26 : : * Each ErrCode becomes an ErrType object.
27 : : *
28 : : */
29 : : enum class ErrCode
30 : : {
31 : : SQL3Error = 1, ///< sqlite3 error happened
32 : : NoConnection = 2, ///< no database
33 : : OutOfRange = 5, ///< index op out of range
34 : : TypeMisMatch = 6, ///< type cast problem
35 : : NullValueAccess = 7, ///< accessing a value that is Null
36 : : UNEXPECTED = 99 ///< for everything that happens unexpected
37 : : };
38 : :
39 : : /**
40 : : * \brief Get the textual representation (the name) of an ErrCode
41 : : * \param ec
42 : : * wanted ErrCode name
43 : : * \return the ErrCode name
44 : : */
45 : : constexpr const char*
46 : 9 : ErrCodeName (ErrCode ec)
47 : : {
48 : 17 : return ec == ErrCode::SQL3Error ? "SQLite3Error"
49 : 15 : : ec == ErrCode::NoConnection ? "NoConnection"
50 : 13 : : ec == ErrCode::OutOfRange ? "OutOfRange"
51 : 8 : : ec == ErrCode::TypeMisMatch ? "TypeMisMatch"
52 : 3 : : ec == ErrCode::NullValueAccess ? "NullValueAccess"
53 : 1 : : ec == ErrCode::UNEXPECTED ? "UNEXPECTED"
54 : 9 : : "NA";
55 : : }
56 : :
57 : : /**
58 : : * \brief Exception base type
59 : : *
60 : : * A common base for all ErrType objects.
61 : : * All exceptions thrown by the
62 : : * library will have this base type.
63 : : */
64 : : class LIBSL3_API Error : public std::runtime_error
65 : : {
66 : : protected:
67 : : public:
68 : : /// Inherit constructors from std::runtime_error
69 : : using std::runtime_error::runtime_error;
70 : :
71 : : /**
72 : : * \brief Get ErrCode
73 : : * \return the ErrCode of the exception
74 : : */
75 : : virtual ErrCode getId () const = 0;
76 : : };
77 : :
78 : : /**
79 : : * \brief Overloaded stream operator
80 : : * \param os ostream
81 : : * \param e the Error
82 : : * \return the ostream
83 : : */
84 : : LIBSL3_API std::ostream& operator<< (std::ostream& os, const Error& e);
85 : :
86 : : /**
87 : : * \brief Object class representing an ErrCode
88 : : *
89 : : * Allows typedefs using an ErrCode.
90 : : * Each sl3::ErrCode becomes
91 : : * an ErrType object.
92 : : */
93 : : template <ErrCode ec> class LIBSL3_API ErrType final : public Error
94 : : {
95 : : public:
96 : 54 : ErrType ()
97 : 54 : : Error ("")
98 : : {
99 : 54 : }
100 : :
101 : : using Error::Error;
102 : :
103 : : ErrCode
104 : 8 : getId () const override
105 : : {
106 : 8 : return ec;
107 : : }
108 : : };
109 : :
110 : : /// error that will be thrown if no open database was available but needed
111 : : using ErrNoConnection = ErrType<ErrCode::NoConnection>;
112 : :
113 : : /// thrown if an index op is out of range
114 : : using ErrOutOfRange = ErrType<ErrCode::OutOfRange>;
115 : :
116 : : /**
117 : : * \brief thrown in case of an incorrect type usage
118 : : */
119 : : using ErrTypeMisMatch = ErrType<ErrCode::TypeMisMatch>;
120 : :
121 : : /// thrown in case of accessing a Null value field/parameter
122 : : using ErrNullValueAccess = ErrType<ErrCode::NullValueAccess>;
123 : :
124 : : /// thrown if something unexpected happened, mostly used by test tools and in
125 : : /// debug mode
126 : : using ErrUnexpected = ErrType<ErrCode::UNEXPECTED>;
127 : :
128 : : /**
129 : : * \brief Package an error from sqlite3.
130 : : * This exception will be thrown if sqlite3 reports an error.
131 : : *
132 : : * Holds the sqlite3 error code and the error message if it is available.
133 : : * \see Database::getMostRecentErrMsg
134 : : * \see Database::getMostRecentErrCode
135 : : *
136 : : * \n Extended error codes can be obtained through Database class.
137 : : * \see Database::getMostRecentExtendedErrCode
138 : : * \see Database::enableExtendedResultCodes
139 : : *
140 : : */
141 : : template <> class LIBSL3_API ErrType<ErrCode::SQL3Error> final : public Error
142 : : {
143 : : public:
144 : : /**
145 : : * \brief c'tor
146 : : * \param sl3ec sqlite error code
147 : : * \param sl3msg sqlite error
148 : : * message
149 : : * \param msg additional message
150 : : */
151 : 17 : ErrType (int sl3ec, const char* sl3msg, const std::string& msg)
152 : 34 : : Error ("(" + std::to_string (sl3ec) + ":" + sl3msg + "):" + msg)
153 : 17 : , _sqlite_ec (sl3ec)
154 : 68 : , _sqlite_msg (sl3msg)
155 : : {
156 : 17 : }
157 : :
158 : : /**
159 : : * \brief c'tor
160 : : * \param sl3ec sqlite error code
161 : : * \param sl3msg sqlite error
162 : : * message
163 : : */
164 : 17 : ErrType (int sl3ec, const char* sl3msg)
165 : 34 : : ErrType (sl3ec, sl3msg, "")
166 : : {
167 : 17 : }
168 : : ErrCode
169 : 1 : getId () const override
170 : : {
171 : 1 : return ErrCode::SQL3Error;
172 : : }
173 : :
174 : : /**
175 : : * \brief Get the sqlite3 error code
176 : : * \return the sqlite3 error code
177 : : */
178 : : int
179 : : SQLiteErrorCode () const
180 : : {
181 : : return _sqlite_ec;
182 : : }
183 : :
184 : : /**
185 : : * \brief Get the sqlite3 error message.
186 : : *
187 : : * If the exception was created with a sqlite error message,
188 : : * it can
189 : : * be accessed here.
190 : : *
191 : : * \return the sqlite3 error message
192 : : */
193 : : const std::string&
194 : : SQLiteErrorMessage () const
195 : : {
196 : : return _sqlite_msg;
197 : : };
198 : :
199 : : private:
200 : : int _sqlite_ec;
201 : : std::string _sqlite_msg;
202 : : };
203 : :
204 : : /**
205 : : * \brief Alias for ErrType<ErrCode::SQL3Error>
206 : : *
207 : : * A short alias for an ErrType<ErrCode::SQL3Error>
208 : : */
209 : : using SQLite3Error = ErrType<ErrCode::SQL3Error>;
210 : :
211 : : #define ASSERT_EXCEPT(exp, except) \
212 : : if (!(exp)) \
213 : : throw except (std::string (__FUNCTION__) + ": " + #exp)
214 : :
215 : : /*
216 : : TODO check if this can be done, together with __FUNCTION__,
217 : : into a nice
218 : : code location for clearer messages
219 : : File.cpp::Function::39 The problem
220 : :
221 : :
222 : : using cstr = const char * const;
223 : :
224 : : static constexpr cstr past_last_slash(cstr str, cstr last_slash)
225 : : {
226 : : return
227 : : *str == '\0' ? last_slash :
228 : : *str == '/' ? past_last_slash(str + 1, str + 1) :
229 : : past_last_slash(str + 1, last_slash);
230 : : }
231 : :
232 : : static constexpr cstr past_last_slash(cstr str)
233 : : {
234 : : return past_last_slash(str, str);
235 : : }
236 : :
237 : : #define __SHORT_FILE__ ({constexpr cstr sf__ {past_last_slash(__FILE__)};
238 : : sf__;})
239 : :
240 : : */
241 : :
242 : : } // ns
243 : :
244 : : #endif /* ...ERROR_HPP_ */
|