src/zserio/CppRuntimeException.h
Line | Count | Source |
1 | | #ifndef ZSERIO_CPP_RUNTIME_EXCEPTION_H_INC |
2 | | #define ZSERIO_CPP_RUNTIME_EXCEPTION_H_INC |
3 | | |
4 | | #include <array> |
5 | | #include <exception> |
6 | | #include <string> |
7 | | #include <type_traits> |
8 | | #include <vector> |
9 | | |
10 | | #include "zserio/Span.h" |
11 | | #include "zserio/StringConvertUtil.h" |
12 | | #include "zserio/Traits.h" |
13 | | |
14 | | namespace zserio |
15 | | { |
16 | | |
17 | | /** |
18 | | * Exception thrown when an error within the Zserio C++ runtime library occurs. |
19 | | */ |
20 | | class CppRuntimeException : public std::exception |
21 | | { |
22 | | public: |
23 | | /** |
24 | | * Constructor. |
25 | | * |
26 | | * \param message Description of the error. |
27 | | */ |
28 | | explicit CppRuntimeException(const char* message = ""); |
29 | | |
30 | | /** |
31 | | * Method generated by default. |
32 | | * \{ |
33 | | */ |
34 | 33.9k | ~CppRuntimeException() override = default; |
35 | | |
36 | | CppRuntimeException(const CppRuntimeException& other) = default; |
37 | 113 | CppRuntimeException& operator=(const CppRuntimeException& other) = default; |
38 | | |
39 | 16.8k | CppRuntimeException(CppRuntimeException&& other) = default; |
40 | 2 | CppRuntimeException& operator=(CppRuntimeException&& other) = default; |
41 | | /** |
42 | | * \} |
43 | | */ |
44 | | |
45 | | const char* what() const noexcept override; |
46 | | |
47 | | /** |
48 | | * Appends a message to the description. |
49 | | * |
50 | | * \param message Description of the error to append. |
51 | | */ |
52 | | void append(const char* message); |
53 | | |
54 | | /** |
55 | | * Appends a message of a known length to the description. |
56 | | * |
57 | | * \param message Description of the error to append. |
58 | | * \param messageLen Length of the message. |
59 | | */ |
60 | | void append(const char* message, size_t messageLen); |
61 | | |
62 | | private: |
63 | | void appendImpl(Span<const char> message); |
64 | | |
65 | | std::array<char, 512> m_buffer; // note fixed sized array is deeply copied on copy operations and it's OK |
66 | | size_t m_len = 0; |
67 | | }; |
68 | | |
69 | | /** |
70 | | * Appends a message to the exception's description. |
71 | | * |
72 | | * \param exception Exception to modify. |
73 | | * \param message Description of the error to append. |
74 | | * |
75 | | * \return Reference to the exception to allow operator chaining. |
76 | | */ |
77 | | CppRuntimeException& operator<<(CppRuntimeException& exception, const char* message); |
78 | | |
79 | | /** |
80 | | * Appends a bool value to the exception's description. |
81 | | * |
82 | | * \param exception Exception to modify. |
83 | | * \param value Bool value to append. |
84 | | * |
85 | | * \return Reference to the exception to allow operator chaining. |
86 | | */ |
87 | | CppRuntimeException& operator<<(CppRuntimeException& exception, bool value); |
88 | | |
89 | | /** |
90 | | * Appends a float value to the exception's description. |
91 | | * |
92 | | * \param exception Exception to modify. |
93 | | * \param value Float value to append. |
94 | | * |
95 | | * \return Reference to the exception to allow operator chaining. |
96 | | */ |
97 | | CppRuntimeException& operator<<(CppRuntimeException& exception, float value); |
98 | | |
99 | | /** |
100 | | * Appends a double value to the exception's description. |
101 | | * |
102 | | * \param exception Exception to modify. |
103 | | * \param value Double value to append. |
104 | | * |
105 | | * \return Reference to the exception to allow operator chaining. |
106 | | */ |
107 | | CppRuntimeException& operator<<(CppRuntimeException& exception, double value); |
108 | | |
109 | | /** |
110 | | * Appends an integral value to the exception's description. |
111 | | * |
112 | | * \param exception Exception to modify. |
113 | | * \param value Integral value to append. |
114 | | * |
115 | | * \return Reference to the exception to allow operator chaining. |
116 | | */ |
117 | | template <typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> |
118 | | CppRuntimeException& operator<<(CppRuntimeException& exception, T value) |
119 | 1.92k | { |
120 | 1.92k | std::array<char, 24> buffer = {}; |
121 | 1.92k | const char* stringValue = convertIntToString(buffer, value); |
122 | 1.92k | return exception << stringValue; |
123 | 1.92k | } |
124 | | |
125 | | /** |
126 | | * Appends any object which implement getValue() method (e.g. bitmask) to the exception's description. |
127 | | * |
128 | | * \param exception Exception to modify. |
129 | | * \param value Object with getValue() method to append. |
130 | | * |
131 | | * \return Reference to the exception to allow operator chaining. |
132 | | */ |
133 | | template <typename T, typename std::enable_if<is_bitmask<T>::value, int>::type = 0> |
134 | | CppRuntimeException& operator<<(CppRuntimeException& exception, T value) |
135 | 1 | { |
136 | 1 | exception << value.getValue(); |
137 | 1 | return exception; |
138 | 1 | } |
139 | | |
140 | | /** |
141 | | * Appends a string value to the exception's description. |
142 | | * |
143 | | * \param exception Exception to modify. |
144 | | * \param value String value to append. |
145 | | * |
146 | | * \return Reference to the exception to allow operator chaining. |
147 | | */ |
148 | | template <typename ALLOC> |
149 | | CppRuntimeException& operator<<( |
150 | | CppRuntimeException& exception, const std::basic_string<char, std::char_traits<char>, ALLOC>& value) |
151 | 5 | { |
152 | 5 | exception.append(value.c_str(), value.size()); |
153 | 5 | return exception; |
154 | 5 | } |
155 | | |
156 | | /** |
157 | | * Appends a vector value to the exception's description. |
158 | | * |
159 | | * \param exception Exception to modify. |
160 | | * \param value Vector value to append. |
161 | | * |
162 | | * \return Reference to the exception to allow operator chaining. |
163 | | */ |
164 | | template <typename T, typename ALLOC> |
165 | | CppRuntimeException& operator<<(CppRuntimeException& exception, const std::vector<T, ALLOC>& value) |
166 | 1 | { |
167 | 1 | return exception << "vector([...], " << value.size() << ")"; |
168 | 1 | } |
169 | | |
170 | | namespace detail |
171 | | { |
172 | | |
173 | | // inspired by C++ ostreams - see https://cplusplus.github.io/LWG/issue1203 |
174 | | // note that e.g. in gcc implementation of ostreams there are two constraints, but the second one: |
175 | | // typename = decltype(std::declval<EXCEPTION&>() << std::declval<const VALUE&>()) |
176 | | // is probably unnecessary and since it caused a compilation error in MSVC 2017 Conformance Mode, |
177 | | // we intentionally skipped it (even though it was probably a compiler bug) |
178 | | template <typename EXCEPTION, typename VALUE, |
179 | | typename = typename std::enable_if<std::is_base_of<CppRuntimeException, EXCEPTION>::value, int>::type> |
180 | | using CppRuntimeExceptionRValueInsertion = EXCEPTION&&; |
181 | | |
182 | | } // namespace detail |
183 | | |
184 | | /** |
185 | | * Appends any value for which operator<< is implemented to the exception's description. |
186 | | * |
187 | | * Overload for rvalue to enable operator<< on a temporary object, .e.g. CppRuntimeException() << "value". |
188 | | * Moreover note that this overload preserves the concrete type of the exception! |
189 | | * |
190 | | * \param exception Exception to modify. |
191 | | * \param value Value to append. |
192 | | * |
193 | | * \return R-value reference to the original exception to allow operator chaining. |
194 | | */ |
195 | | template <typename CPP_RUNTIME_EXCEPTION, typename T> |
196 | | detail::CppRuntimeExceptionRValueInsertion<CPP_RUNTIME_EXCEPTION, T> operator<<( |
197 | | CPP_RUNTIME_EXCEPTION&& exception, const T& value) |
198 | 35.1k | { |
199 | 35.1k | exception << value; |
200 | 35.1k | return std::forward<CPP_RUNTIME_EXCEPTION>(exception); |
201 | 35.1k | } |
202 | | |
203 | | } // namespace zserio |
204 | | |
205 | | #endif // ifndef ZSERIO_CPP_RUNTIME_EXCEPTION_H_INC |