ALib C++ Library
Library Version: 2510 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
exception.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2025 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
7#include "alib_precompile.hpp"
8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
10#endif
11#if ALIB_C20_MODULES
12 module;
13#endif
14// ====================================== Global Fragment ======================================
15#include <vector>
16#include <algorithm>
17#include <any>
19// =========================================== Module ==========================================
20#if ALIB_C20_MODULES
21 module ALib.Exceptions;
22 import ALib.Lang;
23 import ALib.Strings;
25 import ALib.Boxing;
26 import ALib.EnumRecords;
28# if ALIB_SYSTEM
29 import ALib.System;
30# endif
31# if ALIB_FORMAT
32 import ALib.Format;
33# endif
35# if ALIB_CAMP
36 import ALib.Camp.Base;
37# endif
38#else
39# include "ALib.Lang.H"
40# include "ALib.Strings.H"
42# include "ALib.Boxing.H"
43# include "ALib.EnumRecords.H"
45# include "ALib.System.H"
46# include "ALib.Format.H"
48# include "ALib.Camp.Base.H"
49# include "ALib.Exceptions.H"
50#endif
51// ====================================== Implementation =======================================
53
54
55namespace alib::exceptions {
56
58{
59 enumrecords::bootstrap::EnumRecordParser::Get( ERSerializable::EnumElementName );
60 ERSerializable::MinimumRecognitionLength= 0;
62}
63
65{
66 // find pointer to the last entry pointer;
67 detail::ExceptionEntry** tail= &**this;
68 while(*tail != nullptr)
69 tail= &(*tail)->next;
70
71 *tail= GetAllocator()().Alloc<detail::ExceptionEntry>();
72 (*tail)->next= nullptr;
73
74 return &(*tail)->message;
75}
76
77
78void Exception::finalizeMessage( Message* message, bool hasRecord, ResourcePool* pool, const NString& category )
79{
80 message->CloneAll();
81
82 if( hasRecord )
83 {
84 #if ALIB_DEBUG
85 {
86 auto* tryRecord= boxing::TryRecord<ERException>(message->Type);
87 if( tryRecord == nullptr )
88 {
89 std::vector<std::pair<integer,const void*>> recordList;
90 for( auto& record : enumrecords::detail::getInternalRecordMap() )
91 if( record.first.RTTI == message->Type.TypeID() )
92 recordList.push_back( std::pair<integer,const void*>(record.first.Element, record.second) );
93 if( recordList.size() == 0)
94 {
95 ALIB_ERROR( "EXCEPT", "No enum records defined for exception enumeration "
96 "type {!Q<>}.", message->Type.TypeID().name() )
97 }
98 else
99 {
100 std::sort( recordList.begin(), recordList.end(),
101 [] (std::pair<integer,const void*>& a, std::pair<integer,const void*>& b )
102 {
103 return a.first < b.first;
104 });
105 std::vector<std::any> args; args.reserve(32);
106 args.emplace_back( "Enum record {} not found for exception enumeration type {}.\n"
107 "The following records have been found:\n" );
108 args.emplace_back( message->Type.Integral() );
109 args.emplace_back( &message->Type.TypeID() );
110
111 for( auto& pair : recordList )
112 {
113 args.emplace_back( " {}: {}\n" );
114 args.emplace_back( pair.first );
115 args.emplace_back( reinterpret_cast<const ERException*>( pair.second )->EnumElementName );
116 }
117 assert::raise( ALIB_CALLER_PRUNED, 1, "EXCEPT", args );
118 }
119 }
120 }
121 #endif
122 const auto& enumRecord= boxing::GetRecord<ERException>(message->Type);
123 if( pool == nullptr )
124 message->emplace( message->begin(),
125 enumRecord.DescriptionOrItsResourceName );
126 else
127 message->emplace( message->begin(),
128 pool->Get( category,
129 enumRecord.DescriptionOrItsResourceName
130 ALIB_DBG(, true) ) );
131 }
132}
133
134
136{
137 auto* result= **this;
138 while( result->next != nullptr )
139 result= result->next;
140
141 return result->message;
142}
143
145{
146 int result= 1;
147 auto* entry= **this;
148 while( entry->next != nullptr )
149 {
150 entry= entry->next;
151 ++result;
152 }
153
154 return result;
155}
156
157const Enum& Exception::Type() const
158{
159 auto* entry= **this;
160 Enum* result= &entry->message.Type;
161 while( (entry= entry->next) != nullptr )
162 if( entry->message.Type.Integral() >= 0 )
163 result= &entry->message.Type;
164
165 return *result;
166}
167
168
169#if ALIB_FORMAT
171{
172 Paragraphs text(target);
173 Tokenizer tknzr;
174 tknzr.TrimChars= A_CHAR( "\r" );
175 String1K buf;
177 Formatter& formatter= *Formatter::Default;
178 formatter.GetArgContainer();
179 size_t entryNo= 1;
180 for ( auto entry= begin(); entry != end(); ++entry )
181 {
182 text.Add( A_CHAR("{}{}: {!Q<>}"), (entry->Type.Integral() >= 0 ? 'E' : 'I'), entryNo, entry->Type );
183 text.PushIndent( A_CHAR(" ") );
184 try
185 {
186 formatter.FormatArgs( buf.Reset(), *entry );
187 }
188 catch( Exception& e )
189 {
190 #if ALIB_CAMP
191 buf << BASECAMP.GetResource("ExcFmtExc");
192 #else
193 buf << A_CHAR("\nAn exception occurred while formatting another (!) exception:\n" );
194 #endif
195 e.Format( buf );
196 }
197 tknzr.Set( buf, '\n' );
198 while( tknzr.HasNext() )
199 text.Add( tknzr.Next() );
200
201 #if ALIB_DEBUG
202 text.Add( entry->CI );
203 #endif
204
205 text.PopIndent();
206 ++entryNo;
207 }
208
209 return target;
210}
211#endif // ALIB_FORMAT
212
213} // namespace [alib::lang]
214
215
216#if ALIB_CAMP
217namespace alib::system {
218
220{
221 auto* enumRecord= enumrecords::TryRecord( SystemErrors(errNo) );
222 if( enumRecord == nullptr )
223 return Exception( ci, SystemErrors::UNKNOWN, errNo );
224
225 return Exception( ci, SystemErrors(errNo), // as exception
226 SystemErrors(errNo), // boxing the exception's name (!)
227 errNo );
228}
229} // namespace [alib::lang]
230#endif
Exception(Exception &) noexcept=default
Deleted copy constructor. Exceptions must be caught only as references.
ALIB_DLL AString & Format(AString &target) const
ALIB_DLL Message & Back() const
ALIB_DLL Message * allocMessageLink()
Definition exception.cpp:64
ForwardIterator begin()
ALIB_DLL const Enum & Type() const
ALIB_DLL void finalizeMessage(Message *message, bool hasRecord, ResourcePool *pool, const NString &category)
Definition exception.cpp:78
ALIB_DLL int Size() const
static ALIB_DLL SPFormatter Default
ALIB_DLL Paragraphs & PushIndent(uinteger qty, character fillChar=' ')
void Add(boxing::TBoxes< TAllocatorArgs > &args)
ALIB_DLL Paragraphs & PopIndent()
virtual const String & Get(const NString &category, const NString &name, bool dbgAssert)=0
void DbgDisableBufferReplacementWarning()
Definition tastring.inl:245
ALIB_DLL TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
Definition tokenizer.cpp:26
void Set(const TString< TChar > &src, TChar delimiter, bool skipEmptyTokens=false)
TLocalString< TChar, 8 > TrimChars
Definition tokenizer.inl:70
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
#define A_CHAR(STR)
#define ALIB_ERROR(domain,...)
Definition alib.inl:1045
#define ALIB_DBG(...)
Definition alib.inl:836
#define ALIB_CALLER_PRUNED
Definition alib.inl:1007
void raise(const CallerInfo &ci, int type, std::string_view domain, const std::span< std::any > &args)
Definition assert.cpp:575
const TRecord * TryRecord(Enum e)
const TRecord & GetRecord(Enum e)
HashMap< MonoAllocator, EnumRecordKey, const void *, EnumRecordKey::Hash, EnumRecordKey::EqualTo > & getInternalRecordMap()
Definition records.cpp:89
const RecordsTraits< TEnum >::Type * TryRecord(TEnum element)
Definition records.inl:218
Exception CreateSystemException(const CallerInfo &ci, int errNo)
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
strings::util::TTokenizer< character > Tokenizer
Type alias in namespace alib.
camp::Basecamp BASECAMP
The singleton instance of ALib Camp class Basecamp.
Definition basecamp.cpp:81
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2390
format::Paragraphs Paragraphs
Type alias in namespace alib.
resources::ResourcePool ResourcePool
Type alias in namespace alib.
format::Formatter Formatter
Type alias in namespace alib.
boxing::Enum Enum
Type alias in namespace alib.
Definition enum.inl:211
LocalString< 1024 > String1K
Type alias name for TLocalString<character,1024>.
exceptions::Exception Exception
Type alias in namespace alib.
lang::CallerInfo CallerInfo
Type alias in namespace alib.
integer Integral() const
Definition enum.inl:87
const std::type_info & TypeID() const
Definition box.inl:827
String EnumElementName
The name of the enum element.
Definition records.inl:466
static ALIB_DLL void Get(String &result, bool isLastField=false)
ExceptionEntry * next
A pointer to the next message.
Definition exception.inl:20