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"
28# if __has_include(<format>)
31# include <fmt/format.h>
35# if (ALIB_SINGLE_THREADED && ALIB_EXT_LIB_THREADS_AVAILABLE)
38# if ALIB_DEBUG_ASSERTION_PRINTABLES
39# include <unordered_set>
53 import ALib.Bootstrap;
56 import ALib.Strings.Token;
58 import ALib.Strings.Monomem;
65 import ALib.EnumRecords;
68 import ALib.Resources;
71 import ALib.Variables;
77 import ALib.ThreadModel;
80 import ALib.Camp.Base;
110#if (ALIB_SINGLE_THREADED && ALIB_EXT_LIB_THREADS_AVAILABLE) || DOXYGEN
113 namespace { std::thread::id dbg_thread_seen;
114 bool dbg_in_single_threaded_check=
false; }
143 if( dbg_in_single_threaded_check )
145 dbg_in_single_threaded_check=
true;
150 dbg_thread_seen= std::this_thread::get_id();
151 dbg_in_single_threaded_check=
false;
155 if( dbg_thread_seen != std::this_thread::get_id() )
158 "A second thread was detected using a single-threaded compilation of ALib"
159 "(Symbol 'ALIB_SINGLE_THREADED' given with the ALib Build)." )
161 dbg_in_single_threaded_check=
false;
173 std::string_view domain, std::string_view msg ) =
nullptr;
176std::string_view
FORMAT =
"{file}:{line} {type}:\n{message}";
183 thread_local TLD HALT_FLAGS_AND_COUNTERS;
184 bool isInitialized=
false;
185 std::string outBuffer;
186#if !ALIB_SINGLE_THREADED
191static std::unordered_map<std::type_index, AnyConversionFunc> registeredAnys;
193#if __has_include(<format>)
199void initializeDefaultPrintables() {
201 RegisterPrintable(
typeid(
bool ), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast< bool >(any)); });
202 RegisterPrintable(
typeid(
char ), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast< char >(any)); });
203 RegisterPrintable(
typeid( int8_t ), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast< int8_t >(any)); });
204 RegisterPrintable(
typeid(uint8_t ), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast<uint8_t >(any)); });
205 RegisterPrintable(
typeid( int16_t ), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast< int16_t >(any)); });
206 RegisterPrintable(
typeid(uint16_t ), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast<uint16_t >(any)); });
207 RegisterPrintable(
typeid( int32_t ), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast< int32_t >(any)); });
208 RegisterPrintable(
typeid(uint32_t ), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast<uint32_t >(any)); });
209 RegisterPrintable(
typeid( int64_t ), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast< int64_t >(any)); });
210 RegisterPrintable(
typeid(uint64_t ), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast<uint64_t >(any)); });
211 RegisterPrintable(
typeid(
float ), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast<float >(any)); });
212 RegisterPrintable(
typeid(
unsigned long), [](
const std::any& any, std::string& s) { s+= f::format(
"{}", std::any_cast<unsigned long>(any)); });
213DOX_MARKER( [DOX_ASSERT_REGISTER_PRINTABLE])
215 [](
const std::any& any, std::string& s) {
216 s+= f::format(
"{}", std::any_cast<double >(any));
219 [](
const std::any& any, std::string& s) {
220 auto* value= std::any_cast<const char*>(any);
225 [](
const std::any& any, std::string& s) {
226 auto* value= std::any_cast<const char*>(any);
231 [](
const std::any& any, std::string& s) {
232 auto* value= std::any_cast<const wchar_t*>(any);
235 std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
236 s+= converter.to_bytes(value);
240DOX_MARKER( [DOX_ASSERT_REGISTER_PRINTABLE])
242 if constexpr (
sizeof(wchar_t) == 2)
244 [](
const std::any& any, std::string& s) {
245 auto* value= std::any_cast<const char32_t*>(any);
248 std::wstring_convert<std::codecvt_utf8<char32_t>,
char32_t> converter;
249 s+= converter.to_bytes(value);
253 if constexpr (
sizeof(wchar_t) == 4)
255 [](
const std::any& any, std::string& s) {
256 auto* value= std::any_cast<const char16_t*>(any);
259 std::wstring_convert<std::codecvt_utf8<char16_t>,
char16_t> converter;
260 s+= converter.to_bytes(value);
265 RegisterPrintable(
typeid(std::string ), [](
const std::any& any, std::string& s) { s+= *std::any_cast<std::string >(&any); });
266 RegisterPrintable(
typeid(std::string_view ), [](
const std::any& any, std::string& s) { s+= std::any_cast<std::string_view>( any); });
267 RegisterPrintable(
typeid(
const std::type_info*), [](
const std::any& any, std::string& s) {
268 auto* typeInfo= std::any_cast<const std::type_info*>(any);
272 RegisterPrintable(
typeid(std::thread::id) , [](
const std::any& any, std::string& s) {
273 #if !ALIB_SINGLE_THREADED
274 auto threadID= std::any_cast<std::thread::id>(any);
278 #if !ALIB_CHARACTERS_WIDE
281 std::wstring_convert<std::codecvt_utf8<character>,
character> converter;
282 s+= converter.to_bytes(thread->
GetName());
284 s += f::format(
"({})", thread->
GetID());
287 s+=
"<Unknown thread>";
291 s+=
"<SINGLE_THREADED>";
296 CallerInfo callerInfo= std::any_cast<CallerInfo>(any);
297 if ( callerInfo.
File ==
nullptr ) {
298 s+=
"<nulled caller>";
301 s+=f::format(
"{{Caller: @ {}:{} ({}) ", callerInfo.
File,callerInfo.
Line, callerInfo.
Func);
305 #if !ALIB_SINGLE_THREADED
306 s+=f::format(
"thread::id= {}", 5 );
312 #if !ALIB_SINGLE_THREADED
313 Thread* thread= std::any_cast<Thread*>(any);
315 #if !ALIB_CHARACTERS_WIDE
318 std::wstring_convert<std::codecvt_utf8<character>,
character> converter;
319 s+= converter.to_bytes(thread->
GetName());
321 s += f::format(
"({})", thread->
GetID());
324 s+=
"<Unknown thread>";
327 s+=
"<SINGLE_THREADED>";
331 #if !ALIB_SINGLE_THREADED
333 auto state= std::any_cast<Thread::State>(any);
339 else s+=
"<Unknown thread state>";
345 RegisterPrintable(
typeid(
NString ), [](
const std::any& any, std::string& s) { s+= std::string_view( std::any_cast<NString >(any).Buffer(),
size_t(std::any_cast<NString >(any).Length()) ); });
346 RegisterPrintable(
typeid(
NAString), [](
const std::any& any, std::string& s) { s+= std::string_view( std::any_cast<NAString>(any).Buffer(),
size_t(std::any_cast<NAString>(any).Length()) ); });
347 RegisterPrintable(
typeid(
NCString), [](
const std::any& any, std::string& s) { s+= std::string_view( std::any_cast<NCString>(any).Buffer(),
size_t(std::any_cast<NCString>(any).Length()) ); });
348 RegisterPrintable(
typeid(
WString ), [](
const std::any& any, std::string& s) { std::wstring_convert<std::codecvt_utf8<wchar>,
wchar> converter;
auto src=std::any_cast<WString >(any); s+= converter.to_bytes(src.Buffer(), src.Buffer() + src.Length() ); });
349 RegisterPrintable(
typeid(
WAString), [](
const std::any& any, std::string& s) { std::wstring_convert<std::codecvt_utf8<wchar>,
wchar> converter;
auto src=std::any_cast<WAString>(any); s+= converter.to_bytes(src.Buffer(), src.Buffer() + src.Length() ); });
350 RegisterPrintable(
typeid(
WCString), [](
const std::any& any, std::string& s) { std::wstring_convert<std::codecvt_utf8<wchar>,
wchar> converter;
auto src=std::any_cast<WCString>(any); s+= converter.to_bytes(src.Buffer(), src.Buffer() + src.Length() ); });
351 RegisterPrintable(
typeid(
XString ), [](
const std::any& any, std::string& s) { std::wstring_convert<std::codecvt_utf8<xchar>,
xchar> converter;
auto src=std::any_cast<XString >(any); s+= converter.to_bytes(src.Buffer(), src.Buffer() + src.Length() ); });
352 RegisterPrintable(
typeid(
XAString), [](
const std::any& any, std::string& s) { std::wstring_convert<std::codecvt_utf8<xchar>,
xchar> converter;
auto src=std::any_cast<XAString>(any); s+= converter.to_bytes(src.Buffer(), src.Buffer() + src.Length() ); });
353 RegisterPrintable(
typeid(
XCString), [](
const std::any& any, std::string& s) { std::wstring_convert<std::codecvt_utf8<xchar>,
xchar> converter;
auto src=std::any_cast<XCString>(any); s+= converter.to_bytes(src.Buffer(), src.Buffer() + src.Length() ); });
356 RegisterPrintable(
typeid(
NAStringMA), [](
const std::any& any, std::string& s) { s+= std::string_view( std::any_cast<NAStringMA>(any).Buffer(),
size_t(std::any_cast<NAStringMA>(any).Length()) ); });
357 RegisterPrintable(
typeid(
WAStringMA), [](
const std::any& any, std::string& s) { std::wstring_convert< std::codecvt_utf8<wchar>,
wchar> converter;
auto src=std::any_cast<WAStringMA>(any); s+= converter.to_bytes(src.Buffer(), src.Buffer() + src.Length() ); });
358 RegisterPrintable(
typeid(
NAStringPA), [](
const std::any& any, std::string& s) { s+= std::string_view( std::any_cast<NAStringPA>(any).Buffer(),
size_t(std::any_cast<NAStringPA>(any).Length()) ); });
359 RegisterPrintable(
typeid(
WAStringPA), [](
const std::any& any, std::string& s) { std::wstring_convert< std::codecvt_utf8<wchar>,
wchar> converter;
auto src=std::any_cast<WAStringPA>(any); s+= converter.to_bytes(src.Buffer(), src.Buffer() + src.Length() ); });
364 #if ALIB_BOXING && ALIB_ENUMRECORDS
400 auto* o= std::any_cast<const variables::Variable*>(any);
407 auto* o= std::any_cast<variables::Variable*>(any);
414 auto o= std::any_cast<variables::Variable>(any);
428 #if ALIB_THREADMODEL && ALIB_ENUMRECORDS
434void printRegisteredAny(
const std::any& any,
const CallerInfo& ci) {
435 if (!any.has_value())
437 auto it = registeredAnys.find(std::type_index(any.type()));
438 if (it != registeredAnys.end()) {
440 it->second(any, outBuffer);
442 std::cerr <<
"Internal Error using alib::assert::Assert(): No converter registered for type: <"
445 <<
"at " << ci.
File <<
':' << ci.
Line << std::endl;
449const char* resolveMessageType(
int msgType) {
450 if (msgType == 0)
return "error";
451 if (msgType == 1)
return "warning";
455void writeMessage( std::ostream& os,
int msgType,
const std::string_view& domain,
456 const char* file,
int line,
457 const std::string_view& message ) {
463 while (start <
format.size()) {
465 size_t openBrace =
format.find(
'{', start);
466 if (openBrace == std::string_view::npos) {
468 os <<
format.substr(start);
473 os <<
format.substr(start, openBrace - start);
476 size_t closeBrace =
format.find(
'}', openBrace + 1);
477 if (closeBrace == std::string_view::npos) {
479 os <<
format.substr(openBrace);
484 std::string_view placeholder =
format.substr(openBrace + 1, closeBrace - openBrace - 1);
487 if ( placeholder ==
"type" ) os << resolveMessageType(msgType);
488 else if ( placeholder ==
"file" ) os << file;
489 else if ( placeholder ==
"line" ) os << line;
490 else if ( placeholder ==
"message" ) os << message;
491 else if ( placeholder ==
"domain" ) os << domain;
492 else os <<
"{" << placeholder <<
"}";
495 start = closeBrace + 1;
500class RecursionBlocker {
502 static inline std::atomic<bool> isRecursing{
false};
506 RecursionBlocker()
noexcept { wasBlocked = isRecursing.exchange(
true); }
508 ~RecursionBlocker() {
if (!wasBlocked) isRecursing =
false; }
510 [[nodiscard]]
bool blocked()
const noexcept {
return wasBlocked; }
513 RecursionBlocker(
const RecursionBlocker&) =
delete;
514 RecursionBlocker& operator =(
const RecursionBlocker&) =
delete;
517#if ALIB_DEBUG_ASSERTION_PRINTABLES
518 struct Key {
const char* str;
520 bool operator==(
const Key& other)
const {
521 return str == other.str && value == other.value;
524 struct KeyHash { std::size_t operator()(
const Key& key)
const {
525 return std::hash<const char*>()(key.str) ^ ( std::hash<int>()(key.value) << 1);
528 std::unordered_set<Key, KeyHash> seenSourceLocations;
534 registeredAnys[typeIndex] = func;
537#if ALIB_DEBUG_ASSERTION_PRINTABLES
538# pragma message ("ALIB_DEBUG_ASSERTION_PRINTABLES set. ALib will print all assertions once, no matter if they are raised or not." )
541 if( !isInitialized ) initializeDefaultPrintables();
543 if (!seenSourceLocations.insert(Key{ci.File, ci.Line}).second)
547 for (
size_t i = 0; i < args.size(); ++i) {
548 auto it = registeredAnys.find(std::type_index(args[i].type()));
549 if (it == registeredAnys.end()) {
550 std::cerr <<
"Internal Error using alib::assert::Assert(): No converter registered for type: <"
551 << lang::DbgTypeDemangler( args[i].type() ).Get()
553 <<
" at: " << ci.File <<
':' << ci.Line << std::endl;
557 raise(ci, -1,
"ASSERTTEST", args );
566 const std::span<std::any>& args ) {
570 RecursionBlocker blocker;
571 if (blocker.blocked())
576 initializeDefaultPrintables();
584 for(
nchar c : domain ) {
586 || ( c >=
'A' && c <=
'Z' )
587 || c ==
'-' || c ==
'_' || c ==
'/' || c ==
'.' ) ) {
588 std::cerr <<
"Illegal alib::assert::Assert() domain given: " << domain << std::endl;
593 while (i < args.size()) {
594 const std::any& arg = args[i];
596 if ( arg.type() ==
typeid(
const char*)
597 || arg.type() ==
typeid(std::string)
598 || arg.type() ==
typeid(std::string_view) ) {
600 std::string_view str;
602 if (arg.type() ==
typeid(
const char*)) str = std::string_view( std::any_cast<const char* >( arg));
603 else if (arg.type() ==
typeid(std::string)) str = std::string_view(*std::any_cast<std::string >(&arg));
604 else str = std::any_cast<std::string_view>( arg) ;
605 std::string_view origStr= str;
609 auto handle_format_string = [&]() {
611 while ((pos = str.find(
"{}")) != std::string::npos) {
613 outBuffer+= str.substr(0, pos);
616 if (++i >= args.size()) {
617 std::cerr <<
"alib::assert: Not enough arguments for format placeholders!" << std::endl;
618 std::cerr <<
" Format string: <" << origStr <<
'>' << std::endl;
619 std::cerr <<
" @ : " << ci.
File <<
':' << ci.
Line << std::endl;
625 const std::any& placeholderArg = args[i];
626 printRegisteredAny(placeholderArg, ci);
629 str = str.substr(pos + 2);
639 handle_format_string();
641 printRegisteredAny(arg, ci);
648 PLUGIN( ci, type, domain, outBuffer.c_str() );
655 #if !ALIB_SINGLE_THREADED
657 if( lockingIoStreams )
664 type, domain, ci.
File, ci.
Line, outBuffer);
665 #if !ALIB_SINGLE_THREADED
666 if( lockingIoStreams )
673 if (type == 0) {HALT_FLAGS_AND_COUNTERS.CtdErrors++; halt= HALT_FLAGS_AND_COUNTERS.HaltOnErrors; }
674 else if (type == 1) {HALT_FLAGS_AND_COUNTERS.CtdWarnings++; halt= HALT_FLAGS_AND_COUNTERS.HaltOnWarnings; }
675 else {HALT_FLAGS_AND_COUNTERS.CtdMessages++; halt=
false; }
676 #if defined( _WIN32 )
686 #if defined(__GNUC__) || defined(__clang__)
689 #elif defined ( _MSC_VER )
ALIB_DLL const char * Get()
@ Running
The thread's Run method is currently processed.
@ Started
Method Start was invoked but not running, yet.
@ Terminated
The thread is terminated.
virtual const character * GetName() const
static ALIB_DLL Thread * Get(std::thread::id nativeID)
#define ALIB_WARNINGS_RESTORE
#define ALIB_STRINGS_TO_NARROW( src, dest, bufSize)
#define ALIB_ERROR(domain,...)
#define ALIB_LOCK_RECURSIVE_WITH(lock)
#define ALIB_WARNINGS_IGNORE_DEPRECATED
This namespace exposes entities of module ALib Assert.
std::ostream * STREAM_WARNINGS
void(* PLUGIN)(const CallerInfo &ci, int type, std::string_view domain, std::string_view msg)
std::ostream * STREAM_ERRORS
ALIB_DLL void CheckArgsImpl(const CallerInfo &ci, const std::span< std::any > &args)
TLD & GetHaltFlagAndCounters()
ALIB_DLL void RegisterPrintable(std::type_index typeIndex, AnyConversionFunc func)
void raise(const CallerInfo &ci, int type, std::string_view domain, const std::span< std::any > &args)
std::ostream * STREAM_MESSAGES
void(*)(const std::any &, std::string &) AnyConversionFunc
SortOrder
Denotes sort order.
Side
Denotes if something is left or right.
SourceData
Denotes if the source data should be moved or copied.
Reach
Denotes the reach of something.
Recursive
Denotes whether recursion is performed/allowed or not.
Timing
Denotes if asynchronous tasks become synchronized.
Alignment
Denotes Alignments.
LineFeeds
Denotes line-feed encoding sequences "\n" and "\r\n".
ContainerOp
Denotes standard container operations.
Switch
Denotes if sth. is switched on or off.
Phase
Denotes a phase, e.g.,of a transaction.
CreateIfNotExists
Denotes whether something should be created if it does not exist.
Case
Denotes upper and lower case character treatment.
CreateDefaults
Denotes whether default entities should be created or not.
Whitespaces
Denotes whether a string is trimmed or not.
constexpr bool IsNull(const T &t)
Caching
Denotes if a cache mechanism is enabled or disabled.
Propagation
Denotes whether a e.g a setting should be propagated.
ValueReference
Denotes if a value is interpreted as an absolute or relative number.
Safeness
Denotes whether something should be performed in a safe or unsafe fashion.
Initialization
Used, for example, with constructors that allow to suppress initialization of members.
Inclusion
Denotes how members of a set something should be taken into account.
Timezone
Denotes whether a time value represents local time or UTC.
Priority
Possible priorities of jobs assigned to an DedicatedWorker.
ALIB_DLL Lock STD_IOSTREAMS_LOCK
strings::TAString< wchar, lang::HeapAllocator > WAString
Type alias in namespace alib.
strings::TAString< wchar, PoolAllocator > WAStringPA
Type alias in namespace alib.
strings::util::Token Token
Type alias in namespace alib.
LocalString< 256 > String256
Type alias name for TLocalString<character,256>.
camp::Basecamp BASECAMP
The singleton instance of ALib Camp class Basecamp.
strings::TAString< wchar, MonoAllocator > WAStringMA
Type alias in namespace alib.
strings::TString< xchar > XString
Type alias in namespace alib.
characters::wchar wchar
Type alias in namespace alib.
strings::TString< nchar > NString
Type alias in namespace alib.
strings::TAString< nchar, lang::HeapAllocator > NAString
Type alias in namespace alib.
strings::TCString< xchar > XCString
Type alias in namespace alib.
threads::Thread Thread
Type alias in namespace alib.
strings::TString< wchar > WString
Type alias in namespace alib.
strings::TCString< wchar > WCString
Type alias in namespace alib.
strings::TCString< nchar > NCString
Type alias in namespace alib.
characters::nchar nchar
Type alias in namespace alib.
boxing::Enum Enum
Type alias in namespace alib.
boxing::Box Box
Type alias in namespace alib.
strings::TAString< nchar, PoolAllocator > NAStringPA
Type alias in namespace alib.
threads::RecursiveLock RecursiveLock
Type alias in namespace alib.
strings::TAString< nchar, MonoAllocator > NAStringMA
Type alias in namespace alib.
characters::xchar xchar
Type alias in namespace alib.
bool NonCampModulesInitialized
lang::CallerInfo CallerInfo
Type alias in namespace alib.
NLocalString< 256 > NString256
Type alias name for TLocalString<nchar,256>.
strings::TAString< xchar, lang::HeapAllocator > XAString
Type alias in namespace alib.
characters::character character
Type alias in namespace alib.
const char * File
The name of the source file as given by compiler.
const std::type_info * TypeInfo
The calling type.
int Line
The line number within File.