ALib C++ Framework
by
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
scopeinfo.cpp
1//##################################################################################################
2// ALib C++ Framework
3//
4// Copyright 2013-2025 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6//##################################################################################################
7#include "alib_precompile.hpp"
8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Configuration MACRO ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
10#endif
11#if ALIB_C20_MODULES
12 module;
13#endif
14//========================================= Global Fragment ========================================
18#include <vector>
20
21//============================================== Module ============================================
22#if ALIB_C20_MODULES
23 module ALib.ALox.Impl;
24 import ALib.Lang;
25 import ALib.Characters.Functions;
26 import ALib.Strings;
27 import ALib.Strings.Tokenizer;
28 import ALib.Boxing;
29 import ALib.EnumRecords;
30 import ALib.EnumRecords.Bootstrap;
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 trimInfoList= &LocalSPTRs;
91 ALIB_STRINGS_FROM_NARROW(loxName,sLoxName, 1024)
92 variable.Declare( Variables::SPTR_LOX, sLoxName );
93 } else {
95 continue;
97
98 trimInfoList= &GlobalSPTRs;
100 }
101
102 if( variable.IsDefined() ) {
103 Tokenizer tokOuter;
104 tokOuter.Set(variable, ';', true);
105 while(tokOuter.HasNext()) {
106 Tokenizer ruleTknzr( tokOuter.Next(), ',' );
107 trimInfoList->emplace_back();
108 SourcePathTrimRule& rule=trimInfoList->back();
109 rule.Priority= variable.GetPriority();
110
111 ruleTknzr.Next();
112 if( ( rule.IsPrefix= !ruleTknzr.Actual.StartsWith( A_CHAR("*") ) ) == false )
113 ruleTknzr.Actual.ConsumeChars(1);
114 rule.Path._( ruleTknzr.Actual );
115 if ( rule.Path.CharAtEnd() == '*' )
116 rule.Path.DeleteEnd( 1 );
117
118 if ( rule.Path.IsEmpty() ) {
119 trimInfoList->pop_back();
120 continue;
121 }
122
123 if( DIRECTORY_SEPARATOR == '/' )
124 rule.Path.SearchAndReplace( '\\', '/' );
125 else
126 rule.Path.SearchAndReplace( '/' , '\\' );
127
129 ruleTknzr.Next().ConsumeInt( rule.TrimOffset );
131
132 rule.TrimReplacement.Reset( ruleTknzr.Next() );
133} } } }
134
137 ALIB_ASSERT( callStackSize < 8, "ALOX")
138 if( callStack.size() == size_t(callStackSize) )
139 callStack.emplace_back();
140
141 FrameRecord& scope= callStack[size_t(callStackSize)];
142
143 scope.timeStamp = Ticks::Now();
144 scope.origLine = ci.Line;
145 scope.origMethod= ci.Func;
146 auto resultPair = parsedFileNameCache.Try( ci.File ); // search file in cache
147 if( resultPair.first == false )
148 resultPair.second.Construct(ci.File);
149 scope.Parsed = &*resultPair.second;
150
151 // we must not use ci.ThreadID, because this might be nulled with release logging
152 IF_ALIB_THREADS( threadNativeIDx= std::this_thread::get_id();
153 thread = nullptr;
154 threadName = nullptr;
155 )
156}
157
159 lang::Inclusion includeString,
160 int trimOffset,
161 lang::Case sensitivity,
162 const NString& trimReplacement,
163 lang::Reach reach,
164 Priority priority ) {
165 // clear cache to have lazy variables reset with the next invocation
166 parsedFileNameCache.Clear();
167
168 // clear command
169 if ( trimOffset == 999999 ) {
170 LocalSPTRs.clear();
171 if ( reach == lang::Reach::Global )
172 GlobalSPTRs.clear();
174
175 // reset config read flag. This is done for unit testing. Not really useful/needed in real life.
177 return;
178 }
179
180 // choose local or global list
181 std::vector<SourcePathTrimRule>* trimInfoList=
183 : &LocalSPTRs;
184
185 // insert sorted by priority
186 auto it= trimInfoList->begin();
187 while( it != trimInfoList->end() && priority < it->Priority )
188 ++it;
189
190 it= trimInfoList->emplace(it);
191 SourcePathTrimRule& rule= *it;
192 rule.Priority= priority;
193
194 // if path starts with '*', it is not a prefix. We store without *
195 rule.Path._(path, (rule.IsPrefix= (path.CharAtStart() != '*') ) == true ? 0 : 1 );
196 if ( rule.Path.CharAtEnd() == '*' )
197 rule.Path.DeleteEnd( 1 );
198 if ( rule.Path.IsEmpty() ) {
199 trimInfoList->erase( it );
200 return;
201 }
202
203 if( DIRECTORY_SEPARATOR == '/' )
204 rule.Path.SearchAndReplace( '\\', '/' );
205 else
206 rule.Path.SearchAndReplace( '/' , '\\' );
207
208 rule.IncludeString= includeString;
209 rule.TrimOffset= trimOffset;
210 rule.Sensitivity= sensitivity;
211 rule.TrimReplacement.Reset( trimReplacement );
212 if( DIRECTORY_SEPARATOR == '/' )
213 rule.TrimReplacement.SearchAndReplace( '\\', '/' );
214 else
215 rule.TrimReplacement.SearchAndReplace( '/' , '\\' );
216}
217
218
220 bool trimmed= false;
221
222 ParsedFileName* actual= callStack[size_t(callStackSize)].Parsed;
223 integer idx= getPathLength();
224 if( idx < 0 ) {
225 actual->trimmedPath= "";
226 return;
227 }
228 actual->trimmedPath= NString( actual->origFile.Buffer(), idx );
229
230
231 // do 2 times, 0== local list, 1== global list
232 for( int trimInfoNo= 0; trimInfoNo < 2 ; ++trimInfoNo ) {
233 // choose local or global list
234 std::vector<SourcePathTrimRule>* trimInfoList=
235 trimInfoNo == 0 ? &LocalSPTRs
236 : &GlobalSPTRs;
237
238 // loop over trimInfo
239 for ( auto& ti : *trimInfoList ) {
240 if( ti.IsPrefix )
241 idx= ( ti.Sensitivity == lang::Case::Sensitive ? actual->trimmedPath.StartsWith<CHK,lang::Case::Sensitive>( ti.Path )
242 : actual->trimmedPath.StartsWith<CHK,lang::Case::Ignore >( ti.Path )
243 )
244
245 ? 0 : -1;
246 else
247 idx= ti.Sensitivity == lang::Case::Sensitive ? actual->trimmedPath.IndexOf<CHK, lang::Case::Sensitive>( ti.Path )
248 : actual->trimmedPath.IndexOf<CHK, lang::Case::Ignore >( ti.Path );
249 if ( idx >= 0 ) {
250 integer startIdx= idx + ( ti.IncludeString == lang::Inclusion::Include ? ti.Path.Length() : 0 ) + ti.TrimOffset;
251 actual->trimmedPath= actual->trimmedPath.Substring( startIdx, actual->trimmedPath.Length() - startIdx );
252 actual->trimmedPathPrefix= ti.TrimReplacement;
253
254 trimmed= true;
255 break;
256 } }
257
258 if (trimmed)
259 break;
260 }
261
262 // if nothing was found and the flag is still set, try once to auto-detect rule
263 // from the 'difference' of source path and current working directory
264 if( !trimmed && AutoDetectTrimableSourcePath ) {
265 AutoDetectTrimableSourcePath= false; // do this only once
266
267 // get system execution path and compare to file path
268 Path currentDir(SystemFolders::Current);
269
270 // Get the prefix that is the same in both paths
271 integer i= 0;
272 integer maxIdx= currentDir.Length();
273 if ( maxIdx > actual->trimmedPath.Length() )
274 maxIdx= actual->trimmedPath.Length();
275
276 while ( i < maxIdx && characters::ToUpper( currentDir[i] )
277 == characters::ToUpper( character(actual->trimmedPath[i]) ) )
278 ++i;
279
280 if ( i > 1 ) {
281 currentDir.ShortenTo( i );
282 NCString origFile= actual->origFile;
283 ALIB_PATH_TO_NARROW(currentDir,nCurrentDir,1024)
285 lang::Reach::Local, Priority::AutoDetected );
286 actual->origFile= origFile;
287 trimPath(); // one recursive call
288} } }
289
290
291}}} // namespace [alib::lox::detail]
292
293#if defined(_MSC_VER)
294 #pragma warning( pop )
295#endif
#define IF_ALIB_THREADS(...)
Definition alib.inl:466
#define A_CHAR(STR)
Definition alib.inl:1325
#define ALIB_ASSERT(cond, domain)
Definition alib.inl:1143
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1144
#define ALIB_LOCK_WITH(lock)
Definition alib.inl:1413
static std::vector< SourcePathTrimRule > GlobalSPTRs
List of trim definitions for portions of source paths to be ignored.
Definition scopeinfo.inl:60
StdVectorMA< FrameRecord > callStack
A stack of scopes (allows recursive calls/nested logging).
static bool GlobalSPTRsReadFromConfig
Flag to determine if global rules have been read from config already.
Definition scopeinfo.inl:67
ScopeInfo(const NString &name, MonoAllocator &allocator)
Definition scopeinfo.cpp:63
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.
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.
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
integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0, integer endIdx=strings::MAX_LEN)
TAString & DeleteEnd(integer regionLength)
TAString & ShortenTo(integer newLength)
Definition tastring.inl:747
TAString & _(const TAppendable &src)
constexpr integer Length() const
Definition string.inl:304
constexpr bool IsEmpty() const
Definition string.inl:353
TChar CharAtStart() const
Definition string.inl:421
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.inl:803
constexpr const TChar * Buffer() const
Definition string.inl:299
TChar CharAtEnd() const
Definition string.inl:440
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.inl:372
bool StartsWith(const TString &needle) const
Definition string.inl:739
bool ConsumeInt(std::integral auto &result, TNumberFormat< TChar > *numberFormat=nullptr)
integer ConsumeChars(integer regionLength, TSubstring *target=nullptr)
void Set(const TString< TChar > &src, TChar delimiter, bool skipEmptyTokens=false)
TSubstring< TChar > Actual
Definition tokenizer.inl:67
TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
Definition tokenizer.cpp:26
static Thread * GetMain()
Definition thread.cpp:313
Variable & Declare(const String &name, const String &typeName, const String &defaultValue=NULL_STRING)
Definition variable.cpp:186
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 #"alxcvALOX_GLOBAL_SOURCE_PATH_TRIM_RULES".
Definition aloxcamp.inl:31
@ SPTR_LOX
Denotes configuration variable #"alxcvALOX_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:285
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2181
constexpr NString NULL_NSTRING
A nulled string of the narrow character type.
Definition string.inl:2263
strings::TCString< nchar > NCString
Type alias in namespace alib.
Definition cstring.inl:408
alib::variables::Priority Priority
Type alias in namespace alib.
variables::Variable Variable
Type alias in namespace alib.
strings::util::TTokenizer< character > Tokenizer
Type alias in namespace alib.
lox::ALoxCamp ALOX
The singleton instance of ALib Camp class #"ALoxCamp".
Definition aloxcamp.cpp:54
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
system::Path Path
Type alias in namespace alib.
Definition path.inl:375
characters::character character
Type alias in namespace alib.
#define ALIB_STRINGS_FROM_NARROW( src, dest, bufSize)
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
#define ALIB_PATH_TO_NARROW( src, dest, bufSize)