ALib C++ Framework
by
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
alox.cpp
1//##################################################################################################
2// ALib C++ Framework
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 "Configuration MACRO 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 ========================================
18
19//============================================== Module ============================================
20#if ALIB_C20_MODULES
21 module ALib.ALox;
22 import ALib.Lang;
23 import ALib.Containers.List;
24 import ALib.Monomem;
25 import ALib.Boxing;
26 import ALib.EnumRecords;
27 import ALib.Strings;
28 import ALib.EnumRecords.Bootstrap;
29 import ALib.Variables;
30 import ALib.Camp;
31 import ALib.Camp.Base;
32 import ALib.ALox.Impl;
33#else
34# include "ALib.Lang.H"
35# include "ALib.Containers.List.H"
36# include "ALib.Monomem.H"
37# include "ALib.Boxing.H"
39# include "ALib.Variables.H"
40# include "ALib.Camp.H"
41# include "ALib.Camp.Base.H"
42# include "ALib.ALox.H"
43# include "ALib.ALox.Impl.H"
44#endif
45//========================================== Implementation ========================================
46#if !DOXYGEN
47namespace alib::lox::detail {
48namespace { ListMA<Lox*> loxes(monomem::GLOBAL_ALLOCATOR); }
49integer dbgCountLoxes() { return loxes.size(); }
50void shutdownLoxes() {
51 while ( loxes.IsNotEmpty() )
52 loxes.back()->~Lox();
53 loxes.Reset();
54}
55
56}
57#endif
58
59namespace alib::lox {
60
62
63//##################################################################################################
64// Lox management
65//##################################################################################################
66#if !DOXYGEN
67
68#if ALOX_DBG_LOG
69 Lox* DEBUG_LOX = nullptr; // will be created in ALoxCamp::Bootstrap
70#endif
71
72#endif
73
74
75// The lox singletons for debug and release logging
78
79 // search
80 for( auto* it : detail::loxes )
81 if( it->GetName().Equals<CHK, lang::Case::Ignore>( name ) )
82 return it;
83
84
85 // create?
86 if ( create == lang::CreateIfNotExists::Yes ) {
87 Lox* newLox= new Lox ( name, false );
88 detail::loxes.emplace_back( newLox );
89 return newLox;
90 }
91
92 // not found
93 return nullptr;
94}
95
98
99 // check
100 if ( lox == nullptr ) {
101 ALIB_ERROR( "ALOX", "Nullptr given" )
102 return;
103 }
104
105 // remove
106 if( operation == lang::ContainerOp::Remove ) {
107 for( auto search= detail::loxes.begin() ; search != detail::loxes.end() ; ++search )
108 if ( *search == lox ) {
109 (void) detail::loxes.erase( search );
110 return;
111 }
112 ALIB_WARNING( "ALOX", "Given lox named \"{}\" could not be found for removal.",
113 lox != nullptr ? lox->GetName() : "<null>" )
114 }
115
116 // insert
117 else {
118 for( auto* it : detail::loxes )
119 if( it->GetName().Equals<NC>( lox->GetName() ) ) {
120 ALIB_ERROR( "ALOX", "Given lox named \"{}\" was already registered. "
121 "Registration ignored.", lox->GetName() )
122 return;
123 }
124 detail::loxes.emplace_back( lox );
125}}
126
127
128Lox::Lox(const NString& name, bool doRegister ) {
130
131 if( doRegister )
133}
134
141
142
143//##################################################################################################
144// Static methods of Lox
145//##################################################################################################
147 ALIB_ASSERT_ERROR(name.IsNotEmpty(), "ALOX", "Empty logger name given.")
148
149 //--- check configuration setting "CONSOLE_TYPE" ---
151 if(variable.Define())
152 variable= String( A_CHAR("Default") );
153
154 Substring val = variable;
155 val.Trim();
156 if( val.IsEmpty() ||
157 val.Equals<NC, lang::Case::Ignore>( A_CHAR("Default") ) ) goto DEFAULT;
158
159 if( val.Equals<NC, lang::Case::Ignore>( A_CHAR("Plain") ) ) return new ConsoleLogger ( name );
160 if( val.Equals<NC, lang::Case::Ignore>( A_CHAR("Ansi") ) ) return new AnsiConsoleLogger( name );
161
162 if( val.Equals<NC, lang::Case::Ignore>( A_CHAR("Windows") ) )
163 #if defined( _WIN32 )
164 return new WindowsConsoleLogger( name );
165 #else
166 goto DEFAULT;
167 #endif
168 ALIB_WARNING( "ALOX", "Unrecognized value in config variable \"{}\" = \"{}\".",
169 variable, variable.GetString() )
170
171 DEFAULT:
172 if( variable.Define(variables::Priority::Standard) )
173 variable.GetString().Reset(A_CHAR("Default"));
174
175 #if defined( _WIN32 )
176 // if there is no console window we do not do colors
177 if ( !BASECAMP.HasConsoleWindow )
178 return new ConsoleLogger( name );
179 else
180 return new WindowsConsoleLogger( name );
181 #else
182 return new AnsiConsoleLogger( name );
183 #endif
184}
185
186
187#if ALOX_DBG_LOG
188//##################################################################################################
189// Auto detection of DEBUG environment
190//##################################################################################################
192TextLogger* Log::IDE_LOGGER = nullptr;
193
195 static bool recursion= false;
196 if( recursion )
197 return;
198 recursion= true;
199
200 // block recursion caused by log operations in this code
201 if ( DEBUG_LOGGER != nullptr ) {
202 ALIB_WARNING( "ALOX", "Log::AddDebugLogger(): called twice." )
203 recursion= false;
204 return;
205 }
206 DEBUG_LOGGER= reinterpret_cast<decltype(DEBUG_LOGGER)>(-1);
207
208 // add a VStudio logger if this is a VStudio debug session
209 #if defined(_MSC_VER) && ALIB_DEBUG
210 if( BASECAMP.IsDebuggerPresent() ) {
211 Variable variable= variables::CampVariable( ALOX, Variables::NO_IDE_LOGGER );
212 bool createIDELogger= variable.IsNotDefined() || (variable.GetBool() == false);
213
214 if(createIDELogger) {
215 IDELogger= new VStudioLogger("IDE_LOGGER");
216
217 // add logger
218 lox->SetVerbosity( IDELogger, Verbosity::Verbose, "/" );
219 lox->SetVerbosity( IDELogger, Verbosity::Warning, Lox::InternalDomains );
220 } }
221 #endif
222
223 // add a default console logger
224 DEBUG_LOGGER= Lox::CreateConsoleLogger("DEBUG_LOGGER");
225
226 // add logger by setting verbosities
227 lox->SetVerbosity( DEBUG_LOGGER, Verbosity::Verbose );
228 lox->SetVerbosity( DEBUG_LOGGER, Verbosity::Warning, Lox::InternalDomains );
229
230 // check various variables, if existed already externally. If not, create them empty or
231 // with debug defaults (only done here, namely for debug logger)
232 {ALIB_LOCK_WITH(ALOX.GetConfig())
233 // Verbosity: If not, set 'ExportAll' flag
234 Variable variable= variables::CampVariable( ALOX );
235 Box replacements[2]= { "LOG", "DEBUG_LOGGER" };
236 variable.Declare( Variables::VERBOSITY, replacements );
237 if( variable.IsNotDefined() ) {
238 (void) variable.Define();
239 variable.Get<CVVerbosities>().ExportAll= true;
240 }
241
242 variable.Declare( Variables::SPTR_LOX , "LOG" ); (void) variable.Define();
243 variable.Declare( Variables::DOMAIN_SUBSTITUTION, "LOG" ); (void) variable.Define();
244 variable.Declare( Variables::PREFIXES , "LOG" ); (void) variable.Define();
245 variable.Declare( Variables::DUMP_STATE_ON_EXIT , "LOG" ); (void) variable.Define();
246 if( dynamic_cast<AnsiConsoleLogger*>(DEBUG_LOGGER) != nullptr )
247 variable.Declare( Variables::CONSOLE_LIGHT_COLORS ); (void) variable.Define();
248 }
249
250 // set ALib's assertion plugin with one that uses ALox
251 SetALibAssertionPlugin( lox );
252
253 recursion= false;
254}
255
257 // remove ALox specific assertion plugin of ALib
258 SetALibAssertionPlugin( nullptr );
259
260 // remove debug logger(s)
261 ALIB_ASSERT_WARNING( DEBUG_LOGGER != nullptr, "ALOX",
262 "Log::RemoveDebugLogger(): no debug logger to remove." )
263
264 if ( DEBUG_LOGGER != nullptr ) {
265 lox->RemoveLogger( DEBUG_LOGGER );
266
267 delete DEBUG_LOGGER;
268 DEBUG_LOGGER= nullptr;
269 }
270
271 #if defined(_WIN32) && ALIB_DEBUG
272 if ( IDE_LOGGER != nullptr ) {
273 lox->RemoveLogger( IDELogger );
274
275 delete IDE_LOGGER;
276 IDE_LOGGER= nullptr;
277 }
278 #endif
279}
280#endif // ALOX_DBG_LOG
281
282
283//##################################################################################################
284// ALoxAssertionPlugin
285//##################################################################################################
286#if ALIB_DEBUG
287
288//==================================================================================================
289/// This function will be set to global pointer #"assert::PLUGIN" when calling
290/// method #"Log::AddDebugLogger;*".<br>
291/// If no debug-logging is used, or method \b AddDebugLogger is not used, then
292/// this function can also be used with a different \b Lox and explicitly activated using
293/// the static method #"Log::SetALibAssertionPlugin;*".
294/// Uses internal domain <b>"/ALIB"</b> for logging, respectively to what the global variable
295/// #"ALOX_ASSERTION_PLUGIN_DOMAIN_PREFIX" is set.
296/// @param ci Information about the scope of invocation.
297/// @param type The type of the message. As a convention, \c 0 is an assertion, \c 1 is a
298/// warning, \c 2 is an info message, \c 3 or above are a verbose messages.
299/// @param domain The domain of the assertion, warning, or message.
300/// Will be appended to the \alox domain.
301/// @param msg The assembled message to print.
302//==================================================================================================
304 int type,
305 std::string_view domain,
306 std::string_view msg );
307
308std::string_view const ALOX_ASSERTION_PLUGIN_DOMAIN_PREFIX = "/ALIB";
309
310#if !DOXYGEN
311namespace { Lox* assertionLox= nullptr; }
312#endif
313
315
316 // remove plugin
317 if ( pLox == nullptr ) {
318 if ( assertionLox == nullptr )
319 return;
320
321 assertionLox->Acquire( ALIB_CALLER );
322 assertionLox->GetLogableContainer().Add( "ALoxAssertionPlugin removed "
323 "from Lox {!Q}", assertionLox->GetName() );
324 assertionLox->Entry( ALOX_ASSERTION_PLUGIN_DOMAIN_PREFIX, Verbosity::Verbose );
325 assertionLox->Release ();
326 assertionLox = nullptr;
327 assert::PLUGIN= nullptr;
328 return;
329 }
330
331 // add plugin
332 assertionLox = pLox;
334 assertionLox->Acquire( ALIB_CALLER );
335 assertionLox->GetLogableContainer().Add( "ALoxAssertionPlugin set to Lox {!Q}.", pLox->GetName() );
336 assertionLox->Entry( ALOX_ASSERTION_PLUGIN_DOMAIN_PREFIX, Verbosity::Verbose );
337
338 // we set the verbosity only now. This should
339 // - allow to have the above verbose message seen once
340 // - in case the values become externalized, this setting is written to such external
341 // configuration file and thus is not displayed a second time.
342 assertionLox->SetVerbosity( DEBUG_LOGGER, Verbosity::Warning,
344 assertionLox->Release ();
345}
346
348 int type,
349 std::string_view domain,
350 std::string_view msg ) {
351 assertionLox->Acquire( ci );
352
353 auto& logables= assertionLox->GetLogableContainer();
354 logables.Add( msg );
355
356 auto verbosity= type == 0 ? Verbosity::Error :
357 type == 1 ? Verbosity::Warning :
358 type == 2 ? Verbosity::Info :
359 Verbosity::Verbose ;
360
361 NString256 dom(ALOX_ASSERTION_PLUGIN_DOMAIN_PREFIX); dom << '/' << domain;
362
363 assertionLox->Entry( dom, verbosity );
364 assertionLox->Release ();
365}
366
367
368#endif //ALIB_DEBUG
369
370//##################################################################################################
371// Other minor method implementations
372//##################################################################################################
373#include "ALib.Lang.CIMethods.H"
374
375bool Logger::SetVerbosityExport(Lox* lox, bool value, Priority priority) {
376 ALIB_LOCK_WITH(ALOX.GetConfig())
377 Variable verbVar(*ALOX.GetConfig());
378
379 Box replacements[2] { lox->GetName(), GetName() };
380
381 if ( !verbVar.Declare( lox::Variables::VERBOSITY, replacements ).IsDeclared()
382 || !verbVar.Define(priority) )
383 return false;
384
385 auto& varValue= verbVar.Get<lox::CVVerbosities>();
386 varValue.ExportAll= value;
387 if ( value )
388 varValue.WriteBack= true;
389 return true;
390}
391
392}// namespace [alib::lox]
#define ALIB_CALLER
Definition alib.inl:1096
#define A_CHAR(STR)
Definition alib.inl:1325
#define ALIB_WARNING(domain,...)
Definition alib.inl:1141
#define ALIB_ASSERT_WARNING(cond, domain,...)
Definition alib.inl:1145
#define ALIB_ERROR(domain,...)
Definition alib.inl:1140
#define ALIB_LOCK_RECURSIVE_WITH(lock)
Definition alib.inl:1414
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1144
#define ALIB_LOCK_WITH(lock)
Definition alib.inl:1413
static textlogger::TextLogger * IDE_LOGGER
An (additional) IDE specific logger, that might be created by AddDebugLogger.
Definition log.inl:43
static void RemoveDebugLogger(Lox *lox)
Definition alox.cpp:256
static void AddDebugLogger(Lox *lox)
Definition alox.cpp:194
static textlogger::TextLogger * DEBUG_LOGGER
The debug logger created by AddDebugLogger.
Definition log.inl:40
static void SetALibAssertionPlugin(Lox *lox)
Definition alox.cpp:314
This class acts as a container for Loggers and provides a convenient interface to logging.
Definition lox.inl:14
~Lox()
Destructs a lox.
Definition alox.cpp:135
Lox(const NString &name, bool doRegister=true)
Definition alox.cpp:128
detail::LoxImpl * impl
The implementation.
Definition lox.inl:22
static textlogger::TextLogger * CreateConsoleLogger(const NString &name=nullptr)
Definition alox.cpp:146
static constexpr NString InternalDomains
Definition lox.inl:46
const NString & GetName()
Definition lox.inl:117
static void Register(Lox *lox, lang::ContainerOp operation)
Definition alox.cpp:96
static Lox * Get(const NString &name, lang::CreateIfNotExists create=lang::CreateIfNotExists::No)
Definition alox.cpp:76
bool SetVerbosityExport(Lox *lox, bool value, Priority priority=Priority::Standard)
Definition alox.cpp:375
const NString & GetName() const
Definition logger.inl:143
constexpr bool IsEmpty() const
Definition string.inl:353
constexpr bool IsNotEmpty() const
Definition string.inl:357
bool Equals(const TString< TChar > &rhs) const
Definition string.inl:519
TSubstring & Trim(const TCString< TChar > &whiteSpaces=CStringConstantsTraits< TChar >::DefaultWhitespaces())
bool Define(Priority requestedPriority=Priority::Standard)
Definition variable.cpp:260
Variable & Declare(const String &name, const String &typeName, const String &defaultValue=NULL_STRING)
Definition variable.cpp:186
void(* PLUGIN)(const CallerInfo &ci, int type, std::string_view domain, std::string_view msg)
Definition assert.cpp:171
ContainerOp
Denotes standard container operations.
@ Remove
Denotes removals.
@ Insert
Denotes insertions.
CreateIfNotExists
Denotes whether something should be created if it does not exist.
@ Yes
Create if something does not exist.
void shutdownLoxes()
Internal lox management.
integer dbgCountLoxes()
void ALoxAssertionPlugin(const lang::CallerInfo &ci, int type, std::string_view domain, std::string_view msg)
Definition alox.cpp:347
Lox * DEBUG_LOX
std::string_view const ALOX_ASSERTION_PLUGIN_DOMAIN_PREFIX
Definition alox.cpp:308
@ CONSOLE_LIGHT_COLORS
Denotes configuration variable #"alxcvALOX_CONSOLE_LIGHT_COLORS" used by colorful specializations of ...
Definition aloxcamp.inl:67
@ CONSOLE_TYPE
Denotes configuration variable #"alxcvALOX_CONSOLE_TYPE" used by #"Lox::CreateConsoleLogger;2".
Definition aloxcamp.inl:25
@ VERBOSITY
Denotes configuration variable #"alxcvALOX_LOGGERNAME_VERBOSITY_WITH_LOXNAME".
Definition aloxcamp.inl:28
@ DOMAIN_SUBSTITUTION
Denotes configuration variable #"alxcvALOX_LOXNAME_DOMAIN_SUBSTITUTION" used by class #"Lox".
Definition aloxcamp.inl:37
@ DUMP_STATE_ON_EXIT
Denotes configuration variable #"alxcvALOX_LOXNAME_DUMP_STATE_ON_EXIT" used by class #"Lox".
Definition aloxcamp.inl:43
@ SPTR_LOX
Denotes configuration variable #"alxcvALOX_LOXNAME_SOURCE_PATH_TRIM_RULES" used by class #"Lox".
Definition aloxcamp.inl:34
@ PREFIXES
Denotes configuration variable #"alxcvALOX_LOXNAME_PREFIXES" used by class #"Lox".
Definition aloxcamp.inl:40
RecursiveLock GLOBAL_ALLOCATOR_LOCK
TMonoAllocator< lang::HeapAllocator > GLOBAL_ALLOCATOR
variables::Variable CampVariable(camp::Camp &camp)
Definition camp.inl:285
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2181
lox::textlogger::TextLogger TextLogger
Type alias in namespace alib.
alib::variables::Priority Priority
Type alias in namespace alib.
variables::Variable Variable
Type alias in namespace alib.
containers::List< T, MonoAllocator, TRecycling > ListMA
Type alias in namespace alib.
Definition list.inl:697
lox::ALoxCamp ALOX
The singleton instance of ALib Camp class #"ALoxCamp".
Definition aloxcamp.cpp:54
lox::loggers::WindowsConsoleLogger WindowsConsoleLogger
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
lox::Lox Lox
Type alias in namespace alib.
Definition lox.inl:1286
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1135
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2172
strings::TSubstring< character > Substring
Type alias in namespace alib.
camp::Basecamp BASECAMP
The singleton instance of ALib Camp class #"Basecamp".
Definition basecamp.cpp:80
lox::loggers::AnsiConsoleLogger AnsiConsoleLogger
Type alias in namespace alib.
NLocalString< 256 > NString256
Type alias name for #"TLocalString;TLocalString<nchar,256>".
lox::loggers::ConsoleLogger ConsoleLogger
Type alias in namespace alib.
See sibling type #"NC".
Definition chk_nc.inl:33
static void Destruct(LoxImpl *lox)
Definition loxpimpl.cpp:284
static LoxImpl * Construct(const NString &name)
Definition loxpimpl.cpp:274