ALib C++ Library
Library Version: 2510 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
scopeinfo.cpp
1// #################################################################################################
2// alib::lox::detail - ALox Logging Library
3//
4// Copyright 2013-2025 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
7#include "alib_precompile.hpp"
8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
10#endif
11#if ALIB_C20_MODULES
12 module;
13#endif
14// ====================================== Global Fragment ======================================
18#include <vector>
20
21// =========================================== Module ==========================================
22#if ALIB_C20_MODULES
23 module ALib.ALox.Impl;
24 import ALib.Lang;
26 import ALib.Strings;
28 import ALib.Boxing;
29 import ALib.EnumRecords;
31 import ALib.Variables;
32 import ALib.Camp;
33 import ALib.Camp.Base;
34#else
35# include "ALib.Lang.H"
37# include "ALib.Strings.H"
39# include "ALib.Boxing.H"
41# include "ALib.Variables.H"
42# include "ALib.System.H"
43# include "ALib.Camp.H"
44# include "ALib.Camp.Base.H"
45# include "ALib.Camp.H"
46# include "ALib.Camp.Base.H"
47# include "ALib.ALox.H"
48# include "ALib.ALox.Impl.H"
49#endif
50// ====================================== Implementation =======================================
51
52using namespace alib::system;
53
54namespace alib { namespace lox { namespace detail {
55
56// #################################################################################################
57// Static
58// #################################################################################################
59
60std::vector<ScopeInfo::SourcePathTrimRule> ScopeInfo::GlobalSPTRs;
62
63ScopeInfo::ScopeInfo( const NString& pName, MonoAllocator& allocator )
64#if !ALIB_SINGLE_THREADED
65: threadDictionary (allocator)
66,
67#else
68:
69#endif
70 parsedFileNameCache(allocator, 4, 6)
71, callStack (allocator)
72, loxName (allocator, pName)
73{
74 callStack.reserve(2);
75 characters::ToUpper( const_cast<char*>( loxName.Buffer() ), loxName.Length() );
76 ALIB_ASSERT_ERROR( !loxName.Equals<NC>( "GLOBAL" ), "ALOX",
77 "Name \"GLOBAL\" not allowed for Lox instances" )
78
79 IF_ALIB_THREADS( threadDictionary.EmplaceUnique(Thread::GetMain()->GetID(), "PROCESS" ); )
80
81 // read trim rules from config
82 // do 2 times, 0== local list, 1== global list
83 std::vector<SourcePathTrimRule>* trimInfoList;
84 for( int trimInfoNo= 0; trimInfoNo < 2 ; ++trimInfoNo )
85 { ALIB_LOCK_WITH(ALOX.GetConfig())
87
88 // check if done... or set list
89 if ( trimInfoNo == 0 )
90 {
91 trimInfoList= &LocalSPTRs;
92 ALIB_STRINGS_FROM_NARROW(loxName,sLoxName, 1024)
93 variable.Declare( Variables::SPTR_LOX, sLoxName );
94 }
95 else
96 {
98 continue;
100
101 trimInfoList= &GlobalSPTRs;
103 }
104
105 if( variable.IsDefined() )
106 {
107 Tokenizer tokOuter;
108 tokOuter.Set(variable, ';', true);
109 while(tokOuter.HasNext())
110 {
111 Tokenizer ruleTknzr( tokOuter.Next(), ',' );
112 trimInfoList->emplace_back();
113 SourcePathTrimRule& rule=trimInfoList->back();
114 rule.Priority= variable.GetPriority();
115
116 ruleTknzr.Next();
117 if( ( rule.IsPrefix= !ruleTknzr.Actual.StartsWith( A_CHAR("*") ) ) == false )
118 ruleTknzr.Actual.ConsumeChars(1);
119 rule.Path._( ruleTknzr.Actual );
120 if ( rule.Path.CharAtEnd() == '*' )
121 rule.Path.DeleteEnd( 1 );
122
123 if ( rule.Path.IsEmpty() )
124 {
125 trimInfoList->pop_back();
126 continue;
127 }
128
129 if( DIRECTORY_SEPARATOR == '/' )
130 rule.Path.SearchAndReplace( '\\', '/' );
131 else
132 rule.Path.SearchAndReplace( '/' , '\\' );
133
135 ruleTknzr.Next().ConsumeInt( rule.TrimOffset );
137
138 rule.TrimReplacement.Reset( ruleTknzr.Next() );
139 }
140 }
141 }
142}
143
145{
147 ALIB_ASSERT( callStackSize < 8, "ALOX")
148 if( callStack.size() == size_t(callStackSize) )
149 callStack.emplace_back();
150
151 FrameRecord& scope= callStack[size_t(callStackSize)];
152
153 scope.timeStamp = Ticks::Now();
154 scope.origLine = ci.Line;
155 scope.origMethod= ci.Func;
156 auto resultPair = parsedFileNameCache.Try( ci.File ); // search file in cache
157 if( resultPair.first == false )
158 resultPair.second.Construct(ci.File);
159 scope.Parsed = &*resultPair.second;
160
161 // we must not use ci.ThreadID, because this might be nulled with release logging
162 IF_ALIB_THREADS( threadNativeIDx= std::this_thread::get_id();
163 thread = nullptr;
164 threadName = nullptr;
165 )
166}
167
169 lang::Inclusion includeString,
170 int trimOffset,
171 lang::Case sensitivity,
172 const NString& trimReplacement,
173 lang::Reach reach,
174 Priority priority )
175{
176 // clear cache to have lazy variables reset with the next invocation
177 parsedFileNameCache.Clear();
178
179 // clear command
180 if ( trimOffset == 999999 )
181 {
182 LocalSPTRs.clear();
183 if ( reach == lang::Reach::Global )
184 GlobalSPTRs.clear();
186
187 // reset config read flag. This is done for unit testing. Not really useful/needed in real life.
189 return;
190 }
191
192 // choose local or global list
193 std::vector<SourcePathTrimRule>* trimInfoList=
195 : &LocalSPTRs;
196
197 // insert sorted by priority
198 auto it= trimInfoList->begin();
199 while( it != trimInfoList->end() && priority < it->Priority )
200 ++it;
201
202 it= trimInfoList->emplace(it);
203 SourcePathTrimRule& rule= *it;
204 rule.Priority= priority;
205
206 // if path starts with '*', it is not a prefix. We store without *
207 rule.Path._(path, (rule.IsPrefix= (path.CharAtStart() != '*') ) == true ? 0 : 1 );
208 if ( rule.Path.CharAtEnd() == '*' )
209 rule.Path.DeleteEnd( 1 );
210 if ( rule.Path.IsEmpty() )
211 {
212 trimInfoList->erase( it );
213 return;
214 }
215
216 if( DIRECTORY_SEPARATOR == '/' )
217 rule.Path.SearchAndReplace( '\\', '/' );
218 else
219 rule.Path.SearchAndReplace( '/' , '\\' );
220
221 rule.IncludeString= includeString;
222 rule.TrimOffset= trimOffset;
223 rule.Sensitivity= sensitivity;
224 rule.TrimReplacement.Reset( trimReplacement );
225 if( DIRECTORY_SEPARATOR == '/' )
226 rule.TrimReplacement.SearchAndReplace( '\\', '/' );
227 else
228 rule.TrimReplacement.SearchAndReplace( '/' , '\\' );
229}
230
231
233{
234 bool trimmed= false;
235
236 ParsedFileName* actual= callStack[size_t(callStackSize)].Parsed;
237 integer idx= getPathLength();
238 if( idx < 0 )
239 {
240 actual->trimmedPath= "";
241 return;
242 }
243 actual->trimmedPath= NString( actual->origFile.Buffer(), idx );
244
245
246 // do 2 times, 0== local list, 1== global list
247 for( int trimInfoNo= 0; trimInfoNo < 2 ; ++trimInfoNo )
248 {
249 // choose local or global list
250 std::vector<SourcePathTrimRule>* trimInfoList=
251 trimInfoNo == 0 ? &LocalSPTRs
252 : &GlobalSPTRs;
253
254 // loop over trimInfo
255 for ( auto& ti : *trimInfoList )
256 {
257 if( ti.IsPrefix )
258 idx= ( ti.Sensitivity == lang::Case::Sensitive ? actual->trimmedPath.StartsWith<CHK,lang::Case::Sensitive>( ti.Path )
259 : actual->trimmedPath.StartsWith<CHK,lang::Case::Ignore >( ti.Path )
260 )
261
262 ? 0 : -1;
263 else
264 idx= ti.Sensitivity == lang::Case::Sensitive ? actual->trimmedPath.IndexOf<CHK, lang::Case::Sensitive>( ti.Path )
265 : actual->trimmedPath.IndexOf<CHK, lang::Case::Ignore >( ti.Path );
266 if ( idx >= 0 )
267 {
268 integer startIdx= idx + ( ti.IncludeString == lang::Inclusion::Include ? ti.Path.Length() : 0 ) + ti.TrimOffset;
269 actual->trimmedPath= actual->trimmedPath.Substring( startIdx, actual->trimmedPath.Length() - startIdx );
270 actual->trimmedPathPrefix= ti.TrimReplacement;
271
272 trimmed= true;
273 break;
274 }
275 }
276
277 if (trimmed)
278 break;
279 }
280
281 // if nothing was found and the flag is still set, try once to auto-detect rule
282 // from the 'difference' of source path and current working directory
283 if( !trimmed && AutoDetectTrimableSourcePath )
284 {
285 AutoDetectTrimableSourcePath= false; // do this only once
286
287 // get system execution path and compare to file path
288 Path currentDir(SystemFolders::Current);
289
290 // Get the prefix that is the same in both paths
291 integer i= 0;
292 integer maxIdx= currentDir.Length();
293 if ( maxIdx > actual->trimmedPath.Length() )
294 maxIdx= actual->trimmedPath.Length();
295
296 while ( i < maxIdx && characters::ToUpper( currentDir[i] )
297 == characters::ToUpper( character(actual->trimmedPath[i]) ) )
298 ++i;
299
300 if ( i > 1 )
301 {
302 currentDir.ShortenTo( i );
303 NCString origFile= actual->origFile;
304 ALIB_PATH_TO_NARROW(currentDir,nCurrentDir,1024)
306 lang::Reach::Local, Priority::AutoDetected );
307 actual->origFile= origFile;
308 trimPath(); // one recursive call
309 }
310 }
311}
312
313
314}}} // namespace [alib::lox::detail]
315
316#if defined(_MSC_VER)
317 #pragma warning( pop )
318#endif
319
static ALIB_DLL std::vector< SourcePathTrimRule > GlobalSPTRs
List of trim definitions for portions of source paths to be ignored.
Definition scopeinfo.inl:60
static ALIB_DLL bool GlobalSPTRsReadFromConfig
Flag to determine if global rules have been read from config already.
Definition scopeinfo.inl:67
ALIB_DLL ScopeInfo(const NString &name, MonoAllocator &allocator)
Definition scopeinfo.cpp:63
ALIB_DLL void SetSourcePathTrimRule(const NCString &path, lang::Inclusion includeString, int trimOffset, lang::Case sensitivity, const NString &trimReplacement, lang::Reach reach, Priority priority)
NString loxName
The name of the Lox we are attached to.
StdVectorMono< FrameRecord > callStack
A stack of scopes (allows recursive calls/nested logging).
ThreadDictionary threadDictionary
Definition scopeinfo.inl:88
String threadName
The name of the thread that executed the log.
Definition scopeinfo.inl:84
LRUCacheTable< MonoAllocator, ValueDescriptorPFN, std::hash< NString > > parsedFileNameCache
Least recently used cache of parsed file name.
Thread * thread
The thread passed with Set.
Definition scopeinfo.inl:81
int callStackSize
The current depth of recursive invocations.
ALIB_DLL void Set(const lang::CallerInfo &ci)
std::vector< SourcePathTrimRule > LocalSPTRs
List of trim definitions for portions of source paths to be ignored.
Definition scopeinfo.inl:63
std::thread::id threadNativeIDx
The C++ native ID.
Definition scopeinfo.inl:78
TAString & DeleteEnd(integer regionLength)
ALIB_DLL integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0, integer endIdx=strings::MAX_LEN)
TAString & ShortenTo(integer newLength)
Definition tastring.inl:816
TAString & _(const TAppendable &src)
constexpr integer Length() const
Definition string.inl:318
constexpr bool IsEmpty() const
Definition string.inl:367
TChar CharAtStart() const
Definition string.inl:440
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.inl:844
constexpr const TChar * Buffer() const
Definition string.inl:313
TChar CharAtEnd() const
Definition string.inl:460
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.inl:386
bool StartsWith(const TString &needle) const
Definition string.inl:772
bool ConsumeInt(std::integral auto &result, TNumberFormat< TChar > *numberFormat=nullptr)
integer ConsumeChars(integer regionLength, TSubstring *target=nullptr)
ALIB_DLL TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
Definition tokenizer.cpp:26
void Set(const TString< TChar > &src, TChar delimiter, bool skipEmptyTokens=false)
TSubstring< TChar > Actual
Definition tokenizer.inl:66
static ALIB_DLL Thread * GetMain()
Definition thread.cpp:328
ALIB_DLL Variable & Declare(const String &name, const String &typeName, const String &defaultValue=NULL_STRING)
Definition variable.cpp:201
#define IF_ALIB_THREADS(...)
Definition alib.inl:401
#define A_CHAR(STR)
#define ALIB_ASSERT(cond, domain)
Definition alib.inl:1048
#define ALIB_PATH_TO_NARROW( src, dest, bufSize)
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1049
#define ALIB_LOCK_WITH(lock)
Definition alib.inl:1322
#define ALIB_STRINGS_FROM_NARROW( src, dest, bufSize)
TChar ToUpper(TChar c)
bool ParseEnumOrTypeBool(strings::TSubstring< TChar > &input, TEnum &result, TEnum falseValue, TEnum trueValue)
Reach
Denotes the reach of something.
@ Global
Denotes global reach.
@ Local
Denotes local reach.
Case
Denotes upper and lower case character treatment.
Inclusion
Denotes how members of a set something should be taken into account.
@ Exclude
Chooses exclusion.
@ Include
Chooses inclusion.
@ SPTR_GLOBAL
Denotes configuration variable ALOX/GLOBAL_SOURCE_PATH_TRIM_RULES.
Definition aloxcamp.inl:31
@ SPTR_LOX
Denotes configuration variable ALOX/LOXNAME/SOURCE_PATH_TRIM_RULES used by class Lox.
Definition aloxcamp.inl:34
constexpr PathCharType DIRECTORY_SEPARATOR
The standard path separator character. Defaults to '\' on Windows OS, '/' else.
Definition path.inl:63
variables::Variable CampVariable(camp::Camp &camp)
Definition camp.inl:349
constexpr NString NULL_NSTRING
A nulled string of the narrow character type.
Definition string.inl:2472
strings::util::TTokenizer< character > Tokenizer
Type alias in namespace alib.
variables::Variable Variable
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2390
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
strings::TCString< nchar > NCString
Type alias in namespace alib.
Definition cstring.inl:512
alib::variables::Priority Priority
Type alias in namespace alib.
lox::ALoxCamp ALOX
The singleton instance of ALib Camp class ALoxCamp.
Definition aloxcamp.cpp:53
characters::character character
Type alias in namespace alib.
See sibling type NC.
Definition chk_nc.inl:33
const char * File
The name of the source file as given by compiler.
int Line
The line number within File.
Ticks timeStamp
Time of the call that created this record.
NCString origMethod
Function/method name (given by the C++ preprocessor)
ParsedFileName * Parsed
The entry from the parsedFileNameCache.
int origLine
Line number within the source file (given by the C++ preprocessor)
Information of a single source file. Stored in field parsedFileNameCache.
Definition scopeinfo.inl:93
NCString origFile
Path and name of source file (given by the C++ preprocessor).
Definition scopeinfo.inl:95
NString trimmedPath
Trimmed path of source file (evaluated).
int TrimOffset
Additional offset of the trim position.
Definition scopeinfo.inl:51
lang::Inclusion IncludeString
Denotes if Path itself should be included when trimmed.
Definition scopeinfo.inl:52
variables::Priority Priority
The priority of the rule. Depends on origin: source code, config...)
Definition scopeinfo.inl:54
bool IsPrefix
true if path was not starting with '*', when provided.
Definition scopeinfo.inl:55
lang::Case Sensitivity
The sensitivity of the comparison when trimming.
Definition scopeinfo.inl:53
NAString TrimReplacement
Optional replacement string for trimmed paths.
Definition scopeinfo.inl:50