ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
exception.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_exceptions of the \aliblong.
4///
5/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace exceptions {
9
10/// Internal details of namespace #"alib::exceptions;2".
11namespace detail
12{
13/// An element of the (single) linked list of message entries of class exception.
14/// A pointer to this type is used as the template parameter \p{T} of
15/// struct #"TSharedMonoVal" that class #"exc Exception" is derived from
16/// and this way allocated (self-contained) in a #"MonoAllocator".
18 Message message; ///< The message,
19 ExceptionEntry* next = nullptr; ///< A pointer to the next message.
20};
21}
22
23//==================================================================================================
24/// An #"alib_enums_records;ALib Enum Record" type used to equip custom enumeration types
25/// with records that define an entries of class #"exc Exception".
26///
27/// Besides the exception entry name, the only field this record adds provides a textual description
28/// of an exception entry.
29/// If the type trait #"ResourcedTraits" is likewise specialized
30/// for a custom enumeration type, then this field is interpreted as a resource name to load the
31/// description from.
32///
33/// When parsing the enum records from string data, inherited field
34/// #"ERSerializable::MinimumRecognitionLength;*" is not parsed from the string, but set to
35/// fixed value \c 0. Therefore, only three fields have to be given per record:
36///
37/// 1. The custom integral enum value (this is mandatory with every resourced enum record).
38/// 2. A string denoting inherited field #"ERSerializable::EnumElementName;*".
39/// 3. A string containing the description text, respectively the resource name of that.
40//==================================================================================================
42 /// The description of the exception.
43 /// \note
44 /// If the type trait #"ResourcedTraits" is specialized for an
45 /// enumeration, this field is interpreted as a resource name to load the description from.
47
48 /// Default constructor leaving the record undefined.
49 ERException() noexcept =default;
50
51
52 /// Constructor usually used with static variable declarations (declarations that are not
53 /// using enumeration types associated with #"alib_enums_records;ALib Enum Records" of this
54 /// type).
55 ///
56 /// If used however to define an enum record during bootstrap of software (by user code
57 /// that omits the preferred option of parsing resourced strings to create such records), then
58 /// each parameter of type #"%^String" passed, has to be of "static nature".
59 /// This means, that string buffers and their contents are deemed to survive the life-cycle of
60 /// an application. Usually, C++ string literals are passed in such situation.
61 /// @param name The name of the exception. (Usually the enum element's C++ name.)
62 /// @param description The exception's descrption. (Usually a format string.)
63 ERException(const String& name, const String& description) noexcept
64 : ERSerializable(name)
65 , DescriptionOrItsResourceName(description) {}
66
67 /// Implementation of #"EnumRecordPrototype::Parse;*".
68 /// \note Field #"ERSerializable::MinimumRecognitionLength;*" is not read from the
69 /// string, but set to fixed value \c 0.
71 void Parse();
72};
73
74//==================================================================================================
75/// The (one and only) <em>"throwable"</em> used with \aliblong.
76///
77/// Please consult the Programmer's Manual of module \alib_exceptions for
78/// #"alib_exceptions_exceptions;detailed information" about this class and its use.
79///
80/// In short, this class implements the following "exception paradigm":
81/// - There is only one exception type.
82/// - That type stores a forward list of #"Message;messages".
83/// - With creation, a first message is added to the list of messages.
84/// - While unwinding the stack, new messages may be added to the list.
85/// - A new message may either add information to the previous entry or may change the meaning
86/// of the exception.
87/// - Messages contain IDs of #"Enum;arbitrary scoped enumeration types".
88/// This allows structured processing of Exceptions.
89///
90/// This type uses a smart memory model leveraging class #"TSharedMonoVal"
91/// which places all internal data in a first buffer of a #"TMonoAllocator",
92/// even the #"%exc Exception" object itself!
93/// With that, exceptions usually perform only one single dynamic allocation, even if various
94/// messages with various data objects (#"Box;boxes") are attached.
95/// Only when many messages are added, a next allocation might occur.
96/// The allocation size of the monotonic buffers is set to be one kilobyte.
97///
98/// Although the footprint (<c>sizeof</c>) of the class is just the size of a pointer
99/// (One into the first memory buffer of the monotonic allocator), objects of this type should be
100/// caught as references. Once caught, copies may be stored for later logging or similar.
101///
102/// @see Chapter #"alib_exceptions_exceptions" of the Programmer's Manual of
103/// camp \alib_exceptions_nl.
104//==================================================================================================
105class Exception : protected monomem::TSharedMonoVal<detail::ExceptionEntry*, HeapAllocator, void> {
106 protected:
107 /// Shortcut to the parent class.
109
110 public:
111 /// Deleted copy constructor. Exceptions must be caught only as references.
112 Exception( const Exception& ) noexcept =default;
113
114 /// Defaulted move constructor.
115 /// @param src The object to move.
116 Exception(Exception&& src) noexcept =default;
117
118 /// Defaulted copy assignment operator.
119 /// @return Nothing (deleted).
120 Exception& operator=( const Exception& ) noexcept =default;
121
122 /// Defaulted move assignment operator.
123 /// @return Nothing (deleted).
124 Exception& operator=( Exception&& ) noexcept =default;
125
126 /// Defaulted destructor.
127 ~Exception() noexcept =default;
128
129 /// Defaulted default constructor.
130 Exception() noexcept =default;
131
132 /// Constructs an empty instance from \c std::nullptr.
133 /// This constructor is necessary to allow assignment of \c nullptr to values of this type,
134 /// which clears the automatic pointer.
135 Exception(std::nullptr_t) noexcept {}
136
137 /// Constructor that allows providing the size of the allocated memory buffer in bytes.
138 /// With other constructors, this size is fixed to \c 1kB (1024 bytes).
139 /// A higher size may avoid a second allocation (which is not problematic in usual cases).
140 ///
141 /// \note The use of this constructor is advisable only in seldom cases. The same
142 /// notes as given with the documentation of the default constructor apply.
143 ///
144 /// @param initialBufferSizeInKB The initial allocation size of the internal
145 /// #"MonoAllocator" in kilobytes (1024 bytes).
146 /// @param bufferGrowthInPercent Optional growth factor in percent, applied to the buffer size
147 /// with each next buffer allocation.
148 /// With this type, the parameter defaults to \c 100, which does
149 /// not increase subsequent buffer allocations.
150 template<typename TIntegral>
151 Exception( TIntegral initialBufferSizeInKB, int bufferGrowthInPercent= 100 )
152 : TSharedMonoVal( size_t(initialBufferSizeInKB), bufferGrowthInPercent ) {
153 static_assert( !std::is_integral<TIntegral>::value,
154 "Erroneous use of Exception constructor overload which expects an integral "
155 "value as first parameter to determine the size of the first memory buffer." );
156 }
157
158 /// Constructs an exception and invokes #".Add" to create the initial message entry.
159 ///
160 /// In case that the enumeration type of given parameter \p{type} is equipped with
161 /// #"alib_enums_records;ALib Enum Records" according to record type
162 /// #"ERException", the first argument added to the message entry
163 /// is collected from the corresponding enum record. For more
164 /// information consult the #"alib_exceptions_exceptions_res;corresponding section" of the
165 /// Programmer's Manual.
166 ///
167 /// @tparam TEnum Template type of the enumeration element.
168 /// @tparam TArgs The variadic template argument types.
169 ///
170 /// @param ci Source location of entry creation.
171 /// @param type An enum element denoting the message type.
172 /// @param args The message arguments.
173 template<typename TEnum, typename... TArgs >
174 Exception( const lang::CallerInfo& ci, TEnum type, TArgs&&... args )
175 : TSharedMonoVal( 1, 100 ) { ConstructT(); Add( ci, type, std::forward<TArgs>(args)... ); }
176
177//##################################################################################################
178// Interface
179//##################################################################################################
180 /// Returns the last message in the list of stored messages.
181 ///
182 /// @return The most recently added message.
184 Message& Back() const;
185
186 /// Returns the number of message entries.
187 ///
188 /// @return The number of messages added to this exception.
190 int Size() const;
191
192 /// Returns field #"Message::Type;*" of the #"%last" message in the list of
193 /// messages that has a positive underlying enum element value.
194 ///
195 /// The rationale here is explained in the
196 /// #"alib_exceptions_exception_types;Programmer's Manual".
197 /// In short, positive and negative enum element values are used to separated
198 /// "informational entries" (with a negative value) from message entries that change the
199 /// type of the exception (positive value). Usually, only the latter ones are processed
200 /// by exception handlers.
201 ///
202 /// @return The most high level exception code.
204 const Enum& Type() const;
205
206 /// Adds a new message to this exception. The parameters of this method are
207 /// exactly those that are expected by the #"Message::Message;constructor"
208 /// of class #"Message".
209 ///
210 /// The message object itself is created in the inherited monotonic allocator.
211 /// After the insertion, method #"TBoxes;CloneAll" is invoked, which
212 /// creates "safe" copies of the arguments to guarantee their survival during this
213 /// exception's lifespan.
214 ///
215 /// If the enumeration type \p{TEnum} (which is deduced from parameter \p{type}) is equipped
216 /// with #"alib_enums_records;ALib Enum Records" of type #"ERException",
217 /// an additional message argument is \b prepended to the message.
218 /// This argument is of a string-type and is taken from the field
219 /// #"ERException::DescriptionOrItsResourceName" of the associated enum record.
220 /// As described in chapter alib_exceptions_exceptions_args of the Programmer's Manual,
221 /// it is proposed that this argument of string-type, is a formatter-string that is used to
222 /// format the arguments of an exception into a human-readable message.
223 ///
224 /// If furthermore, the type trait #"ResourcedTraits" is specialized for
225 /// enumeration type \p{TEnum}, then the value of #"%DescriptionOrItsResourceName" is not
226 /// directly prepended but interpreted as a resource name. In this case the resourced
227 /// description is prepended instead.
228 ///
229 /// For more information, consult chapter #"alib_exceptions_exceptions_res" of the
230 /// Programmer's Manual.
231 ///
232 /// @tparam TEnum The enumeration type used to define the message type.
233 /// @tparam TArgs The variadic template argument types.
234 /// @param ci Source location of entry creation.
235 /// @param type An enum element denoting the message type.
236 /// @param args The message arguments.
237 /// @return Return <c>*this</c> to allow concatenated operations or use with throw statement.
238 template <typename TEnum, typename... TArgs> inline
239 Exception& Add( const lang::CallerInfo& ci, TEnum type, TArgs&&... args ) {
240 Message* newMessage= allocMessageLink();
241 new (newMessage) Message( ci, GetAllocator(), type );
242 newMessage->Add( std::forward<TArgs>( args )... );
243 finalizeMessage( newMessage,
244 std::is_base_of_v<ERException,typename enumrecords::RecordsTraits<TEnum>::Type>,
247 return *this;
248 }
249
250
251 #if ALIB_FORMAT
252 /// Uses class #"Paragraphs" to write all entries of this
253 /// exception into the given narrow \p{target} string.
254 /// Entries are expected to have a format string set as their description meta-information
255 /// that corresponds (in respect to the placeholders within the string) to the arguments
256 /// found in the entry.
257 /// \note In multithreaded applications, the#"Formatter::DEFAULT_LOCK;*"
258 /// has to be acquired before invoking this method.
259 /// \par Availability
260 /// This method is available only if the module \alib_format is included in the \alibbuild.
261 /// @param target The target string to format the entry description to.
262 /// @return Returns given #"%AString" \p{target} for convenience.
264 AString& Format( AString& target ) const;
265
266 /// Same as #"Format(AString&)const;Format(AString&)", but writing
267 /// to a string of complement character width.
268 /// \note In multithreaded applications, the#"Formatter::DEFAULT_LOCK;*"
269 /// has to be acquired before invoking this method.
270 /// \par Availability
271 /// This method is available only if the module \alib_format is included in the \alibbuild.
272 /// @param target The target string to format the entry description to.
273 /// @return Returns given #"%AString" \p{target} for convenience.
277 {
278 target << Format();
279 return target;
280 }
281
282 /// Inline shortcut to #"Format(AString&)const;Format(AString&)"
283 /// that creates, uses and returns an AString value for the exception's description.
284 /// \note In multithreaded applications, the#"Formatter::DEFAULT_LOCK;*" has to
285 /// be acquired before invoking this method.
286 ///
287 /// \par Availability
288 /// This method is available only if the module \alib_format is included in the \alibbuild.
289 /// @return The formatted description of the Exception.
290 AString Format() const {
291 AString result;
292 Format( result );
293 return result;
294 }
295 #endif
296
297
298//##################################################################################################
299// std::ForwardIterator
300//##################################################################################################
301 protected:
302 /// Implementation of \c std::ForwardIterator that iterates all #"Message"
303 /// entries of an #"%exc Exception".
304 template<typename TConstOrMutableMessage>
306 protected:
307 /// The pointer to the actual node.
309
310 public:
311 using iterator_category = std::forward_iterator_tag; ///< Implementation of <c>std::iterator_traits</c>.
312 using value_type = Message ; ///< Implementation of <c>std::iterator_traits</c>.
313 using difference_type = integer ; ///< Implementation of <c>std::iterator_traits</c>.
314 using pointer = TConstOrMutableMessage* ; ///< Implementation of <c>std::iterator_traits</c>.
315 using reference = TConstOrMutableMessage& ; ///< Implementation of <c>std::iterator_traits</c>.
316
317 public:
318 /// Constructor.
319 /// @param _p Our initial value
320 explicit IteratorType( detail::ExceptionEntry* _p = nullptr )
321 : p(_p) {}
322
323 /// Constructor taking a constant entry pointer.
324 /// Available for the constant version of this iterator only.
325 /// @param entry The initial message entry.
326 template<typename TConstEntry>
327 requires std::is_const_v<TConstEntry>
328 IteratorType( TConstEntry* entry ) : p(const_cast<detail::ExceptionEntry*>(entry)) {}
329
330
331 /// Constructor taking a mutable iterator.
332 /// Available for the constant version of this iterator only.
333 /// @param it The mutable iterator used to construct this constant one.
334 template<typename TMutableIterator>
335 requires std::same_as<TMutableIterator, IteratorType<const Message>>
336 IteratorType( TMutableIterator it ) : p(it) {}
337
338 //############################ To satisfy concept of InputIterator ##########################
339
340 /// Prefix increment operator.
341 /// @return A reference to ourselves.
342 IteratorType& operator++() { p= p->next; return *this; }
343
344 /// Postfix increment operator.
345 /// @return A new iterator object that is not increased, yet.
347 auto result= IteratorType(p);
348 p= p->next;
349 return result;
350 }
351
352 /// Comparison operator.
353 /// @param other The iterator to compare ourselves to.
354 /// @return \c true if this and given iterator are equal, \c false otherwise.
355 bool operator==(IteratorType other) const { return p == other.p; }
356
357 /// Comparison operator.
358 /// @param other The iterator to compare ourselves to.
359 /// @return \c true if this and given iterator are not equal, \c false otherwise.
360 bool operator!=(IteratorType other) const { return p != other.p; }
361
362 /// Retrieves the message that this iterator references.
363 /// @return The message reference.
364 TConstOrMutableMessage& operator*() const { return p->message; }
365
366 /// Retrieves the pointer to the message that this iterator references.
367 /// @return The message pointer.
368 TConstOrMutableMessage* operator->() const { return &p->message; }
369 };
370
371 public:
372 /// The constant iterator exposed by this container.
373 using ConstForwardIterator = IteratorType <const Message>;
374
375 /// The mutable iterator exposed by this container.
376 using ForwardIterator = IteratorType < Message>;
377
378
379 /// Returns an iterator pointing to the first message entry.
380 /// @return A forward iterator to the first message entry.
381 ForwardIterator begin() { return ForwardIterator( **this ); }
382
383 /// Returns an iterator representing the end of the message entries.
384 /// @return The end of this exception's message entries.
385 ForwardIterator end() { return ForwardIterator( nullptr ); }
386
387 /// Returns an iterator pointing to the first message entry.
388 /// @return A forward iterator to the first message entry.
389 ConstForwardIterator begin() const { return ConstForwardIterator( **this ); }
390
391 /// Returns an iterator representing the end of the message entries.
392 /// @return The end of this exception's message entries.
393 ConstForwardIterator end() const { return ConstForwardIterator( nullptr ); }
394
395
396//##################################################################################################
397// protected methods
398//##################################################################################################
399 protected:
400 /// Searches the last linked message and attaches a new, monotonically allocated list node.
401 /// @returns A pointer to the message in the allocated link node.
404
405 /// Non-inlined portion of the method #".Add".
406 /// Clones arguments and prepends description argument, in case the enum element of the message
407 /// has an enum record attached.
408 /// If furthermore, the enum element's record was resourced, then the record's description
409 /// value is interpreted as a resource string's name, which is prepended instead.
410 /// @param message The message to finalize.
411 /// @param hasRecord Indicates if a record is assigned.
412 /// @param pool If records are resourced, this is the resource pool to use.
413 /// @param category If records are resourced, this is the category to use.
415 void finalizeMessage( Message* message, bool hasRecord, ResourcePool* pool, const NString& category );
416}; // class Exception
417
418
419/// Creates an according #"exc Exception" to a corresponding system error number.
420/// The following data is attached to the message:<br>
421/// 1. <c>"{!Q} ({}){!X}"</c> - Format string used with #"Exception::Format;*"
422/// Note that the 3rd placeholder inhibits formatting the 4th. parameter.
423/// 2. <c>errorCode.message()</c> - First format parameter.
424/// 3. <c>errorCode.category().name()</c> - Second format parameter.
425/// 4. <c>errorCode</c> - A copy of the error code.
426///
427/// The exceptions' enumeration type will be <c>std::errc</c>.
428/// The result of function <c>std::error_code::message()</c> is attched as a parameter
429/// @param ci The source location of the exception creation.
430/// @param errorCode The system's error number.
431/// @return An exception object.
432inline
433Exception CreateExceptionFromSystemError( const CallerInfo& ci, std::error_code errorCode ){
434 return Exception( ci, std::errc(errorCode.value()),
435 "{!Q} ({}){!X}",
436 errorCode.message(),
437 errorCode.category().name(),
438 errorCode);
439}
440
441/// Overloaded version, which accepts an integral POSIX system exception.
442/// Uses <c>std::make_error_code</c> to create an object of type <c>std::error_code</c>
443/// to be passed to the original function.
444/// @param ci The source location of the exception creation.
445/// @param errNo The system's error number. Defaults to system macro <c>errno</c>.
446/// @return An exception object.
447inline
449 return CreateExceptionFromSystemError( ci, std::make_error_code(std::errc(errNo)));
450}
451
452#if defined(_WIN32)
453/// Overloaded version, which accepts a WindowsOS error code.
454/// @param ci The source location of the exception creation.
455/// @param winError A WindowsOS error number, i.e. received with <c>GetLastError()</c>.
456/// @return An exception object.
457inline
459 return CreateExceptionFromSystemError( ci, std::error_code( static_cast<int>(winError),
460 std::system_category() ) );
461}
462#endif
463
464} // namespace alib[::exceptions]
465
466
467/// Type alias in namespace #"%alib".
469
470} // namespace [alib]
471
473
474
475
476//##################################################################################################
477// Append
478//##################################################################################################
479#if ALIB_FORMAT
480ALIB_EXPORT namespace alib::strings {
481#if DOXYGEN
482namespace APPENDABLES {
483#endif
484//==================================================================================================
485/// Specialization of functor #"AppendableTraits" for type #"exc Exception".
486///
487/// \par Availability
488/// This method is available only if the module \alib_format is included in the \alibbuild.
489/// @tparam TChar The character type.
490/// @tparam TAllocator The allocator type, as prototyped with class #"lang::Allocator".
491//==================================================================================================
492template<typename TChar, typename TAllocator>
493struct AppendableTraits<exceptions::Exception,TChar,TAllocator> {
494 /// Invokes #"Exception::Format;*" passing the \p{target}.
495 ///
496 /// @param target The #"%AString" that method #"%Append(const TAppendable&)" was invoked on.
497 /// @param src The exception to append.
499 src.Format(target);
500 }
501};
502
503
504
505#if DOXYGEN
506}
507#endif
508}
509#endif // ALIB_FORMAT
#define ALIB_DLL
#define ALIB_EXPORT
#define ALIB_BOXING_VTABLE_DECLARE(TMapped, Identifier)
TBoxes & Add()
Definition boxes.hpp:54
TConstOrMutableMessage & reference
Implementation of std::iterator_traits.
bool operator==(IteratorType other) const
std::forward_iterator_tag iterator_category
Implementation of std::iterator_traits.
Message value_type
Implementation of std::iterator_traits.
integer difference_type
Implementation of std::iterator_traits.
IteratorType(detail::ExceptionEntry *_p=nullptr)
TConstOrMutableMessage * pointer
Implementation of std::iterator_traits.
TConstOrMutableMessage & operator*() const
bool operator!=(IteratorType other) const
TConstOrMutableMessage * operator->() const
IteratorType< Message > ForwardIterator
The mutable iterator exposed by this container.
AString & Format(AString &target) const
strings::TAString< complementChar, lang::HeapAllocator > & Format(strings::TAString< complementChar, lang::HeapAllocator > &target) const
Message & Back() const
Definition exception.cpp:73
ConstForwardIterator end() const
Exception(Exception &&src) noexcept=default
ForwardIterator begin()
Exception & Add(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
TSharedMonoVal< detail::ExceptionEntry *, HeapAllocator, void > base
Shortcut to the parent class.
IteratorType< const Message > ConstForwardIterator
The constant iterator exposed by this container.
Exception & operator=(const Exception &) noexcept=default
Exception(TIntegral initialBufferSizeInKB, int bufferGrowthInPercent=100)
Exception & operator=(Exception &&) noexcept=default
const Enum & Type() const
Definition exception.cpp:92
ConstForwardIterator begin() const
void finalizeMessage(Message *message, bool hasRecord, ResourcePool *pool, const NString &category)
Definition exception.cpp:25
Exception(const Exception &) noexcept=default
Deleted copy constructor. Exceptions must be caught only as references.
Exception(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
TSharedMonoVal(HeapAllocator &allocator, size_t initialBufferSizeInKB, unsigned bufferGrowthInPercent)
Internal details of namespace #"alib::exceptions;2".
Definition exception.hpp:12
Exception CreateExceptionFromSystemError(const CallerInfo &ci, std::error_code errorCode)
Exception CreateExceptionFromWindowsOSError(const CallerInfo &ci, DWORD winError)
Definition alox.cpp:14
strings::TString< nchar > NString
Type alias in namespace #"%alib".
Definition string.hpp:2174
resources::ResourcePool ResourcePool
Type alias in namespace #"%alib".
lang::integer integer
Type alias in namespace #"%alib".
Definition integers.hpp:149
strings::TString< character > String
Type alias in namespace #"%alib".
Definition string.hpp:2165
exceptions::Exception Exception
Type alias in namespace #"%alib".
lang::CallerInfo CallerInfo
Type alias in namespace #"%alib".
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace #"%alib".
boxing::Enum Enum
Type alias in namespace #"%alib".
Definition enum.hpp:210
ERSerializable() noexcept=default
Defaulted constructor leaving the record undefined.
void Type
The data type associated with elements of TEnum.
Definition records.hpp:37
ERException() noexcept=default
Default constructor leaving the record undefined.
ExceptionEntry * next
A pointer to the next message.
Definition exception.hpp:19
static constexpr NString Category()
static constexpr ResourcePool * Pool()
void operator()(TAString< TChar, TAllocator > &target, const exceptions::Exception &src)