ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
loxpimpl.cpp
1// #################################################################################################
2// alib::lox - ALox Logging Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !defined(ALIB_DOX)
10# if !defined (HPP_ALIB_LANG_BASECAMP)
12# endif
13
14# if !defined (HPP_ALOX_CONSOLE_LOGGER)
16# endif
17# if !defined (HPP_ALOX_ANSI_LOGGER)
19# endif
20# if !defined (HPP_ALOX_WINDOWS_CONSOLE_LOGGER)
22# endif
23
24# if !defined(HPP_ALIB_ENUMS_SERIALIZATION)
26# endif
27# if !defined (HPP_ALIB_LANG_COMMONENUMS)
29# endif
30# if !defined (HPP_ALIB_STRINGS_UTIL_TOKENIZER)
32# endif
33# if !defined (HPP_ALIB_STRINGS_FORMAT)
35# endif
36
37#define HPP_ALIB_LOX_PROPPERINCLUDE
38# if !defined (HPP_ALOX_DETAIL_SCOPE)
40# endif
41# if !defined (HPP_ALOX_DETAIL_SCOPEINFO)
43# endif
45#undef HPP_ALIB_LOX_PROPPERINCLUDE
46
47#if !defined (HPP_ALIB_ALOXMODULE)
49#endif
50#if !defined(HPP_ALIB_CAMP_MESSAGE_REPORT)
52#endif
53#endif // !defined(ALIB_DOX)
54
55#if ALIB_THREADS
56 #define UNDEFINED_THREAD threads::UNDEFINED
57#else
58 #define UNDEFINED_THREAD 0
59#endif
60
61namespace alib { namespace lox { namespace detail {
62
63/** Domain substitution rules. */
65{
66 /** Rule types. */
67 public: enum class Type
68 {
69 Exact, ///< Exact match.
70 StartsWith, ///< Starts with match.
71 EndsWith, ///< Ends with match.
72 Substring ///< Any sub-string.
73 };
74
75 Type type; ///< Denotes the type of the rule, depending of what
76 ///< was set in originally as search path
77 NString32 Search; ///< The path to search.
78 NString32 Replacement; ///< The replacement.
79
80 /** Constructor.
81 * @param s The path to search.
82 * @param r The replacement.
83 */
85 {
88
89 // get type and adjust given search parameter
90 integer startPos= 0;
91 integer length= s.Length();
92 if ( s.CharAtStart() == '*' )
93 {
94 ++startPos;
95 --length;
96 if ( s.CharAtEnd() == '*' )
97 {
99 --length;
100 }
101 else
103 }
104 else
105 {
106 if ( s.CharAtEnd() == '*' )
107 {
109 --length;
110 }
111 else
113 }
114 Search._( s, startPos, length );
115
116 // minimum rule check
117 if ( ( ( type == Type::Exact
118 || type == Type::StartsWith )
119 && Search.CharAtStart() != '/'
120 )
121 || ( type == Type::EndsWith
122 && Search.CharAtEnd() == '/'
123 )
124 )
125 Search.Reset(); // illegal rule
126
127
128 Replacement= r;
129 }
130}; // struct DomainSubstitutionRule
131
132
133/** ************************************************************************************************
134 * Implementation struct for class \alib{lox;Lox} following the
135 * \https{Pimpl Idiom,en.cppreference.com/w/cpp/language/pimpl}.
136 **************************************************************************************************/
138{
139 /** The self contained monotonic allocator, that also contains this struct itself. */
141
142 /** The self contained monotonic allocator, that also contains this struct itself. */
144
145#if ALIB_THREADS
146 /** A mutex to control parallel access. */
148#else
149 int AcquirementsCount;
150#endif
151
152 /**
153 * A counter for the quantity of calls. The count includes logs that were suppressed by
154 * disabled <em>Log Domain</em> and those suppressed by the optional log condition parameter.
155 */
157
158 /** A temporary variable to be reused (allocate once pattern). */
160
161 /** A list of a list of logables used for (recursive) logging. */
162 std::vector<Boxes*, StdContMA<Boxes*>> logableContainers;
163
164 /** A list of a list of logables used for (recursive) internal logging. */
165 std::vector<Boxes*, StdContMA<Boxes*>> internalLogables;
166
167 /** The recursion counter for internal logging. */
169
170 /** Information about the source code, method, thread, etc. invoking a log call */
172
173 /**
174 * The root domain \"/\". All registered domains become a sub domain of this root.
175 * If a <em>Sub-Log Domain's Verbosity</em> is not explicitly set, such sub domain inherits
176 * the verbosity of its parent.
177 */
179
180 /** The root domain for internal <em>Log Domains</em>. */
182
183 /** Scope Domains */
185
186 /** Prefix logables store */
188
189 /** Log once counters */
191
192 /** Log data store */
194
195 /** Used for tabular output of logger lists */
197
198 /** Used for tabular output of logger lists */
200
201 /** A key value used in stores if no key is given (global object). */
203
204
205 /** The list of domain substitution rules. */
207
208 /** Flag if a warning on circular rule detection was logged. */
210
211 /** Flag used with configuration variable LOXNAME_DUMP_STATE_ON_EXIT. */
213
214 /**
215 * Constructor.
216 * @param ma The externally created, self-contained monotonic allocator, that also contains
217 * this field.
218 * @param name The lox's name.
219 */
220 LoxImpl( MonoAllocator* ma, const NString& name )
221 : monoAllocator ( ma )
222#if ALIB_THREADS
223 , Lock ( lang::Safeness::Safe )
224#else
225 , AcquirementsCount ( 0 )
226#endif
227 , logableContainers (*ma )
228 , internalLogables (*ma )
229 , scopeInfo ( name , ma, tempVar )
230 , scopeDomains ( scopeInfo, ma )
231 , scopePrefixes ( scopeInfo, ma )
232 , scopeLogOnce ( scopeInfo, ma )
233 , scopeLogData ( scopeInfo, ma )
234 , domainSubstitutions( ma )
235 {
237 LI::init(this);
238 }
239
240 /** Destructor. */
242 {
243 LI::Reset( this, false );
244 }
245
246 /** Returns the number of (recursive) acquirements of this \b Lox.
247 * If greater than \c 1, this is either recursive logging or a user has explicitly
248 * acquired this lox repeatedly (which is not recommended to do).
249 *
250 * @return The number of acquirements. */
252 {
253 #if ALIB_THREADS
254 return Lock.CountAcquirements();
255 #else
256 return AcquirementsCount;
257 #endif
258 }
259
260}; // struct LoxImpl
261
262
263#define ASSERT_ACQUIRED ALIB_ASSERT_ERROR ( impl->CountAcquirements() > 0, "ALOX", "Lox not acquired" )
264
265// #################################################################################################
266// Constructors/destructor
267// #################################################################################################
268
269void LI::Construct( Lox* lox, const NString& name, bool doRegister )
270{
271 MonoAllocator* selfContainedBA= MonoAllocator::Create( 8* 1024 );
272 #if ALIB_DEBUG_MONOMEM
273 selfContainedBA->LogDomain= A_CHAR("MA/ALOX/LOX");
274 #endif
275
276 lox->impl= selfContainedBA->Emplace<LoxImpl>( selfContainedBA, name );
277
278 if( doRegister )
280}
281
282void LI::Destruct( Lox* lox )
283{
284 if( ALOX.Get( lox->GetName(), lang::CreateIfNotExists::No ) == lox )
286
287 lox->impl->~LoxImpl();
288 lox->impl->monoAllocator->~MonoAllocator(); // just destruct, as this is self-contained
289}
290
292{
293 return impl->scopeInfo.loxName;
294}
295
297{
298 return impl->CntLogCalls;
299}
300
301#if ALIB_THREADS
303{
305 return impl->Lock;
306}
307#endif
308
309void LI::Acquire(LoxImpl* impl, const NCString& file, int line, const NCString& func )
310{
311#if ALIB_THREADS
312 ALIB_REL_DBG( impl->Lock.Acquire();
313 , impl->Lock.Acquire(file,line,func); )
314#else
315 ++impl->AcquirementsCount;
317#endif
318
319 impl->scopeInfo.Set( file, line, func ALIB_IF_THREADS(, impl->Lock.GetOwner()) );
320}
321
323{
324 impl->scopeInfo.Release();
325#if ALIB_THREADS
326 impl->Lock.Release();
327#else
328 --impl->AcquirementsCount;
329#endif
330}
331
332void LI::init(LoxImpl* impl)
333{
334 impl->logableContainers.reserve(5); // 5 equals the recursive logging warning threshold
335
336 // create domain trees
337 impl->domains = impl->monoAllocator->Emplace<Domain>( impl->monoAllocator, "" );
338 impl->internalDomains= impl->monoAllocator->Emplace<Domain>( impl->monoAllocator, "$" );
339
340 // create internal sub-domains
341 const NString internalDomainList[]= {"LGR","DMN", "PFX", "THR", "LGD", "VAR" };
342 for ( auto& it : internalDomainList )
343 impl->internalDomains->Find( it, 1, nullptr );
345
346 // read domain substitution rules from configuration
349 LI::GetName(impl)
350 #else
351 String128( LI::GetName( impl ) )
352 #endif
353 );
354 if ( ALOX.GetConfig().Load( variable ) != Priorities::NONE )
355 {
356 for( int ruleNo= 0; ruleNo< variable.Size(); ++ruleNo )
357 {
358 const String& rule= variable.GetString( ruleNo );
359 if( rule.IsEmpty() )
360 continue;
361
362 integer idx= rule.IndexOf( A_CHAR("->") );
363 if ( idx > 0 )
364 {
365 NString64 domainPath ( rule.Substring<false>( 0, idx ) ); domainPath .Trim();
366 NString64 replacement( rule.Substring<false>( idx + 2, rule.Length() - idx - 2 ) ); replacement.Trim();
367 LI::SetDomainSubstitutionRule( impl, domainPath, replacement );
368 }
369 else
370 {
371 // using alib warning here as we can't do internal logging in the constructor
372 ALIB_WARNING( "ALOX", "Syntax error in variable {!Q}.", variable.Fullname() )
373 }
374 }
375 }
376
377}
378
379void LI::Reset(LoxImpl* impl, bool reInitialze)
380{
381 #if ALOX_DBG_LOG
382 if( impl == Log::Get()->impl && Log::DebugLogger != nullptr )
383 {
387 }
388 #endif
389
390 auto& domains = impl->domains;
391 auto& internalDomains = impl->internalDomains;
392 auto& scopeDomains = impl->scopeDomains;
393 auto& scopePrefixes = impl->scopePrefixes;
394 auto& scopeLogOnce = impl->scopeLogOnce;
395 auto& scopeLogData = impl->scopeLogData;
396
397 // unregister each logger in std domains and remove it in internals
398 for ( int i= static_cast<int>(domains->CountLoggers()) - 1 ; i >= 0 ; --i )
399 {
400 Logger* logger= domains->GetLogger( i );
401 int ii= internalDomains->GetLoggerNo( logger );
402 if ( ii >= 0 )
403 internalDomains->RemoveLogger( ii );
405 }
406
407 // unregister remaining loggers in internal domains
408 for ( int i= static_cast<int>(internalDomains->CountLoggers()) - 1 ; i >= 0 ; --i )
409 {
410 Logger* logger= internalDomains->GetLogger( i );
412 }
413
414 // clear domain trees
415 monomem::Destruct(domains);
416 monomem::Destruct(internalDomains);
417
418 // clear scope domains
419 if ( scopeDomains.globalStore.IsNotNull() )
420 delete[] scopeDomains.globalStore.Buffer();
421
422 {
424 for ( it.Initialize( scopeDomains.languageStore.Root() ); it.IsValid(); it.Next() )
425 if( it.Node().Value().IsNotNull() )
426 delete[] it.Node().Value().Buffer();
427 }
428
429 #if ALIB_THREADS
430 for ( auto& thread : scopeDomains.threadStore )
431 for ( auto& it : thread.second )
433 #endif
434
435 if(reInitialze)
436 scopeDomains.Reset();
437
438 // clear scopePrefixes
439 if ( scopePrefixes.globalStore )
440 delete static_cast<PrefixLogable*>( scopePrefixes.globalStore );
441
442 {
444 for ( it.Initialize(scopePrefixes.languageStore.Root()); it.IsValid(); it.Next())
445 if( it.Node().Value() )
446 delete static_cast<PrefixLogable*>( it.Node().Value() );
447 }
448
449
450 #if ALIB_THREADS
451 for ( auto& thread : scopePrefixes.threadStore )
452 for ( auto& it : thread.second )
453 delete static_cast<PrefixLogable*>(it);
454 #endif
455
456 if(reInitialze)
457 scopePrefixes.Reset();
458
459 // clear log once information
460 if ( scopeLogOnce.globalStore )
461 {
462 for( auto mapEntry= scopeLogOnce.globalStore->begin();
463 mapEntry != scopeLogOnce.globalStore->end();
464 ++mapEntry )
465 strings::DeleteString( mapEntry->first );
466 delete scopeLogOnce.globalStore;
467 }
468
469 {
470 ScopeStore<std::map<NString, int>*, false>::LanguageStoreT::RecursiveIterator it;
471 for ( it.Initialize(scopeLogOnce.languageStore.Root()); it.IsValid(); it.Next() )
472 if( it.Node().Value() )
473 {
474 for( auto mapEntry= it.Node().Value()->begin();
475 mapEntry != it.Node().Value()->end();
476 ++mapEntry )
477 delete[] mapEntry->first.Buffer();
478 delete it.Node().Value();
479 }
480 }
481
482
483 #if ALIB_THREADS
484 for ( auto& it : scopeLogOnce.threadStore )
485 {
486 for( auto mapEntry= it.second->begin();
487 mapEntry != it.second->end();
488 ++mapEntry )
489 delete[] mapEntry->first.Buffer();
490 delete it.second;
491 }
492 #endif
493
494 if(reInitialze)
495 scopeLogOnce.Reset();
496
497 // delete LogData objects
498 if ( scopeLogData.globalStore )
499 {
500 for( auto mapEntry= scopeLogData.globalStore->begin();
501 mapEntry != scopeLogData.globalStore->end();
502 ++mapEntry )
503 delete[] mapEntry->first.Buffer();
504 delete scopeLogData.globalStore;
505 }
506
507 {
508 ScopeStore<std::map<NString, Box>*, false>::LanguageStoreT::RecursiveIterator it;
509 for ( it.Initialize(scopeLogData.languageStore.Root()); it.IsValid(); it.Next() )
510 if( it.Node().Value() != nullptr )
511 {
512 for( auto mapEntry= it.Node().Value()->begin();
513 mapEntry != it.Node().Value()->end();
514 ++mapEntry )
515 delete[] mapEntry->first.Buffer();
516 delete it.Node().Value();
517 }
518 }
519
520
521 #if ALIB_THREADS
522 for ( auto it : scopeLogData.threadStore )
523 {
524 for( auto mapEntry= it.second->begin();
525 mapEntry != it.second->end();
526 ++mapEntry )
527 delete[] mapEntry->first.Buffer();
528 delete it.second;
529 }
530 #endif
531
532 // other things
533 if(reInitialze)
534 {
535 scopeLogData .Reset();
536 impl->domainSubstitutions .Reset();
539 impl->CntLogCalls= 0;
540
541 // finally clear the monotonic allocator and rebuild the necessary objects
542 impl->monoAllocator->Reset( impl->initialSnapshot );
543 new (&impl->scopeInfo.scopes) std::vector<Scope , StdContMA<Scope >>( StdContMA<Scope >(*impl->monoAllocator) );
544 new( &impl->logableContainers) std::vector<Boxes*, StdContMA<Boxes*>>( StdContMA<Boxes*>(*impl->monoAllocator) );
545 new( &impl->internalLogables ) std::vector<Boxes*, StdContMA<Boxes*>>( StdContMA<Boxes*>(*impl->monoAllocator) );
546
548 999999, // code for clearing
549 lang::Case::Ignore, NullNString(), lang::Reach::Global, Priorities::NONE );
550
551 LI::init(impl);
552 }
553}
554
556 const NCString& path,
557 lang::Inclusion includeString ,
558 int trimOffset ,
559 lang::Case sensitivity ,
560 const NString& trimReplacement,
561 lang::Reach reach ,
562 Priorities priority )
563
564{
565 impl->scopeInfo.SetSourcePathTrimRule( path, includeString, trimOffset, sensitivity,
566 trimReplacement, reach, priority );
567}
568
569void LI::SetDomain( LoxImpl* impl, const NString& scopeDomain, Scope scope, threads::Thread* thread )
570{
571 if ( !LI::isThreadRelatedScope( impl, scope ) )
572 return;
573 LI::setDomain( impl, scopeDomain, scope, false, thread );
574}
575
576// #################################################################################################
577// Methods
578// #################################################################################################
579Logger* LI::GetLogger(LoxImpl* impl, const NString& loggerName )
580{
581 ASSERT_ACQUIRED
582
583 // search logger
584 Logger* logger;
585 if ( (logger= impl->domains ->GetLogger( loggerName ) ) != nullptr ) return logger;
586 if ( (logger= impl->internalDomains->GetLogger( loggerName ) ) != nullptr ) return logger;
587
588 // not found
589 Boxes& logables= LI::acquireInternalLogables(impl);
590 logables.Add( "No logger named {!Q} found.", loggerName );
591 LI::logInternal( impl, Verbosity::Warning, "LGR", logables );
592 return nullptr;
593}
594
595//! @cond NO_DOX
596void verbositySettingToVariable( Domain& domain, int loggerNo, Variable& var, String512& tempBuf );
597void verbositySettingToVariable( Domain& domain, int loggerNo, Variable& var, String512& tempBuf )
598{
599 tempBuf.Reset() << domain.FullPath << '=' << domain.GetVerbosity( loggerNo );
600 var.Add( tempBuf );
601
602 // loop over all sub domains (recursion)
603 for ( Domain& subDomain : domain.SubDomains )
604 verbositySettingToVariable( subDomain, loggerNo, var, tempBuf );
605}
606//! @endcond
607
609{
610 // When writing back we will use this priority as the maximum to write. This way, if this was
611 // an automatic default value, we will not write back into the user's variable store.
612 // As always, only if the app fetches new variables on termination, this is entry is copied.
613 Box replacements[2]= { LI::GetName( impl ), logger->GetName() };
614 VariableDecl verbositiesDecl( Variables::VERBOSITY );
615 Variable variable( verbositiesDecl, replacements );
616
617 // first token is "writeback" ?
618 ALOX.GetConfig().Load( variable );
619 if ( variable.Size() == 0 )
620 return;
621 Substring firstArg( variable.GetString() );
622 if ( !firstArg.ConsumeString<lang::Case::Ignore, lang::Whitespaces::Trim>( A_CHAR("writeback") ) )
623 return;
624
625 // optionally read a destination variable name
626 Substring destVarCategory= nullptr;
627 Substring destVarName = nullptr;
628
629 if( firstArg.Trim().IsNotEmpty() )
630 {
631 // separate category from variable name
632 integer catSeparatorIdx= firstArg.IndexOf( '_' );
633 if (catSeparatorIdx >= 0 )
634 {
635 destVarCategory= firstArg.Substring<false>( 0 , catSeparatorIdx );
636 destVarName = firstArg.Substring ( catSeparatorIdx + 1);
637 }
638 else
639 destVarName= firstArg;
640
641 if ( destVarName.IsEmpty() )
642 {
643 Boxes& logables= LI::acquireInternalLogables(impl);
644 logables.Add( "Argument 'writeback' in variable {!Q}.\n"
645 "Error: Wrong destination variable name format: {!Q}",
646 variable.Fullname(), firstArg );
647 LI::logInternal( impl, Verbosity::Error, "VAR", logables );
648 return;
649 }
650 }
651
652 // either write directly into LOX_LOGGER_VERBOSITY variable...
653 String256 oldFullName; oldFullName.DbgDisableBufferReplacementWarning();
654 oldFullName << variable.Fullname();
655 if( destVarName.IsEmpty() )
656 {
657 variable.ClearValues( 1 );
658 }
659
660 // ...or into a new given variable
661 else
662 {
663 variable.Declare( destVarCategory, destVarName, verbositiesDecl.Delim );
664 variable.SetFmtHints ( variable.FmtHints() );
665 variable.ReplaceFormatAttrAlignment ( variable.FormatAttrAlignment() );
666 variable.ReplaceComments ( String256("Created at runtime through config option 'writeback' in variable \"")
667 << oldFullName << "\"." );
668 }
669
670 // collect verbosities
671 {
672 int loggerNoMainDom= impl->domains ->GetLoggerNo( logger );
673 int loggerNoIntDom= impl->internalDomains->GetLoggerNo( logger );
674
676 if ( loggerNoMainDom >= 0 ) verbositySettingToVariable( *impl->domains , loggerNoMainDom, variable, tempBuf );
677 if ( loggerNoIntDom >= 0 ) verbositySettingToVariable( *impl->internalDomains, loggerNoIntDom , variable, tempBuf );
678 }
679
680 // now store using the same plug-in as original variable has
681 variable.SetPriority( variable.Priority() );
682 ALOX.GetConfig().Store( variable );
683
684 // internal logging
685 {
686 Boxes& logables= LI::acquireInternalLogables(impl);
687 logables.Add( "Argument 'writeback' in variable {!Q}:\n Verbosities for logger {!Q} written ",
688 oldFullName, logger->GetName() );
689
690 if( destVarName.IsEmpty() )
691 logables.Add( "(to source variable)." );
692 else
693 logables.Add( "to variable {!Q}.", variable.Fullname() );
694 LI::logInternal( impl, Verbosity::Info, "VAR", logables );
695 }
696
697 // verbose logging of the value written
698 {
699 Boxes& logables= LI::acquireInternalLogables(impl);
700 logables.Add(" Value:");
701 for( int i= 0; i< variable.Size() ; ++i )
702 logables.Add( "\n ", variable.GetString(i) );
703 LI::logInternal( impl, Verbosity::Verbose, "VAR", logables );
704 }
705}
706
708{
710 return;
712
715 LI::GetName( impl )
716 #else
717 String128( LI::GetName( impl ) )
718 #endif
719 );
720 ALOX.GetConfig().Load( variable );
721
722 NString64 domain;
723 Verbosity verbosity= Verbosity::Info;
724 Substring tok;
725 bool error= false;
727 for( int tokNo= 0; tokNo< variable.Size(); ++tokNo )
728 {
729 tok= variable.GetString( tokNo );
730 if( tok.IsEmpty() )
731 continue;
732
733
734 // read log domain and verbosity
735 if( tok.IndexOf( '=' ) > 0 )
736 {
738 {
740 enums::Parse<Verbosity>( tok, verbosity );
741 continue;
742 }
744 {
746 domain= tok.Trim();
747 continue;
748 }
749 error= true;
750 break;
751 }
752
753 // read and add state
754 StateInfo stateInfo;
755 if( !enums::Parse<StateInfo>( tok, stateInfo ) )
756 {
757 error= true;
758 break;
759 }
760
761 // as soon as this flag is found, we quit
762 if( stateInfo == StateInfo::NONE )
763 return;
764
765 flags|= stateInfo;
766 }
767 if( error )
768 {
769 Boxes& logables= LI::acquireInternalLogables(impl);
770 logables.Add( "Unknown argument {!Q} in variable {} = {!Q}.",
771 tok, variable.Fullname(), variable.GetString() );
772 LI::logInternal( impl, Verbosity::Error, "VAR", logables);
773 }
774
775 if ( flags != StateInfo::NONE )
776 {
777 LI::State( impl, domain, verbosity, A_CHAR("Auto dump state on exit requested: "), flags );
778 }
779}
780
781
782bool LI::RemoveLogger( LoxImpl* impl, Logger* logger )
783{
784 ASSERT_ACQUIRED
785
786 int noMainDom= impl->domains ->GetLoggerNo( logger );
787 int noIntDom= impl->internalDomains->GetLoggerNo( logger );
788
789 if( noMainDom >= 0 || noIntDom >= 0 )
790 {
793
794 if( noMainDom >= 0 )
795 impl->domains->RemoveLogger( noMainDom );
796
797 if( noIntDom >= 0 )
798 impl->internalDomains->RemoveLogger( noIntDom );
799
801
802 return true;
803 }
804
805 // not found
806 Boxes& logables= LI::acquireInternalLogables(impl);
807 logables.Add( "Logger {!Q} not found. Nothing removed.", logger );
808 LI::logInternal( impl, Verbosity::Warning, "LGR", logables );
809 return false;
810}
811
812Logger* LI::RemoveLogger(LoxImpl* impl, const NString& loggerName )
813{
814 ASSERT_ACQUIRED
815
816 int noMainDom= impl->domains ->GetLoggerNo( loggerName );
817 int noIntDom= impl->internalDomains->GetLoggerNo( loggerName );
818
819 if( noMainDom >= 0 || noIntDom >= 0 )
820 {
821 Logger* logger= impl->domains->GetLogger( noMainDom );
822 if( logger == nullptr ) logger= impl->internalDomains->GetLogger( noIntDom );
823
826
827 if( noMainDom >= 0 )
828 impl->domains->RemoveLogger( noMainDom );
829
830 if( noIntDom >= 0 )
831 impl->internalDomains->RemoveLogger( noIntDom );
832
834
835 Boxes& logables= LI::acquireInternalLogables(impl);
836 logables.Add( "Logger {!Q} removed.", logger );
837 LI::logInternal( impl, Verbosity::Info, "LGR", logables );
838 return logger;
839 }
840
841 // not found
842 Boxes& logables= LI::acquireInternalLogables(impl);
843 logables.Add( "Logger {!Q} not found. Nothing removed.", loggerName );
844 LI::logInternal( impl, Verbosity::Warning, "LGR", logables );
845
846 return nullptr;
847}
848
849void LI::SetVerbosity(LoxImpl* impl, Logger* logger, Verbosity verbosity, const NString& domain, Priorities priority )
850{
851 ASSERT_ACQUIRED
852
853 // check
854 if ( logger == nullptr )
855 {
856 Boxes& logables= LI::acquireInternalLogables(impl);
857 logables.Add( "Given Logger is \"null\". Verbosity not set." );
858 LI::logInternal( impl, Verbosity::Error, "LGR", logables );
859 return;
860 }
861
862 // this might create the (path of) domain(s) and set the \e Logger's verbosities like their
863 // first parent's or as given in configuration
864 Domain* dom= LI::evaluateResultDomain( impl, domain );
865
866 // search logger, insert if not found
867 bool isNewLogger= false;
868 int no= dom->GetLoggerNo( logger );
869 if( no < 0 )
870 {
871 no= dom->AddLogger( logger );
872
873 // error, logger with same name already exists
874 if( no < 0 )
875 {
876 LI::logInternal( impl, Verbosity::Error, "LGR", LI::acquireInternalLogables(impl)
877 .Add( "Unable to add logger {!Q}. Logger with same name exists.", logger ) );
878
879
880 LI::logInternal( impl, Verbosity::Verbose, "LGR",
882 " Request was: SetVerbosity({!Q}, {!Q}, Verbosity::{}, {}). ",
883 logger, dom->FullPath, verbosity, priority ) );
884
885 Logger* existingLogger= dom->GetLogger( logger->GetName() );
886 LI::logInternal( impl, Verbosity::Verbose, "LGR", LI::acquireInternalLogables(impl)
887 .Add( " Existing Logger: {!Q}.", existingLogger ) );
888
889 return;
890 }
891
892 // We have to register with the SmartLock facility of the \e Logger.
893 // But only if we have not done this yet, via the 'other' root domain tree
894 if ( ( dom->GetRoot() == impl->domains ? impl->internalDomains->GetLoggerNo( logger )
895 : impl->domains->GetLoggerNo( logger ) ) < 0 )
896 {
898 }
899
900 // store size of name to support tabular internal log output
901 if ( impl->maxLoggerNameLength < logger->GetName().Length() )
902 impl->maxLoggerNameLength= logger->GetName().Length();
903
904 // for internal log
905 isNewLogger= true;
906
907 // remember that a logger was set after the last removal
908 // (for variable LOXNAME_DUMP_STATE_ON_EXIT)
910 }
911
912 // get verbosities from configuration
913 if( isNewLogger )
914 {
915 Boxes& logables= LI::acquireInternalLogables(impl);
916 logables.Add( "Logger {!Q}.", logger );
917 if( domain.StartsWith(Lox::InternalDomains) )
918 logables.Add(" added for internal log messages.");
919 else
920 logables.Add(" added.");
921 LI::logInternal( impl, Verbosity::Info, "LGR", logables );
922
923 // we have to get all verbosities of already existing domains
924 Box replacements[2]= { LI::GetName( impl ), logger->GetName() };
925 impl->tempVar.Declare( Variables::VERBOSITY, replacements );
926 if( ALOX.GetConfig().Load( impl->tempVar ) != Priorities::NONE )
927 {
928 LI::getAllVerbosities( impl, logger, *impl->domains );
929 LI::getAllVerbosities( impl, logger, *impl->internalDomains );
930 }
931 }
932
933 // do
934 dom->SetVerbosity( no, verbosity, priority );
935
936 Boxes& logables= LI::acquireInternalLogables(impl);
937
938 logables.Add( "Logger {!Q}: {!Fill}{!Q'}{!Fill}= Verbosity::{}.",
939 logger->GetName(),
940 impl->maxLoggerNameLength - logger->GetName().Length(),
941 dom->FullPath,
942 impl->maxDomainPathLength - dom->FullPath.Length() + 1,
943 std::make_pair(verbosity, priority) );
944
945 Verbosity actVerbosity= dom->GetVerbosity( no );
946 if( actVerbosity != verbosity )
947 logables.Add( " Lower priority ({} < {}). Remains {}.",
948 priority, dom->GetPriority(no), actVerbosity );
949
950 LI::logInternal( impl, Verbosity::Info, "LGR", logables );
951}
952
953void LI::SetVerbosity(LoxImpl* impl, const NString& loggerName, Verbosity verbosity, const NString& domain, Priorities priority )
954{
955 ASSERT_ACQUIRED
956
957 // get domain
958 Domain* dom= LI::evaluateResultDomain( impl, domain );
959
960 // get logger
961 Logger* logger;
962 int no= dom->GetLoggerNo( loggerName );
963 if( no >= 0 )
964 logger= dom->GetLogger( no );
965 else
966 {
967 // we have to check if the logger was added in the 'other' tree
968 Domain* otherTree= dom->GetRoot() == impl->domains ? impl->internalDomains
969 : impl->domains;
970 no= otherTree->GetLoggerNo( loggerName );
971 if ( no < 0 )
972 {
973 // error
974 Boxes& logables= LI::acquireInternalLogables(impl);
975 logables.Add( "Logger not found. Request was: SetVerbosity({!Q}, {!Q}, Verbosity::{}, {}).",
976 loggerName, dom->FullPath, verbosity, priority );
977 LI::logInternal( impl, Verbosity::Warning, "LGR", logables );
978 return;
979 }
980
981 logger= otherTree->GetLogger( no );
982 }
983
984 // use the overloaded method
985 LI::SetVerbosity( impl, logger, verbosity, domain, priority );
986}
987
989 const NString& scopeDomain, Scope scope,
990 bool removeNTRSD, threads::Thread* thread )
991{
992 //note: the public class interface assures that \p{removeNTRSD} (named thread related scope domain)
993 // only evaluates true for thread related scopes
994
995 ASSERT_ACQUIRED
996
997 // check
998 int pathLevel= LI::checkScopeInformation( impl, scope, "DMN" );
999 if( pathLevel < 0 )
1000 return;
1001
1002 #if ALIB_THREADS
1003 ThreadID threadID= thread != nullptr ? thread->GetId() : UNDEFINED_THREAD;
1004 #else
1005 threads::ThreadID threadID= UNDEFINED_THREAD;
1006 (void) thread;
1007 #endif
1008
1009 NString previousScopeDomain;
1010
1011 impl->scopeDomains.InitAccess( scope, pathLevel, threadID );
1012 if ( removeNTRSD )
1013 {
1014 previousScopeDomain= impl->scopeDomains.Remove( scopeDomain );
1015 }
1016 else
1017 {
1018 if ( scopeDomain.IsNotEmpty() )
1019 {
1020 NString128 trimmable( scopeDomain );
1021 previousScopeDomain= impl->scopeDomains.Store( strings::AllocateCopy( trimmable.Trim() ) );
1022 }
1023 else
1024 previousScopeDomain= impl->scopeDomains.Remove( nullptr );
1025 }
1026
1027 // log info on this
1028 Boxes& logables= LI::acquireInternalLogables(impl);
1029 if ( !removeNTRSD && scopeDomain.IsNotEmpty() )
1030 {
1031 logables.Add("{!Q'} set as default for {}.", scopeDomain, (scope + pathLevel) );
1032
1033 if ( previousScopeDomain == nullptr )
1034 LI::logInternal( impl, Verbosity::Info, "DMN", logables );
1035 else
1036 {
1037 if ( previousScopeDomain.Equals<false>( scopeDomain ) )
1038 {
1039 logables.Add( " (Was already set.)" );
1040 LI::logInternal( impl, Verbosity::Verbose, "DMN", logables );
1041 }
1042 else
1043 {
1044 logables.Add( " Replacing previous default {!Q'}.", previousScopeDomain );
1045 LI::logInternal( impl, Verbosity::Warning, "DMN", logables );
1046 }
1047 }
1048
1049 }
1050 else
1051 {
1052 if ( previousScopeDomain != nullptr )
1053 {
1054 logables.Add("{!Q'} removed from {}.", previousScopeDomain, (scope + pathLevel) );
1055 LI::logInternal( impl, Verbosity::Info, "DMN", logables );
1056 }
1057 else
1058 {
1059 if ( removeNTRSD )
1060 logables.Add("{!Q'} not found. Nothing removed for {}.", scopeDomain );
1061 else
1062 logables.Add("Empty Scope Domain given, nothing registered for {}.", scopeDomain);
1063
1064 logables.Add( scope + pathLevel);
1065 LI::logInternal( impl, Verbosity::Warning, "DMN", logables );
1066 }
1067 }
1068
1069 // it is on us to delete the previous one
1070 if ( previousScopeDomain.IsNotNull() )
1071 strings::DeleteString( previousScopeDomain );
1072}
1073
1074void LI::RemoveThreadDomain(LoxImpl* impl, const NString& scopeDomain, Scope scope, threads::Thread* thread )
1075{
1076 if ( !LI::isThreadRelatedScope( impl, scope ) )
1077 return;
1078
1079 // check
1080 if ( scopeDomain.IsEmpty() )
1081 {
1082 Boxes& logables= LI::acquireInternalLogables(impl);
1083 logables.Add( "Illegal parameter. No scope domain path given. Nothing removed for {}.",
1084 scope );
1085 LI::logInternal( impl, Verbosity::Warning, "DMN", logables );
1086
1087 // do nothing
1088 return;
1089 }
1090
1091 // invoke internal master
1092 LI::setDomain( impl, scopeDomain, scope, true, thread);
1093}
1094
1095void LI::SetDomainSubstitutionRule(LoxImpl* impl, const NString& domainPath, const NString& replacement )
1096{
1097 // check null param: clears all rules
1098 if ( domainPath.IsEmpty() )
1099 {
1100 impl->oneTimeWarningCircularDS= false;
1101 impl->domainSubstitutions.Clear();
1102 LI::logInternal( impl, Verbosity::Info, "DMN", "Domain substitution rules removed.");
1103 return;
1104 }
1105
1106
1107 // create rule
1108 DomainSubstitutionRule newRule( domainPath, replacement );
1109 if ( newRule.Search.IsEmpty() )
1110 {
1111 LI::logInternal( impl, Verbosity::Warning, "DMN", "Illegal domain substitution rule. Nothing stored." );
1112 return;
1113 }
1114
1115 // search existing rule
1117 for( it= impl->domainSubstitutions.begin(); it != impl->domainSubstitutions.end() ; ++it )
1118 {
1119 if ( (*it).type == newRule.type
1120 && (*it).Search.Equals<false>( newRule.Search ) )
1121 break;
1122 }
1123
1124 // no replacement given?
1125 if ( replacement.IsEmpty() )
1126 {
1127 Boxes& logables= LI::acquireInternalLogables(impl);
1128 if ( it == impl->domainSubstitutions.end() )
1129 {
1130 logables.Add("Domain substitution rule {!Q} not found. Nothing to remove.", domainPath );
1131 LI::logInternal( impl, Verbosity::Warning, "DMN", logables );
1132 return;
1133 }
1134
1135 logables.Add("Domain substitution rule {!Q} -> {!Q} removed.", domainPath, (*it).Replacement );
1136 LI::logInternal( impl, Verbosity::Info, "DMN", logables );
1137 impl->domainSubstitutions.Erase( it );
1138 return;
1139 }
1140
1141 Boxes& logables= LI::acquireInternalLogables(impl);
1142 logables.Add("Domain substitution rule {!Q} -> {!Q} set.", domainPath, newRule.Replacement );
1143
1144 // change of rule
1145 NString256 msg;
1146 if ( it != impl->domainSubstitutions.end() )
1147 {
1148 msg << " Replacing previous -> \"" << (*it).Replacement << "\".";
1149 logables.Add( msg );
1150 (*it).Replacement.Reset( newRule.Replacement );
1151 }
1152 else
1153 impl->domainSubstitutions.EmplaceBack( newRule );
1154
1155 LI::logInternal( impl, Verbosity::Info, "DMN", logables );
1156}
1157
1158void LI::setPrefix(LoxImpl* impl, const Box& prefix, Scope scope, threads::Thread* thread )
1159{
1160 ASSERT_ACQUIRED
1161
1162 // check
1163 int pathLevel= LI::checkScopeInformation( impl, scope, "PFX" );
1164 if( pathLevel < 0 )
1165 return;
1166
1167 #if ALIB_THREADS
1168 ThreadID threadID= thread != nullptr ? thread->GetId() : UNDEFINED_THREAD;
1169 #else
1170 threads::ThreadID threadID= UNDEFINED_THREAD;
1171 (void) thread;
1172 #endif
1173
1174 impl->scopePrefixes.InitAccess( scope, pathLevel, threadID );
1175 bool isVoidOrEmpty= prefix.IsType<void>()
1176 || prefix.IsNull()
1177 || ( prefix.IsArray() && !prefix.UnboxLength() );
1178
1179 Box* previousLogable= !isVoidOrEmpty ? impl->scopePrefixes.Store( new PrefixLogable( prefix ) )
1180 : impl->scopePrefixes.Remove( nullptr );
1181
1182
1183 Boxes& logables= LI::acquireInternalLogables(impl);
1184 logables.Add( "Object ");
1185 Verbosity intMsgVerbosity= Verbosity::Info;
1186 if ( !isVoidOrEmpty )
1187 {
1188 logables.Add( prefix, " added as prefix logable for {}.", (scope + pathLevel) );
1189
1190 if ( previousLogable != nullptr )
1191 {
1192 if ( previousLogable->Call<FEquals>( prefix ) )
1193 {
1194 logables.Add(" (Same as before.)");
1195 intMsgVerbosity= Verbosity::Verbose;
1196 }
1197 else
1198 logables.Add(" Replacing previous {}.", *previousLogable );
1199 }
1200 }
1201 else
1202 {
1203 if ( previousLogable != nullptr )
1204 logables.Add( "{!Q} removed from list of prefix logables for {}.", *previousLogable);
1205 else
1206 {
1207 logables.Add( "<nullptr> given but no prefix logable to remove for {}.");
1208 intMsgVerbosity= Verbosity::Warning;
1209 }
1210 logables.Add( scope + pathLevel );
1211 }
1212 LI::logInternal( impl, intMsgVerbosity, "PFX", logables );
1213
1214 // it is on us to delete the previous one
1215 if ( previousLogable != nullptr )
1216 delete static_cast<PrefixLogable*>( previousLogable );
1217}
1218
1219
1220void LI::SetPrefix(LoxImpl* impl, const Box& prefix, const NString& domain, lang::Inclusion otherPLs )
1221{
1222 ASSERT_ACQUIRED
1223
1224 Domain* dom= LI::evaluateResultDomain( impl, domain );
1225
1226 bool isVoidOrEmpty= prefix.IsType<void>()
1227 || prefix.IsNull()
1228 || ( prefix.IsArray() && !prefix.UnboxLength() );
1229
1230 Boxes& logables= LI::acquireInternalLogables(impl);
1231 Verbosity intLogVerbosity= Verbosity::Info;
1232 PrefixLogable* removedLogable= nullptr;
1233
1234 if ( !isVoidOrEmpty )
1235 {
1236 // create logable: if String* type, then copy the string. We are responsible, then.
1237 logables.Add( "Object {} added as prefix logable for ", prefix );
1238
1239 dom->PrefixLogables.EmplaceBack( new PrefixLogable( prefix ), otherPLs );
1240 }
1241 else
1242 {
1243 auto qtyPLs= dom->PrefixLogables.Size();
1244 if ( qtyPLs > 0 )
1245 {
1246 removedLogable= dom->PrefixLogables.Back().first;
1247 dom->PrefixLogables.PopBack();
1248 logables.Add( "Object {} removed from list of prefix logables for",
1249 *static_cast<Box*>(removedLogable) );
1250 }
1251 else
1252 {
1253 logables.Add( "No prefix logables to remove for" );
1254 intLogVerbosity= Verbosity::Warning;
1255 }
1256 }
1257
1258 logables.Add(" domain {!Q'}.", dom->FullPath);
1259 LI::logInternal( impl, intLogVerbosity, "PFX", logables );
1260
1261 if( removedLogable )
1262 delete removedLogable;
1263}
1264
1265
1266#if defined (__GLIBCXX__) || defined(__APPLE__) || defined(__ANDROID_NDK__)
1267 void LI::SetStartTime(LoxImpl* impl, time_t startTime, const NString& loggerName )
1268 {
1269 TickConverter converter;
1270 LI::SetStartTime( impl, converter.ToTicks( DateTime::FromEpochSeconds( startTime ) ), loggerName );
1271 }
1272
1273#elif defined( _WIN32 )
1274 void LI::SetStartTime(LoxImpl* impl, const FILETIME& startTime, const NString& loggerName )
1275 {
1276 TickConverter converter;
1277 LI::SetStartTime( impl, converter.ToTicks( DateTime::FromFileTime( startTime ) ), loggerName );
1278 }
1279#else
1280 #pragma message "Unknown Platform in file: " __FILE__ )
1281#endif
1282
1283void LI::SetStartTime(LoxImpl* impl, Ticks startTime, const NString& loggerName )
1284{
1285 ASSERT_ACQUIRED
1286
1287 bool foundOne= false;
1288 for( int loggerNo= 0; loggerNo < impl->domains->CountLoggers(); ++loggerNo )
1289 {
1290 // request logger only from main domain tree
1291 Logger* logger= impl->domains->GetLogger( loggerNo );
1292 if( loggerName.IsNotEmpty() && !loggerName.Equals<false, lang::Case::Ignore>( logger->GetName()) )
1293 continue;
1294 foundOne= true;
1295
1296 // log info on this
1297 Boxes& logables= LI::acquireInternalLogables(impl);
1298 logables.Add( "Logger {!Q}: Start time set to ", logger->GetName() );
1299 if ( !startTime.IsSet() )
1300 {
1301 startTime= Ticks::Now();
1302 logables.Add( "'now'" );
1303 }
1304 else
1305 {
1306 DateTime asDateTime;
1307 TextLogger* asTextLogger= dynamic_cast<TextLogger*>(logger);
1308 if( asTextLogger != nullptr )
1309 asDateTime= asTextLogger->MetaInfo->DateConverter.ToDateTime( startTime );
1310 else
1311 asDateTime= TickConverter().ToDateTime( startTime );
1312 logables.Add( "{:yyyy-MM-dd HH:mm:ss}", asDateTime );
1313 }
1314 // do
1315 logger->TimeOfCreation.SetAs( startTime );
1316 logger->TimeOfLastLog .SetAs( startTime );
1317
1318 LI::logInternal( impl, Verbosity::Info, "LGR", logables );
1319 }
1320
1321 if ( loggerName.IsNotEmpty() && !foundOne )
1322 {
1323 Boxes& logables= LI::acquireInternalLogables(impl);
1324 logables.Add( "Logger {!Q}: not found. Start time not set.", loggerName );
1325 LI::logInternal( impl, Verbosity::Error, "LGR", logables );
1326 return;
1327 }
1328}
1329
1330
1331void LI::MapThreadName(LoxImpl* impl, const String& threadName, threads::ThreadID id )
1332{
1333 #if ALIB_THREADS
1334 ASSERT_ACQUIRED
1335
1336 // get current thread id
1337 String origThreadName;
1338 if ( id == 0 )
1339 {
1341 id= t->GetId();
1342 origThreadName= t->GetName();
1343 }
1344 else
1345 origThreadName= nullptr;
1346
1347 // add entry
1348 impl->scopeInfo.threadDictionary.EmplaceOrAssign(id, threadName);
1349
1350 // log info on this
1351 Boxes& logables= LI::acquireInternalLogables(impl);
1352 logables.Add( "Mapped thread ID {} to {!Q}.", id, threadName);
1353 if ( origThreadName.IsNotEmpty() )
1354 logables.Add(" Original thread name: {!Q}.", origThreadName );
1355 LI::logInternal( impl, Verbosity::Info, "THR", logables );
1356 #else
1357 (void) impl;
1358 (void) threadName;
1359 (void) id;
1360 #endif
1361}
1362
1363void LI::once( LoxImpl* impl,
1364 const NString& domain, Verbosity verbosity,
1365 const Box& logable,
1366 const String& pGroup,
1367 Scope scope,
1368 int quantity )
1369{
1370 int pathLevel= LI::checkScopeInformation( impl, scope, "DMN" );
1371 if( pathLevel < 0 )
1372 return;
1373
1374 // We need a group. If none is given, there are two options:
1375 NString512 group(pGroup);
1376 bool groupWasEmtpy= group.IsEmpty();
1377 if ( groupWasEmtpy )
1378 {
1379 // GLOBAL scope: exact code line match
1380 if ( scope == Scope::Global )
1381 {
1382 scope= Scope::Filename;
1383 group._('#')._( impl->scopeInfo.GetLineNumber() );
1384 }
1385
1386 // not GLOBAL scope: Unique group per Scope
1387 else
1388 {
1389 group._( impl->noKeyHashKey );
1390 }
1391 }
1392
1393 // get the store
1394 impl->scopeLogOnce.InitAccess( scope, pathLevel, UNDEFINED_THREAD );
1395
1396 std::map<NString, int>* map= impl->scopeLogOnce.Get();
1397 if( map == nullptr )
1398 {
1399 map= new std::map<NString, int>();
1400 impl->scopeLogOnce.Store( map );
1401 }
1402
1403 // create map entry (if not created yet)
1404 auto it= map->find( group );
1405 if (it == map->end() )
1406 it= map->insert( std::make_pair( strings::AllocateCopy(group), 0) ).first;
1407
1408 // log Once
1409 if ( quantity >= 0 )
1410 {
1411 if ( it->second < quantity )
1412 {
1413 ++it->second;
1414
1415 // do the log
1416 LI::GetLogableContainer(impl) .Add( std::forward<const Box&>( logable ) );
1417 LI::Entry( impl, domain, verbosity );
1418
1419 // log info if this was the last time
1420 if( it->second == quantity )
1421 {
1422 Boxes& logables= LI::acquireInternalLogables(impl);
1423 logables.Add( "Once() reached limit of {} logs. No further logs for ", quantity );
1424
1425 if ( groupWasEmtpy )
1426 logables.Add( scope == Scope::Global ? Box( "this line" )
1427 : Box(scope + pathLevel) );
1428 else
1429 {
1430 logables.Add( "group {!Q}", group );
1431 if ( scope != Scope::Global )
1432 logables.Add(" in ", (scope + pathLevel) );
1433 }
1434 logables.Add('.');
1435
1436 LI::logInternal( impl, Verbosity::Info, "", logables );
1437 }
1438 }
1439 }
1440
1441 // log Nth
1442 else
1443 {
1444 if ( it->second++ % -quantity == 0 )
1445 {
1446 LI::GetLogableContainer(impl) .Add( std::forward<const Box&>( logable ) );
1447 LI::Entry( impl, domain, verbosity );
1448 }
1449 }
1450}
1451
1452void LI::store( LoxImpl* impl, const Box& data, const NString& pKey, Scope scope )
1453{
1454 // We need a key. If none is given, we use a constant one indicating that storage is
1455 // associated exclusively with scope
1456 NString256 key(pKey);
1457 bool keyWasEmtpy= key.IsEmpty();
1458 if ( keyWasEmtpy )
1459 key= impl->noKeyHashKey;
1460
1461 // get path level
1462 int pathLevel= 0;
1463 if ( scope > Scope::Path )
1464 {
1465 pathLevel= UnderlyingIntegral( scope - Scope::Path );
1466 scope= Scope::Path;
1467 }
1468
1469 // get the store
1470 impl->scopeLogData.InitAccess( scope, pathLevel, UNDEFINED_THREAD );
1471 std::map<NString, Box>* map= impl->scopeLogData.Get();
1472 if( map == nullptr )
1473 {
1474 map= new std::map<NString, Box>;
1475 impl->scopeLogData.Store( map );
1476 }
1477
1478 Boxes& logables= LI::acquireInternalLogables(impl);
1479
1480 // create map entry (if not created yet)
1481 auto it= map->find( key );
1482 if ( !data.IsType<void>() )
1483 {
1484 bool replacedPrevious= false;
1485 if ( it == map->end() )
1486 it= map->insert( std::make_pair( strings::AllocateCopy(key), data ) ).first;
1487 else
1488 {
1489 replacedPrevious= true;
1490 it->second= data;
1491 }
1492
1493 // log info if this was the last time
1494 logables.Add( "Stored data " );
1495
1496 if ( !keyWasEmtpy )
1497 logables.Add( " with key {!Q} ", key );
1498 logables.Add( "in {}.", (scope + pathLevel) );
1499 if ( replacedPrevious )
1500 logables.Add( " (Replaced and deleted previous.)" );
1501 }
1502
1503 // delete
1504 else
1505 {
1506 if ( it != map->end() )
1507 {
1508 const nchar* keyBuffer= it->first.Buffer();
1509 map->erase( it );
1510 if ( map->size() == 0 )
1511 {
1512 delete map;
1513 impl->scopeLogData.Remove( nullptr );
1514 }
1515 delete [] keyBuffer;
1516 logables.Add( "Deleted map data " );
1517 }
1518 else
1519 logables.Add( "No map data found to delete " );
1520
1521 if ( !keyWasEmtpy )
1522 logables.Add( " with key {!Q} ", key );
1523 logables.Add( "in {}.", (scope + pathLevel) );
1524 }
1525
1526 LI::logInternal( impl, Verbosity::Info, "LGD", logables );
1527}
1528
1529
1530Box LI::retrieve( LoxImpl* impl, const NString& pKey, Scope scope )
1531{
1532 // We need a key. If none is given, we use a constant one indicating that storage is
1533 // associated exclusively with scope
1534 NString256 key= pKey;
1535 bool keyWasEmtpy= key.IsEmpty();
1536 if ( keyWasEmtpy )
1537 key= impl->noKeyHashKey;
1538
1539 int pathLevel= 0;
1540 if ( scope > Scope::Path )
1541 {
1542 pathLevel= UnderlyingIntegral( scope - Scope::Path );
1543 scope= Scope::Path;
1544 }
1545 // get the data (create if not found)
1546 impl->scopeLogData.InitAccess( scope, pathLevel, UNDEFINED_THREAD );
1547 Box returnValue;
1548 for( int i= 0; i < 2 ; ++i )
1549 {
1550 std::map<NString, Box>* map= impl->scopeLogData.Get();
1551 if( map != nullptr )
1552 {
1553 auto it= map->find( key );
1554 if ( it != map->end() )
1555 returnValue= it->second;
1556 }
1557
1558 if ( returnValue.IsType<void>() )
1559 LI::store( impl, Box(), pKey, scope + pathLevel );
1560 else
1561 break;
1562 }
1563
1564 // log info if this was the last time
1565 Boxes& logables= LI::acquireInternalLogables(impl);
1566 logables.Add( "Data " );
1567
1568 if ( !keyWasEmtpy )
1569 logables.Add( " with key {!Q} ", key );
1570 logables.Add( "in ", (scope + pathLevel), ( !returnValue.IsType<void>() ? " received."
1571 : " not found." ) );
1572
1573 LI::logInternal( impl, Verbosity::Info, "LGD", logables );
1574 return returnValue;
1575}
1576
1577
1578void LI::State( LoxImpl* impl,
1579 const NString& domain,
1580 Verbosity verbosity,
1581 const String& headLine,
1582 StateInfo flags )
1583{
1584 ASSERT_ACQUIRED
1585
1586 NAString buf;
1587 buf.SetBuffer( 2048 );
1588 if ( headLine.IsNotEmpty() )
1589 buf._<false>( headLine ).NewLine();
1590
1591 LI::GetState( impl, buf, flags );
1592
1593 LI::GetLogableContainer(impl) .Add( buf );
1594 LI::Entry( impl, domain, verbosity );
1595}
1596
1598{
1599 auto cntAcquirements= impl->CountAcquirements();
1600 ALIB_ASSERT_ERROR( cntAcquirements >= 1, "ALOX", "Lox not acquired." )
1601 ALIB_ASSERT_WARNING( cntAcquirements < 5, "ALOX", "Logging recursion depth >= 5" )
1602 while( static_cast<int>(impl->logableContainers.size()) < cntAcquirements )
1603 impl->logableContainers.emplace_back( impl->monoAllocator->Emplace<Boxes>(impl->monoAllocator) );
1604 Boxes& logables= *impl->logableContainers[static_cast<size_t>(cntAcquirements - 1)];
1605 logables.clear();
1606 return logables;
1607}
1608
1609void LI::Entry(LoxImpl* impl, const NString& domain, Verbosity verbosity )
1610{
1611 ASSERT_ACQUIRED
1612
1613 // auto-initialization of debug loggers
1614 #if ALOX_DBG_LOG
1615 if( impl == Log::Get()->impl
1616 && impl->domains->CountLoggers() == 0
1617 && Log::DebugLogger == nullptr )
1618 Log::AddDebugLogger( Log::Get() );
1619 #endif
1620
1621 ALIB_ASSERT_ERROR(ALOX.IsBootstrapped(), "ALOX", "ALox (ALib) was not properly bootstrapped." )
1622
1623 ++impl->CntLogCalls;
1624
1625 if ( impl->domains->CountLoggers() == 0 )
1626 return;
1627
1628 LI::log( impl,
1629 LI::evaluateResultDomain( impl, domain ),
1630 verbosity,
1631 *impl->logableContainers[static_cast<size_t>(impl->CountAcquirements() - 1)],
1632 lang::Inclusion::Include );
1633}
1634
1635int LI::IsActive( LoxImpl* impl, Verbosity verbosity, const NString& domain )
1636{
1637 ASSERT_ACQUIRED
1638
1639 // auto-initialization of debug loggers
1640 #if ALOX_DBG_LOG
1641 if( impl == Log::Get()->impl
1642 && impl->domains->CountLoggers() == 0
1643 && Log::DebugLogger == nullptr )
1644 Log::AddDebugLogger( Log::Get() );
1645 #endif
1646
1647 ALIB_ASSERT_ERROR(ALOX.IsBootstrapped(), "ALOX", "ALox (ALib) was not properly bootstrapped." )
1648
1649 if ( impl->domains->CountLoggers() == 0 )
1650 return 0;
1651
1652 Domain* dom= LI::evaluateResultDomain( impl, domain );
1653
1654 int result= 0;
1655 PrefixLogable marker(nullptr);
1656 for ( int i= 0; i < dom->CountLoggers() ; ++i )
1657 if( dom->IsActive( i, verbosity ) )
1658 ++result;
1659 return result;
1660}
1661
1662void LI::IncreaseLogCounter( LoxImpl* impl)
1663{
1664 ++impl->CntLogCalls;
1665}
1666
1667void LI::entryDetectDomainImpl(LoxImpl* impl, Verbosity verbosity )
1668{
1669 Boxes& logables= *impl->logableContainers[static_cast<size_t>(impl->CountAcquirements() - 1)];
1670 if ( logables.Size() > 1 && logables[0].IsArrayOf<nchar>() )
1671 {
1672 NString firstArg= logables[0].Unbox<NString>();
1673
1674 // accept internal domain at the start
1675 integer idx= 0;
1676 if( firstArg.StartsWith( Lox::InternalDomains ) )
1677 idx+= Lox::InternalDomains.Length();
1678
1679 // loop over domain and check for illegal characters
1680 bool illegalCharacterFound= false;
1681 for( ; idx< firstArg.Length() ; ++idx )
1682 {
1683 char c= firstArg[idx];
1684 if (! ( isdigit( c )
1685 || ( c >= 'A' && c <= 'Z' )
1686 || c == '-'
1687 || c == '_'
1688 || c == '/'
1689 || c == '.'
1690 ) )
1691 {
1692 illegalCharacterFound= true;
1693 break;
1694 }
1695 }
1696
1697 if ( illegalCharacterFound )
1698 {
1699 LI::Entry( impl, nullptr, verbosity );
1700 return;
1701 }
1702
1703 logables.erase( logables.begin() );
1704 LI::Entry( impl, firstArg, verbosity );
1705 return;
1706 }
1707
1708 LI::Entry( impl, nullptr, verbosity );
1709}
1710
1711
1712// #################################################################################################
1713// internals
1714// #################################################################################################
1715Domain* LI::evaluateResultDomain(LoxImpl* impl, const NString& domainPath )
1716{
1717 NString128 resDomain;
1718
1719 // 0. internal domain tree?
1720 if ( domainPath.StartsWith( Lox::InternalDomains ) )
1721 {
1722 // cut "$/" from the path
1723 resDomain._( domainPath, Lox::InternalDomains.Length() );
1724 return LI::findDomain( impl, *impl->internalDomains, resDomain );
1725 }
1726
1727 // loop over scopes
1728 NString64 localPath; localPath.DbgDisableBufferReplacementWarning();
1729 impl->scopeDomains.InitWalk( Scope::ThreadInner,
1730 // we have to provide NullString if parameter is empty
1731 domainPath.IsNotEmpty() ? localPath._(domainPath)
1732 : NullNString()
1733 );
1734 NString nextDefault;
1735 while( (nextDefault= impl->scopeDomains.Walk() ).IsNotNull() )
1736 {
1737 ALIB_ASSERT( nextDefault.IsNotEmpty() )
1738
1739 if ( resDomain.IsNotEmpty() )
1740 resDomain.InsertAt( "/", 0);
1741 resDomain.InsertAt( nextDefault, 0 );
1742
1743 // absolute path? That's it
1744 if ( resDomain.CharAtStart() == Domain::Separator() )
1745 break;
1746 }
1747
1748 return LI::findDomain( impl, *impl->domains, resDomain );
1749}
1750
1751void LI::getVerbosityFromConfig(LoxImpl* impl, Logger* logger, Domain& dom )
1752{
1753 // get logger number. It may happen that the logger is not existent in this domain tree.
1754 int loggerNo= dom.GetLoggerNo( logger ) ;
1755 if ( loggerNo < 0 )
1756 return;
1757
1758 for( int varNo= 0; varNo< impl->tempVar.Size(); ++varNo )
1759 {
1760 Tokenizer verbosityTknzr( impl->tempVar.GetString( varNo ), '=' );
1761
1762 NString256 domainStrBuf;
1763 Substring domainStrParser= verbosityTknzr.Next();
1764 if ( domainStrParser.ConsumeString<lang::Case::Ignore>( A_CHAR("INTERNAL_DOMAINS")) )
1765 {
1766 while ( domainStrParser.ConsumeChar('/') )
1767 ;
1768 domainStrBuf << Lox::InternalDomains << domainStrParser;
1769 }
1770 else
1771 domainStrBuf._( domainStrParser );
1772
1773 NSubstring domainStr= domainStrBuf ;
1774
1775 Substring verbosityStr= verbosityTknzr.Next();
1776 if ( verbosityStr.IsEmpty() )
1777 continue;
1778
1779 int searchMode= 0;
1780 if ( domainStr.ConsumeChar ( '*' ) ) searchMode+= 2;
1781 if ( domainStr.ConsumeCharFromEnd( '*' ) ) searchMode+= 1;
1782 if( ( searchMode == 0 && dom.FullPath.Equals <false,lang::Case::Ignore>( domainStr ) )
1783 || ( searchMode == 1 && dom.FullPath.StartsWith<true ,lang::Case::Ignore>( domainStr ) )
1784 || ( searchMode == 2 && dom.FullPath.EndsWith <true ,lang::Case::Ignore>( domainStr ) )
1785 || ( searchMode == 3 && dom.FullPath.IndexOf <true ,lang::Case::Ignore>( domainStr ) >=0 )
1786 )
1787 {
1788 Verbosity verbosity(Verbosity::Info);
1789 enums::Parse<Verbosity>(verbosityStr, verbosity );
1790 dom.SetVerbosity( loggerNo, verbosity, impl->tempVar.Priority() );
1791
1792 // log info on this
1793 NString512 msg;
1794 msg._<false>( "Logger \"" )._<false>( logger->GetName() ) ._<false>( "\":" )._(NFormat::Tab(11 + impl->maxLoggerNameLength))
1795 ._<false>( '\'' )._<false>( dom.FullPath )
1796 ._( '\'' ).InsertChars(' ', impl->maxDomainPathLength - dom.FullPath.Length() + 1 )
1797 ._( "= Verbosity::" )
1798 ._( std::make_pair(verbosity, dom.GetPriority( loggerNo )) ).TrimEnd()
1799 ._<false>( '.' );
1800
1801 LI::logInternal( impl, Verbosity::Info, "LGR", msg );
1802 }
1803 }
1804}
1805
1806void LI::getDomainPrefixFromConfig(LoxImpl* impl, Domain& dom )
1807{
1808 Variable variable( Variables::PREFIXES,
1810 LI::GetName( impl )
1811 #else
1812 String128( LI::GetName( impl ) )
1813 #endif
1814 );
1815 if( ALOX.GetConfig().Load( variable ) == Priorities::NONE )
1816 return;
1817
1818 for( int varNo= 0; varNo< variable.Size(); ++varNo )
1819 {
1820 Tokenizer prefixTok( variable.GetString( varNo ), '=' );
1821
1822 NString128 domainStrBuf;
1823 Substring domainStrParser= prefixTok.Next();
1824 if ( domainStrParser.ConsumeString<lang::Case::Ignore>( A_CHAR("INTERNAL_DOMAINS")) )
1825 {
1826 while ( domainStrParser.ConsumeChar('/') )
1827 ;
1828 domainStrBuf << Lox::InternalDomains << domainStrParser;
1829 }
1830 else
1831 domainStrBuf._( domainStrParser );
1832
1833 NSubstring domainStr= domainStrBuf ;
1834
1835 Tokenizer prefixTokInner( prefixTok.Next(), ',' );
1836 Substring prefixStr= prefixTokInner.Next();
1837 if ( prefixStr.IsEmpty() )
1838 continue;
1839 if ( prefixStr.ConsumeChar( '\"' ) )
1840 prefixStr.ConsumeCharFromEnd( '\"' );
1841
1843 prefixTokInner.Next();
1844 if ( prefixTokInner.Actual.IsNotEmpty() )
1846
1847 int searchMode= 0;
1848 if ( domainStr.ConsumeChar ( '*' ) ) searchMode+= 2;
1849 if ( domainStr.ConsumeCharFromEnd( '*' ) ) searchMode+= 1;
1850 if( ( searchMode == 0 && dom.FullPath.Equals <false,lang::Case::Ignore>( domainStr ) )
1851 || ( searchMode == 1 && dom.FullPath.StartsWith<true ,lang::Case::Ignore>( domainStr ) )
1852 || ( searchMode == 2 && dom.FullPath.EndsWith <true ,lang::Case::Ignore>( domainStr ) )
1853 || ( searchMode == 3 && dom.FullPath.IndexOf <true ,lang::Case::Ignore>( domainStr ) >=0 )
1854 )
1855 {
1856 dom.PrefixLogables.EmplaceBack( new PrefixLogable( prefixStr ), otherPLs );
1857
1858 // log info on this
1859 NString128 msg; msg._<false>( "String \"" )._<false>( prefixStr )._<false> ( "\" added as prefix logable for domain \'" )
1860 ._<false>( dom.FullPath )
1861 ._<false>( "\'. (Retrieved from configuration variable" )
1862 ._<false>( variable.Fullname() )._( ".)" );
1863
1864 LI::logInternal( impl, Verbosity::Info, "PFX", msg );
1865 }
1866 }
1867}
1868
1869void LI::getAllVerbosities(LoxImpl* impl, Logger* logger, Domain& dom )
1870{
1871 // get verbosity for us
1872 LI::getVerbosityFromConfig( impl, logger, dom );
1873
1874 // loop over all sub domains (recursion)
1875 for ( Domain& subDomain : dom.SubDomains )
1876 LI::getAllVerbosities( impl, logger, subDomain );
1877}
1878
1879
1880Domain* LI::findDomain(LoxImpl* impl, Domain& rootDomain, NString domainPath )
1881{
1882 int maxSubstitutions= 10;
1883 NString128 substPath;
1884 for(;;)
1885 {
1886 // loop for creating domains, one by one
1887 Domain* dom= nullptr;
1888 for(;;)
1889 {
1890 bool wasCreated;
1891 dom= rootDomain.Find( domainPath, 1, &wasCreated );
1892 if ( wasCreated )
1893 {
1894 // get maximum domain path length (for nicer State output only...)
1895 if ( impl->maxDomainPathLength < dom->FullPath.Length() )
1896 impl->maxDomainPathLength= dom->FullPath.Length();
1897
1898 // log info on new domain
1899 Boxes& logables= LI::acquireInternalLogables(impl);
1900 logables.Add( "{!Q} registered.", dom->FullPath );
1901 LI::logInternal( impl, Verbosity::Info, "DMN", logables );
1902 }
1903
1904 // read domain from config
1905 if ( !dom->ConfigurationAlreadyRead )
1906 {
1907 dom->ConfigurationAlreadyRead= true;
1908
1910 Box replacements[2];
1911 for ( int i= 0; i < dom->CountLoggers(); ++i )
1912 {
1913 Logger* logger= dom->GetLogger(i);
1914 replacements[0]= LI::GetName( impl );
1915 replacements[1]= logger->GetName();
1916 if ( Priorities::NONE != ALOX.GetConfig().Load( impl->tempVar.Declare(Variables::VERBOSITY,
1917 replacements ) ) )
1918 LI::getVerbosityFromConfig( impl, logger, *dom );
1919 }
1921
1922 LI::getDomainPrefixFromConfig( impl, *dom );
1923 }
1924
1925 if ( wasCreated )
1926 {
1927 if ( dom->CountLoggers() == 0 )
1928 LI::logInternal( impl, Verbosity::Verbose, "DMN", " No loggers set, yet." );
1929 else
1930 {
1931 for ( int i= 0; i < dom->CountLoggers(); ++i )
1932 {
1933 NString256 msg; msg._(" \"")._( dom->GetLogger(i)->GetName() )._("\": ");
1934 msg.InsertChars( ' ', impl->maxLoggerNameLength + 6 - msg.Length() );
1935 msg._( dom->FullPath )._(" = " )
1936 ._(std::make_pair(dom->GetVerbosity(i), dom->GetPriority(i)));
1937 LI::logInternal( impl, Verbosity::Verbose, "DMN", msg );
1938 }
1939 }
1940 }
1941 else
1942 break;
1943 }
1944
1945 // apply domain substitutions
1946 if( !impl->domainSubstitutions.IsEmpty() )
1947 {
1948 substPath.Reset();
1949 while( maxSubstitutions-- > 0 )
1950 {
1951 // loop over rules
1952 bool substituted= false;
1953 for( auto& rule : impl->domainSubstitutions )
1954 {
1955 switch( rule.type )
1956 {
1957 case DomainSubstitutionRule::Type::StartsWith:
1958 if( substPath.IsEmpty() )
1959 {
1960 if ( dom->FullPath.StartsWith( rule.Search ) )
1961 {
1962 substPath._( rule.Replacement )._( dom->FullPath, rule.Search.Length() );
1963 substituted= true;
1964 continue;
1965 }
1966 }
1967 else
1968 {
1969 if ( substPath.StartsWith( rule.Search ) )
1970 {
1971 substPath.ReplaceSubstring<false>( rule.Replacement, 0, rule.Search.Length() );
1972 substituted= true;
1973 continue;
1974 }
1975 }
1976 break;
1977
1978 case DomainSubstitutionRule::Type::EndsWith:
1979 if( substPath.IsEmpty() )
1980 {
1981 if ( dom->FullPath.EndsWith( rule.Search ) )
1982 {
1983 substPath._( dom->FullPath, 0, dom->FullPath.Length() - rule.Search.Length() )._( rule.Replacement );
1984 substituted= true;
1985 continue;
1986 }
1987 }
1988 else
1989 {
1990 if ( substPath.EndsWith( rule.Search ) )
1991 {
1992 substPath.DeleteEnd( rule.Search.Length() )._( rule.Replacement );
1993 substituted= true;
1994 continue;
1995 }
1996 }
1997 break;
1998
1999
2000 case DomainSubstitutionRule::Type::Substring:
2001 {
2002 if( substPath.IsEmpty() )
2003 {
2004 integer idx= dom->FullPath.IndexOf( rule.Search );
2005 if ( idx >= 0 )
2006 {
2007 substPath._( dom->FullPath, 0, idx )._( rule.Replacement)._( dom->FullPath, idx + rule.Search.Length() );
2008 substituted= true;
2009 continue; //next rule
2010 }
2011 }
2012 else
2013 {
2014 integer idx= substPath.IndexOf( rule.Search, 0 );
2015 if ( idx >= 0 )
2016 {
2017 substPath.ReplaceSubstring<false>( rule.Replacement, idx, rule.Search.Length() );
2018 substituted= true;
2019 continue; //next rule
2020 }
2021 }
2022 }
2023 break;
2024
2025
2026 case DomainSubstitutionRule::Type::Exact:
2027 {
2028 if( substPath.IsEmpty() )
2029 {
2030 if ( dom->FullPath.Equals<false>( rule.Search ) )
2031 {
2032 substPath._( rule.Replacement);
2033 substituted= true;
2034 continue; //next rule
2035 }
2036 }
2037 else
2038 {
2039 if ( substPath.Equals<false>( rule.Search) )
2040 {
2041 substPath.Reset( rule.Replacement );
2042 substituted= true;
2043 continue; //next rule
2044 }
2045 }
2046 }
2047 break;
2048
2049 } // switch rule type
2050
2051 }//rules loop
2052
2053 // stop if non was found
2054 if( !substituted )
2055 break;
2056 }
2057
2058 // too many substitutions?
2059 if ( maxSubstitutions <= 0 && !impl->oneTimeWarningCircularDS )
2060 {
2061 impl->oneTimeWarningCircularDS= true;
2062 LI::logInternal( impl, Verbosity::Error, "DMN",
2063 "The Limit of 10 domain substitutions was reached. Circular substitution assumed!"
2064 " (This error is only reported once!)" );
2065 }
2066
2067 // anything substituted?
2068 if( substPath.Length() > 0 )
2069 {
2070 domainPath= substPath;
2071 continue;
2072 }
2073 }
2074
2075 return dom;
2076 }
2077}
2078
2079int LI::checkScopeInformation(LoxImpl* impl, Scope& scope, const NString& internalDomain )
2080{
2081 int pathLevel= 0;
2082 if ( scope > Scope::Path )
2083 {
2084 pathLevel= UnderlyingIntegral( scope - Scope::Path );
2085 scope= Scope::Path;
2086 }
2087
2088 if ( ( scope == Scope::Path && impl->scopeInfo.GetFullPath().IsEmpty() )
2089 || ( scope == Scope::Filename && impl->scopeInfo.GetFileName().IsEmpty() )
2090 || ( scope == Scope::Method && impl->scopeInfo.GetMethod() .IsEmpty() ) )
2091 {
2092 Boxes& logables= LI::acquireInternalLogables(impl);
2093 logables.Add( "Missing scope information. Cant use {}.", (scope + pathLevel) );
2094 LI::logInternal( impl, Verbosity::Error, internalDomain, logables );
2095 return -1;
2096 }
2097 return pathLevel;
2098}
2099
2100bool LI::isThreadRelatedScope(LoxImpl* impl, Scope scope )
2101{
2102 // check
2103 if ( scope == Scope::ThreadOuter
2104 || scope == Scope::ThreadInner )
2105 return true;
2106
2107 Boxes& logables= LI::acquireInternalLogables(impl);
2108 logables.Add( "Illegal parameter, only Scope::ThreadOuter and Scope::ThreadInner allowed."
2109 " Given: {}.", scope );
2110 LI::logInternal( impl, Verbosity::Error, "DMN", logables );
2111
2113 .DoReport( impl->scopeInfo.GetOrigFile(), impl->scopeInfo.GetLineNumber(), impl->scopeInfo.GetMethod(),
2115 "Illegal parameter, only Scope::ThreadOuter and Scope::ThreadInner allowed." );
2116 )
2117
2118 return false;
2119}
2120
2121void LI::log(LoxImpl* impl, Domain* dom, Verbosity verbosity, Boxes& logables, lang::Inclusion includePrefixes )
2122{
2123 ++dom->CntLogCalls;
2124 bool logablesCollected= false;
2125 PrefixLogable marker(nullptr);
2126 for ( int i= 0; i < dom->CountLoggers() ; ++i )
2127 if( dom->IsActive( i, verbosity ) )
2128 {
2129 // lazily collect objects once an active logger is found
2130 if ( !logablesCollected )
2131 {
2132 logablesCollected= true;
2133 impl->scopePrefixes.InitWalk( Scope::ThreadInner, &marker );
2134 const Box* next;
2135 int qtyUserLogables= static_cast<int>( logables.Size() );
2136 int qtyThreadInners= -1;
2137
2138 while( (next= impl->scopePrefixes.Walk() ) != nullptr )
2139 {
2140 if( next != &marker )
2141 {
2142 // this is false for internal domains (only domain specific logables are added there)
2143 if ( includePrefixes == lang::Inclusion::Include )
2144 {
2145 // after marker is read, logables need to be prepended. This is checked below
2146 // using "qtyThreadInners < 0"
2147 if ( next->IsType<Boxes*>() )
2148 {
2149 auto* boxes= next->Unbox<Boxes*>();
2150 for (int pfxI= static_cast<int>(boxes->Size()) - 1 ; pfxI >= 0 ; --pfxI )
2151 logables.emplace( logables.begin() + ( qtyThreadInners < 0 ? qtyUserLogables : 0 ),
2152 (*boxes)[static_cast<size_t>(pfxI)] );
2153 }
2154 else
2155 logables.emplace( logables.begin() + ( qtyThreadInners < 0 ? qtyUserLogables : 0 ), *next );
2156 }
2157 }
2158
2159 // was this the actual? then insert domain-associated logables now
2160 else
2161 {
2162 bool excludeOthers= false;
2163 qtyThreadInners= static_cast<int>( logables.Size() ) - qtyUserLogables;
2164 Domain* pflDom= dom;
2165 while ( pflDom != nullptr )
2166 {
2167 for( auto it= pflDom->PrefixLogables.rbegin() ; it != pflDom->PrefixLogables.rend() ; ++it )
2168 {
2169 // a list of logables? Copy them
2170 PrefixLogable& prefix= *it->first;
2171 if ( prefix.IsType<Boxes*>() )
2172 {
2173 auto* boxes= prefix.Unbox<Boxes*>();
2174 for (int pfxI= static_cast<int>(boxes->Size()) - 1 ; pfxI >= 0 ; --pfxI )
2175 logables.emplace( logables.begin(),
2176 (*boxes)[static_cast<size_t>(pfxI)] );
2177 }
2178 else
2179 logables.emplace( logables.begin(), prefix );
2180
2181
2182 if ( it->second == lang::Inclusion::Exclude )
2183 {
2184 excludeOthers= true;
2185 break;
2186 }
2187 }
2188
2189 pflDom= excludeOthers ? nullptr : pflDom->Parent;
2190 }
2191
2192 // found a stoppable one? remove those from thread inner and break
2193 if (excludeOthers)
2194 {
2195 for ( int ii= 0; ii < qtyThreadInners ; ++ii )
2196 logables.pop_back();
2197 break;
2198 }
2199 }
2200 }
2201 } // end of collection
2202
2203 Logger* logger= dom->GetLogger(i);
2204 ALIB_LOCK_WITH(*logger)
2205 ++logger->CntLogs;
2206 logger->Log( *dom, verbosity, logables, impl->scopeInfo );
2207 logger->TimeOfLastLog= Ticks::Now();
2208 }
2209}
2210
2211Boxes& LI::acquireInternalLogables(LoxImpl* impl)
2212{
2213 if( static_cast<integer>(impl->internalLogables.size()) == impl->internalLogRecursionCounter )
2214 {
2215 Boxes* newLogables= impl->monoAllocator->Emplace<Boxes>(impl->monoAllocator);
2216 impl->internalLogables.emplace_back( newLogables );
2217 }
2218
2219 return *impl->internalLogables[static_cast<size_t>(impl->internalLogRecursionCounter++)];
2220}
2221
2222void LI::logInternal(LoxImpl* impl, Verbosity verbosity, const NString& subDomain, Boxes& msg )
2223{
2224 ALIB_ASSERT_ERROR(ALOX.IsBootstrapped(), "ALOX", "ALox (ALib) was not properly bootstrapped." )
2225 LI::log( impl, LI::findDomain( impl, *impl->internalDomains, subDomain ), verbosity, msg, lang::Inclusion::Exclude );
2226
2227 impl->internalLogables[static_cast<size_t>(--impl->internalLogRecursionCounter)]->clear();
2228}
2229
2230void LI::logInternal(LoxImpl* impl, Verbosity verbosity, const NString& subDomain, const NString& msg )
2231{
2232 Boxes& logables= LI::acquireInternalLogables(impl);
2233 logables.Add( msg );
2234 LI::logInternal( impl, verbosity, subDomain, logables );
2235}
2236
2237#if ALIB_DEBUG_MONOMEM
2238MonoAllocator& LI::DbgGetMonoAllocator(LoxImpl* impl)
2239{
2240 return *impl->monoAllocator;
2241}
2242#endif
2243
2244
2245#if !defined(ALIB_DOX)
2246
2247namespace {
2248void getStateDomainRecursive( Domain& domain, integer maxDomainPathLength, NAString& buf );
2249void getStateDomainRecursive( Domain& domain, integer maxDomainPathLength, NAString& buf )
2250{
2251 integer reference= buf.Length();
2252 buf._(" "); domain.ToString( buf );
2253 integer idx= buf.IndexOf( '[', reference );
2254 buf.InsertChars( ' ', maxDomainPathLength + 5 - idx + reference, idx);
2255 buf.NewLine();
2256
2257 // loop over all sub domains (recursion)
2258 for ( Domain& subDomain : domain.SubDomains )
2259 getStateDomainRecursive( subDomain, maxDomainPathLength, buf );
2260}
2261
2262void getStateDomainsWithDiffVerb( Domain& dom, int loggerNo, std::vector<Domain*>& results );
2263void getStateDomainsWithDiffVerb( Domain& dom, int loggerNo, std::vector<Domain*>& results )
2264{
2265 if ( dom.Parent == nullptr
2266 || dom.Parent->GetVerbosity(loggerNo) != dom.GetVerbosity(loggerNo) )
2267 results.emplace_back( &dom );
2268
2269 for( auto& it : dom.SubDomains )
2270 getStateDomainsWithDiffVerb( it, loggerNo, results );
2271}
2272
2273void getStateCollectPrefixes( Domain& dom, integer indentSpaces, NAString& target );
2274void getStateCollectPrefixes( Domain& dom, integer indentSpaces, NAString& target )
2275{
2276 AString buffer;
2277 for ( auto& pfl : dom.PrefixLogables )
2278 {
2279 buffer.InsertChars( ' ', indentSpaces );
2280 buffer << '"';
2281 integer actLen= buffer.Length();
2282 buffer._( *static_cast<Box*>(pfl.first) );
2283 ESC::ReplaceToReadable( buffer, actLen );
2284 buffer << Format::Escape( lang::Switch::On, actLen );
2285 buffer << '"';
2286 if ( pfl.second == lang::Inclusion::Exclude )
2287 buffer._<false>( " (Excl.)" );
2288 buffer._<false>( Format::Tab( 25, -1 ) );
2289 buffer._<false>( "<domain> [" )._<false>( dom.FullPath )._<false>(']').NewLine();
2290 }
2291 target << buffer;
2292
2293 for( auto& subDom : dom.SubDomains )
2294 getStateCollectPrefixes( subDom, indentSpaces, target );
2295}
2296
2297} // anonymous namespace
2298
2299#endif // !defined(ALIB_DOX)
2300
2301
2302void LI::GetState( LoxImpl* impl, NAString& buf, StateInfo flags )
2303{
2304 ASSERT_ACQUIRED
2305
2307 impl->noKeyHashKey, buf );
2308
2309 if ( HasBits( flags, StateInfo::CompilationFlags ) )
2310 {
2311 buf._<false>( "ALib Version: " )._<false>( alib::Version)
2312 ._<false>(" (Rev. ") ._ ( alib::Revision)._(')').NewLine();
2313 buf._<false>( "ALib Compiler Symbols:" ).NewLine();
2314 {
2315 for( auto& p : alib::CompilationFlagMeanings )
2316 {
2317 buf << " " << NFormat::Field( p.Name, 41, lang::Alignment::Left ) << ':'
2318 << (alib::CompilationFlags.bits[p.Flag/8] & (1 << p.Flag % 8) ? " On" : " Off")
2319 << NewLine();
2320 }
2321
2322 }
2323
2324 buf.NewLine();
2325 }
2326
2327 // basic lox info
2328 if( alib::HasBits( flags, StateInfo::Basic ) )
2329 buf._<false>( "Name: \"" )._( impl->scopeInfo.GetLoxName() )._('\"').NewLine();
2330
2331 if( HasBits( flags, StateInfo::Version ) )
2332 {
2333 buf._<false>( "Version: " )._<false>( alib::Version)
2334 ._<false>(" (Rev. " )._( alib::Revision)._(')').NewLine();
2336 buf._<false>( "Thread Safeness: " )._<false>( impl->Lock.GetSafeness() ).NewLine(); )
2337 }
2338
2339 if( HasBits( flags, StateInfo::Basic ) )
2340 buf._<false>( "#Log Calls: " )._<false>( impl->CntLogCalls ).NewLine();
2341
2342 if( HasBits( flags, StateInfo::Basic )
2343 || HasBits( flags, StateInfo::Version ) )
2344 buf.NewLine();
2345
2346 // source path trim info
2347 if( HasBits( flags, StateInfo::SPTR ) )
2348 {
2349 buf._<false>( "Source Path Trimming Rules: " ).NewLine();
2350
2351 int cnt= 0;
2352 // do 2 times, 0== global list, 1 == local list
2353 for( int trimInfoNo= 0; trimInfoNo < 2 ; ++trimInfoNo )
2354 {
2355 // choose local or global list
2356 std::vector<ScopeInfo::SourcePathTrimRule>* trimInfoList=
2357 trimInfoNo == 0 ? &ScopeInfo::GlobalSPTRs
2358 : &impl->scopeInfo.LocalSPTRs;
2359
2360
2361 // loop over trimInfo
2362 for ( auto& ti : *trimInfoList )
2363 {
2364 ++cnt;
2365 buf._<false>( trimInfoNo == 0 ? " Global: "
2366 : " Local: " );
2367 buf._<false>( ti.IsPrefix ? "\"" : "\"*");
2368 buf._<false>( ti.Path )._<false>( "\", " );
2369 buf._<false>( ti.IncludeString );
2370 if ( ti.TrimOffset != 0 )
2371 buf._<false>( ti.Path )._<false>( "\", Offset: " )._<false>( ti.TrimOffset );
2372 buf._<false>( ", Priority: " )._( ti.Priority );
2373 buf.NewLine();
2374 }
2375 }
2376
2377
2378 if ( cnt == 0 )
2379 buf._<false>(" <no rules set>" ).NewLine();
2380 buf.NewLine();
2381 }
2382
2383 // domain substitutions
2384 if( HasBits( flags, StateInfo::DSR ) )
2385 {
2386 buf._<false>( "Domain Substitution Rules: " ).NewLine();
2387 if( !impl->domainSubstitutions.IsEmpty() )
2388 {
2389 // get size
2390 integer maxWidth= 0;
2391 for ( auto& it : impl->domainSubstitutions )
2392 if ( maxWidth < it.Search.Length() )
2393 maxWidth = it.Search.Length();
2394 maxWidth+= 2;
2395
2396 // write
2397 for ( auto& it : impl->domainSubstitutions )
2398 {
2399 buf._<false>( " " );
2400 if ( it.type == DomainSubstitutionRule::Type::EndsWith
2401 || it.type == DomainSubstitutionRule::Type::Substring )
2402 buf._<false>( '*' );
2403
2404 buf._<false>( it.Search );
2405 if ( it.type == DomainSubstitutionRule::Type::StartsWith
2406 || it.type == DomainSubstitutionRule::Type::Substring )
2407 buf._<false>( '*' );
2408
2409 buf._<false>( NFormat::Tab( maxWidth, -1, 0 ) )
2410 ._<false>( " -> " )
2411 ._<false>( it.Replacement );
2412 buf.NewLine();
2413 }
2414 }
2415 else
2416 buf._<false>(" <no rules set>" ).NewLine();
2417 buf.NewLine();
2418 }
2419
2420 // Log Once Counters
2421 if( HasBits( flags, StateInfo::Once ) )
2422 {
2423 buf._<false>( "Once() Counters: " ).NewLine();
2424 if ( scopeDump.writeStoreMap( &impl->scopeLogOnce ) == 0 )
2425 buf._<false>(" <no Once() counters set>" ).NewLine();
2426 buf.NewLine();
2427 }
2428
2429 // Log Data
2430 if( HasBits( flags, StateInfo::LogData ) )
2431 {
2432 buf._<false>( "Log Data: " ).NewLine();
2433 if ( scopeDump.writeStoreMap( &impl->scopeLogData ) == 0 )
2434 buf._<false>(" <no data objects stored>" ).NewLine();
2435 buf.NewLine();
2436 }
2437
2438 // Prefix Logables
2439 if( HasBits( flags, StateInfo::PrefixLogables ) )
2440 {
2441 buf._<false>( "Prefix Logables: " ).NewLine();
2442 integer oldLength= buf.Length();
2443 scopeDump.writeStore( &impl->scopePrefixes, 2 );
2444 getStateCollectPrefixes( *impl->domains, 2, buf );
2445 if ( oldLength == buf.Length() )
2446 buf._<false>(" <no prefix logables set>" ).NewLine();
2447 buf.NewLine();
2448 }
2449
2450 // thread mappings
2451 if( HasBits( flags, StateInfo::ThreadMappings ) )
2452 {
2453 #if ALIB_THREADS
2454 buf._<false>( "Named Threads: " ).NewLine();
2455 if ( impl->scopeInfo.threadDictionary.Size() == 0 )
2456 buf._<false>(" <no thread name mappings set>" ).NewLine();
2457 else
2458 for ( auto& pair : impl->scopeInfo.threadDictionary )
2459 {
2460 buf._<false>( " " ) << NFormat::Field( String32() << '(' << pair.first << "):", 7, lang::Alignment::Left )
2461 << '\"' << pair.second << '\"';
2462 buf.NewLine();
2463 }
2464 buf.NewLine();
2465 #endif
2466 }
2467
2468 // Scope Domains
2469 if( HasBits( flags, StateInfo::ScopeDomains ) )
2470 {
2471 buf._<false>( "Scope Domains: " ).NewLine();
2472 if ( scopeDump.writeStore( &impl->scopeDomains, 2 ) == 0 )
2473 buf._<false>(" <no scope domains set>" ).NewLine();
2474 buf.NewLine();
2475 }
2476
2477 // Loggers
2478 if( HasBits( flags, StateInfo::Loggers ) )
2479 {
2480 TickConverter dateTimeConverter;
2481 std::vector<Domain*> domainsWithDiffVerb;
2482 for (int treeNo= 0; treeNo < 2; ++treeNo )
2483 {
2484 int cnt= 0;
2485 Domain* domTree;
2486 if( treeNo==0 )
2487 {
2488 domTree= impl->domains;
2489 buf._<false>( "Loggers:" ).NewLine();
2490 }
2491 else
2492 {
2493 domTree= impl->internalDomains;
2494 buf._<false>( "Loggers on Internal Domains:" ).NewLine();
2495 }
2496
2497 for ( int loggerNo= 0; loggerNo< domTree->CountLoggers(); ++loggerNo )
2498 {
2499 ++cnt;
2500 String64 as64;
2502
2503 Logger* logger= domTree->GetLogger(loggerNo);
2504 buf._<false>( " " )._<false>( *logger ).NewLine();
2505 buf._<false>( " Lines logged: " )._<false>( logger->CntLogs ).NewLine();
2506
2507 ct.Set( dateTimeConverter.ToDateTime(logger->TimeOfCreation) );
2508 buf._<false>( " Creation time: " )._<false>( ct.Format( A_CHAR("yyyy-MM-dd HH:mm:ss"), as64.Reset()) ).NewLine();
2509
2510 ct.Set( dateTimeConverter.ToDateTime(logger->TimeOfLastLog) );
2511 buf._<false>( " Last log time: " )._<false>( ct.Format( A_CHAR("yyyy-MM-dd HH:mm:ss"), as64.Reset()) ).NewLine();
2512
2513 domainsWithDiffVerb.clear();
2514 getStateDomainsWithDiffVerb( *domTree, loggerNo, domainsWithDiffVerb);
2515 for ( Domain* dom : domainsWithDiffVerb )
2516 {
2517 buf._<false>(" ")
2518 ._( dom == *domainsWithDiffVerb.begin() ? "Verbosities: "
2519 : " " );
2520
2521 integer tabRef= buf.Length();
2522 buf << dom->FullPath << NFormat::Tab( impl->maxDomainPathLength +1, tabRef);
2523
2524 buf << "= " << std::make_pair(dom->GetVerbosity( loggerNo ), dom->GetPriority(loggerNo) )
2525 << NewLine();
2526 }
2527 }
2528 if ( cnt == 0 )
2529 buf._<false>(" <no loggers attached>" ).NewLine();
2530 buf.NewLine();
2531 }
2532 }
2533
2534 // Internal Domains
2535 if( HasBits( flags, StateInfo::InternalDomains ) )
2536 {
2537 buf._<false>( "Internal Domains:" ).NewLine();
2538 getStateDomainRecursive( *impl->internalDomains, impl->maxDomainPathLength, buf );
2539 buf.NewLine();
2540 }
2541
2542 // Domains
2543 if( HasBits( flags, StateInfo::Domains ) )
2544 {
2545 buf._<false>( "Domains:" ).NewLine();
2546 getStateDomainRecursive( *impl->domains , impl->maxDomainPathLength, buf );
2547 buf.NewLine();
2548 }
2549}
2550
2551} // namespace alib::lox[::detail]
2552
2553
2554// #################################################################################################
2555// Static methods of Lox
2556// #################################################################################################
2557TextLogger* Lox::CreateConsoleLogger(const NString& name)
2558{
2559 //--- check configuration setting "CONSOLE_TYPE" ---
2560
2561 Variable variable( Variables::CONSOLE_TYPE );
2562 ALOX.GetConfig().Load( variable );
2563 Substring val= variable.GetString();
2564 val.Trim();
2565 if( val.IsEmpty() ||
2566 val.Equals<false, lang::Case::Ignore>( A_CHAR("default") ) ) goto DEFAULT;
2567
2568 if( val.Equals<false, lang::Case::Ignore>( A_CHAR("plain") ) ) return new ConsoleLogger ( name );
2569 if( val.Equals<false, lang::Case::Ignore>( A_CHAR("Ansi") ) ) return new AnsiConsoleLogger( name );
2570
2571 if( val.Equals<false, lang::Case::Ignore>( A_CHAR("WINDOWS") ) )
2572 #if defined( _WIN32 )
2573 return new WindowsConsoleLogger( name );
2574 #else
2575 goto DEFAULT;
2576 #endif
2577
2578
2579 ALIB_WARNING( "ALOX", "Unrecognized value in config variable {!Q} = {!Q}.",
2580 variable.Fullname(), variable.GetString() )
2581
2582 DEFAULT:
2583
2584 #if defined( _WIN32 )
2585 // if there is no console window we do not do colors
2587 return new ConsoleLogger( name );
2588 else
2589 return new WindowsConsoleLogger( name );
2590 #else
2591 return new AnsiConsoleLogger( name );
2592 #endif
2593
2594}
2595
2596}} // namespace [alib::lox]
2597
2598#undef UNDEFINED_THREAD
2599#undef ASSERT_ACQUIRED
integer UnboxLength() const
Definition box.inl:979
bool IsType() const
bool IsNull() const
Definition box.inl:1312
decltype(std::declval< typename TFDecl::Signature >()(std::declval< Box & >(), std::declval< TArgs >()...)) Call(TArgs &&... args) const
Definition box.inl:1135
const TUnboxable Unbox() const
bool IsArray() const
Definition box.inl:711
integer Size() const
Definition boxes.inl:258
ALIB_API Priorities Load(Variable &variable)
ALIB_API Priorities Store(Variable &variable, const String &externalizedValue=nullptr)
void SetFmtHints(FormatHints hints)
Definition variable.hpp:538
integer Size() const
Definition variable.hpp:708
void ReplaceFormatAttrAlignment(const String &newValue)
Definition variable.hpp:694
const String & FormatAttrAlignment() const
Definition variable.hpp:549
void ReplaceComments(const String &newValue)
Definition variable.hpp:668
FormatHints FmtHints() const
Definition variable.hpp:527
ALIB_API const String & Fullname()
Definition variable.cpp:266
void SetPriority(Priorities priority)
Definition variable.hpp:628
ALIB_API void Add(const String &value)
Definition variable.cpp:223
ALIB_API Variable & Declare(const VariableDecl &declaration, const Box &replacements)
Definition variable.cpp:77
const String & GetString(int idx=0)
Definition variable.hpp:780
Variable & ClearValues(int startIdx=0)
Definition variable.hpp:721
Priorities Priority() const
Definition variable.hpp:617
bool IsBootstrapped()
Definition camp.hpp:190
config::Configuration & GetConfig()
Definition camp.hpp:231
static Report & GetDefault()
Definition report.hpp:157
ALIB_API void Set(const DateTime &timeStamp, lang::Timezone timezone=lang::Timezone::Local)
Definition calendar.cpp:65
ALIB_API AString & Format(Substring format, AString &target, lang::CurrentData targetData=lang::CurrentData::Keep) const
ALIB_API void Register(Lox *lox, lang::ContainerOp operation)
ALIB_API Lox * Get(const NString &name, lang::CreateIfNotExists create=lang::CreateIfNotExists::No)
static ALIB_API void ReplaceToReadable(AString &target, integer startIdx)
static ALIB_API void RemoveDebugLogger(Lox *lox)
Definition log.cpp:95
static ALIB_API detail::textlogger::TextLogger * DebugLogger
Definition log.inl:53
static ALIB_FORCE_INLINE Lox * Get()
Definition log.inl:74
detail::LoxImpl * impl
Definition lox.inl:93
static constexpr NString InternalDomains
Definition lox.inl:121
const NString & GetName()
Definition lox.inl:170
Verbosity GetVerbosity(int loggerNo)
Definition domain.inl:314
List< Domain > SubDomains
Definition domain.inl:128
int AddLogger(detail::Logger *logger)
Definition domain.inl:201
ALIB_API Verbosity SetVerbosity(int loggerNo, Verbosity verbosity, Priorities priority)
Definition domain.cpp:220
void ToString(NAString &target)
Definition domain.cpp:248
bool IsActive(int loggerNo, Verbosity statement)
Definition domain.inl:348
Priorities GetPriority(int loggerNo)
Definition domain.inl:324
void RemoveLogger(int loggerNo)
Definition domain.inl:221
List< std::pair< PrefixLogable *, lang::Inclusion > > PrefixLogables
Definition domain.inl:135
int GetLoggerNo(const NString &loggerName)
Definition domain.inl:275
detail::Logger * GetLogger(const NString &loggerName)
Definition domain.inl:250
ALIB_API Domain * Find(NSubstring domainPath, int maxCreate, bool *wasCreated)
Definition domain.cpp:97
virtual void AcknowledgeLox(LoxImpl *lox, lang::ContainerOp op)
Definition logger.hpp:173
const NString & GetName() const
Definition logger.hpp:184
time::Ticks TimeOfCreation
Definition logger.hpp:100
virtual void Log(Domain &dom, Verbosity verbosity, Boxes &logables, ScopeInfo &scope)=0
time::Ticks TimeOfLastLog
Definition logger.hpp:103
const NCString & GetOrigFile()
std::vector< SourcePathTrimRule > LocalSPTRs
ThreadDictionary threadDictionary
ALIB_API void SetSourcePathTrimRule(const NCString &path, lang::Inclusion includeString, int trimOffset, lang::Case sensitivity, const NString &trimReplacement, lang::Reach reach, Priorities priority)
std::vector< Scope, StdContMA< Scope > > scopes
ALIB_API void Set(const NCString &source, int lineNumber, const NCString &method, threads::Thread *thread)
std::pair< Iterator, bool > EmplaceOrAssign(const KeyType &key, TArgs &&... args)
ALIB_FORCE_INLINE T * Emplace(TArgs &&... args)
static ALIB_API MonoAllocator * Create(size_t initialChunkSize, unsigned int chunkGrowthInPercent=200)
ALIB_API void Reset(const Snapshot &snapshot=Snapshot())
ALIB_API TAString & Trim(const TCString< TChar > &trimChars=TT_StringConstants< TChar >::DefaultWhitespaces())
Definition astring.cpp:306
TAString & DeleteEnd(integer regionLength)
Definition astring.hpp:1589
TAString & ReplaceSubstring(const TString< TChar > &src, integer regionStart, integer regionLength)
Definition astring.hpp:1708
TAString & InsertChars(TChar c, integer qty)
Definition astring.hpp:1405
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
Definition astring.hpp:1056
void DbgDisableBufferReplacementWarning()
Definition astring.hpp:353
ALIB_API void SetBuffer(integer newCapacity)
Definition astring.cpp:107
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:889
constexpr bool IsEmpty() const
Definition string.hpp:414
constexpr bool IsNotEmpty() const
Definition string.hpp:420
constexpr integer Length() const
Definition string.hpp:357
TChar CharAtStart() const
Definition string.hpp:459
constexpr bool IsNotNull() const
Definition string.hpp:402
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.hpp:314
bool Equals(const TString< TChar > &rhs) const
Definition string.hpp:573
TChar CharAtEnd() const
Definition string.hpp:481
bool EndsWith(const TString &needle) const
Definition string.hpp:847
bool StartsWith(const TString &needle) const
Definition string.hpp:813
TSubstring & Trim(const TCString< TChar > &whiteSpaces=TT_StringConstants< TChar >::DefaultWhitespaces())
bool ConsumeString(const TString< TChar > &consumable)
integer ConsumePartOf(const TString< TChar > &consumable, int minChars=1)
bool ConsumeCharFromEnd(TChar consumable)
ALIB_API TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
Definition tokenizer.cpp:18
TSubstring< TChar > Actual
Definition tokenizer.hpp:84
Thread * GetOwner() const
ALIB_API void Acquire(const NCString &dbgFile, int dbgLine, const NCString &dbgFunc)
lang::Safeness GetSafeness() const
ALIB_API void Release()
defined(ALIB_DOX)
static Thread * GetCurrent()
Definition thread.hpp:288
virtual ThreadID GetId()
Definition thread.hpp:217
virtual const CString GetName()
Definition thread.hpp:226
static ALIB_API DateTime FromFileTime(const FILETIME &fileTime)
static DateTime FromEpochSeconds(time_t epochSeconds)
Definition datetime.hpp:72
Ticks ToTicks(DateTime dateTime)
DateTime ToDateTime(Ticks ticks)
void SetAs(const TDerived &other)
#define LOG_RELEASE
Definition macros.inl:39
#define LOG_ACQUIRE
Definition macros.inl:38
#define ALIB_WARNING(...)
Definition alib.hpp:981
#define A_CHAR(STR)
#define ALIB_IF_THREADS(...)
Definition alib.hpp:303
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:984
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
#define ALIB_ASSERT_WARNING(cond,...)
Definition alib.hpp:985
#define ALIB_DBG(...)
Definition alib.hpp:457
#define ALIB_LOCK_WITH(lock)
#define ALIB_REL_DBG(releaseCode,...)
Definition alib.hpp:459
#define ALIB_CHARACTERS_WIDE
Definition alib.hpp:351
#define ALIB_THREADS
Definition alib.hpp:180
bool ParseEnumOrTypeBool(strings::TSubstring< TChar > &input, TEnum &result, TEnum falseValue, TEnum trueValue)
@ Exclude
Chooses exclusion.
@ Include
Chooses inclusion.
@ Trim
Trim whitespaces away.
@ On
Switch it on, switched on, etc.
@ Global
Denotes global reach.
@ Left
Chooses left alignment.
@ Remove
Denotes removals.
@ Insert
Denotes insertions.
StateInfo
Definition lox.inl:40
static ALIB_FORCE_INLINE void Destruct(T *object)
strings::TString< TChar > AllocateCopy(const strings::TString< TChar > &src)
Definition string.hpp:2406
void DeleteString(const strings::TString< TChar > &string)
Definition string.hpp:2424
integer ThreadID
Definition loxpimpl.inl:34
Definition alib.cpp:57
constexpr CString NewLine()
Definition cstring.hpp:528
unsigned char Revision
Definition alib.cpp:66
lang::basecamp::BaseCamp BASECAMP
Definition basecamp.cpp:136
void DbgCheckSingleThreaded()
Definition alib.cpp:226
lox::ALox ALOX
LocalString< 32 > String32
Type alias name for TLocalString<character,32> .
ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE TCompilationFlags CompilationFlags
Definition alib.cpp:68
time::TickConverter TickConverter
Type alias in namespace alib.
LocalString< 256 > String256
Type alias name for TLocalString<character,256> .
constexpr NString NullNString()
Definition string.hpp:2510
int Version
Definition alib.cpp:65
characters::nchar nchar
Type alias in namespace alib.
boxing::Box Box
Type alias in namespace alib.
CompilationFlagMeaningsEntry CompilationFlagMeanings[30]
Definition alib.cpp:105
LocalString< 128 > String128
Type alias name for TLocalString<character,128> .
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
threads::ThreadID ThreadID
Type to store thread identifiers.
Definition thread.hpp:393
unsigned char bits[4]
The Flags.
Definition alib.hpp:1063
NString32 Replacement
The replacement.
Definition loxpimpl.cpp:78
DomainSubstitutionRule(const NString &s, const NString &r)
Definition loxpimpl.cpp:84
NString32 Search
The path to search.
Definition loxpimpl.cpp:77
static ALIB_API void logInternal(LoxImpl *impl, Verbosity verbosity, const NString &subDomain, Boxes &msg)
static ALIB_API void writeVerbositiesOnLoggerRemoval(LoxImpl *impl, Logger *logger)
Definition loxpimpl.cpp:608
static ALIB_API void SetSourcePathTrimRule(LoxImpl *impl, const NCString &path, lang::Inclusion includeString, int trimOffset, lang::Case sensitivity, const NString &trimReplacement, lang::Reach reach, Priorities priority)
Definition loxpimpl.cpp:555
static ALIB_API void SetStartTime(LoxImpl *impl, Ticks startTime, const NString &loggerName)
static ALIB_API void SetDomainSubstitutionRule(LoxImpl *impl, const NString &domainPath, const NString &replacement)
static ALIB_API void setDomain(LoxImpl *impl, const NString &scopeDomain, Scope scope, bool removeNTRSD, threads::Thread *thread)
Definition loxpimpl.cpp:988
static ALIB_API detail::Logger * GetLogger(LoxImpl *impl, const NString &loggerName)
Definition loxpimpl.cpp:579
static ALIB_API void RemoveThreadDomain(LoxImpl *impl, const NString &scopeDomain, Scope scope, threads::Thread *thread)
static ALIB_API detail::Domain * evaluateResultDomain(LoxImpl *impl, const NString &domainPath)
static ALIB_API int checkScopeInformation(LoxImpl *impl, Scope &scope, const NString &internalDomain)
static ALIB_API bool RemoveLogger(LoxImpl *impl, detail::Logger *logger)
Definition loxpimpl.cpp:782
static ALIB_API void init(LoxImpl *impl)
Definition loxpimpl.cpp:332
static ALIB_API void store(LoxImpl *impl, const Box &data, const NString &pKey, Scope scope)
static ALIB_API void Release(LoxImpl *impl)
Definition loxpimpl.cpp:322
static ALIB_API void getAllVerbosities(LoxImpl *impl, detail::Logger *logger, detail::Domain &dom)
static ALIB_API Boxes & acquireInternalLogables(LoxImpl *impl)
static ALIB_API bool isThreadRelatedScope(LoxImpl *impl, Scope scope)
static ALIB_API void Construct(Lox *lox, const NString &name, bool doRegister)
Definition loxpimpl.cpp:269
static ALIB_API void Reset(LoxImpl *impl, bool reInitialze=true)
Definition loxpimpl.cpp:379
static ALIB_API Boxes & GetLogableContainer(LoxImpl *impl)
static ALIB_API void setPrefix(LoxImpl *impl, const Box &prefix, Scope scope, threads::Thread *thread)
static ALIB_API void GetState(LoxImpl *impl, NAString &buf, StateInfo flags)
static ALIB_API void MapThreadName(LoxImpl *impl, const String &threadName, threads::ThreadID id)
static ALIB_API void State(LoxImpl *impl, const NString &domain, Verbosity verbosity, const String &headLine, StateInfo flags)
static ALIB_API void dumpStateOnLoggerRemoval(LoxImpl *impl)
Definition loxpimpl.cpp:707
static ALIB_API void Destruct(Lox *lox)
Definition loxpimpl.cpp:282
static ALIB_API Box retrieve(LoxImpl *impl, const NString &pKey, Scope scope)
static ALIB_API integer & GetLogCounter(LoxImpl *impl)
Definition loxpimpl.cpp:296
static ALIB_API const NString & GetName(LoxImpl *impl)
Definition loxpimpl.cpp:291
static ALIB_API void SetDomain(LoxImpl *impl, const NString &scopeDomain, Scope scope, threads::Thread *thread)
Definition loxpimpl.cpp:569
static ALIB_API void Entry(LoxImpl *impl, const NString &domain, Verbosity verbosity)
static ALIB_API void once(LoxImpl *impl, const NString &domain, Verbosity verbosity, const Box &logables, const String &pGroup, Scope scope, int quantity)
static ALIB_API void Acquire(LoxImpl *impl, const NCString &file, int line, const NCString &func)
Definition loxpimpl.cpp:309
static ALIB_API void SetPrefix(LoxImpl *impl, const Box &prefix, const NString &domain, lang::Inclusion otherPLs)
static ALIB_API void SetVerbosity(LoxImpl *impl, detail::Logger *logger, Verbosity verbosity, const NString &domain, Priorities priority)
Definition loxpimpl.cpp:849
static ALIB_API threads::ThreadLock & getLock(LoxImpl *impl)
Definition loxpimpl.cpp:302
MonoAllocator::Snapshot initialSnapshot
Definition loxpimpl.cpp:143
ScopeStore< std::map< NString, Box > *, false > scopeLogData
Definition loxpimpl.cpp:193
MonoAllocator * monoAllocator
Definition loxpimpl.cpp:140
List< DomainSubstitutionRule > domainSubstitutions
Definition loxpimpl.cpp:206
LoxImpl(MonoAllocator *ma, const NString &name)
Definition loxpimpl.cpp:220
ScopeStore< NString, true > scopeDomains
Definition loxpimpl.cpp:184
ScopeStore< PrefixLogable *, true > scopePrefixes
Definition loxpimpl.cpp:187
threads::ThreadLock Lock
Definition loxpimpl.cpp:147
const alib::NString noKeyHashKey
Definition loxpimpl.cpp:202
ScopeStore< std::map< NString, int > *, false > scopeLogOnce
Definition loxpimpl.cpp:190
std::vector< Boxes *, StdContMA< Boxes * > > internalLogables
Definition loxpimpl.cpp:165
std::vector< Boxes *, StdContMA< Boxes * > > logableContainers
Definition loxpimpl.cpp:162