ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
scopeinfo.cpp
1//##################################################################################################
2// ALib C++ 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;
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
static ALIB_DLL 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 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.
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:787
TAString & _(const TAppendable &src)
constexpr integer Length() const
Definition string.inl:316
constexpr bool IsEmpty() const
Definition string.inl:365
TChar CharAtStart() const
Definition string.inl:433
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.inl:815
constexpr const TChar * Buffer() const
Definition string.inl:311
TChar CharAtEnd() const
Definition string.inl:452
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.inl:384
bool StartsWith(const TString &needle) const
Definition string.inl:751
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:67
static ALIB_DLL Thread * GetMain()
Definition thread.cpp:313
ALIB_DLL Variable & Declare(const String &name, const String &typeName, const String &defaultValue=NULL_STRING)
Definition variable.cpp:187
#define IF_ALIB_THREADS(...)
Definition alib.inl:401
#define A_CHAR(STR)
#define ALIB_ASSERT(cond, domain)
Definition alib.inl:1065
#define ALIB_PATH_TO_NARROW( src, dest, bufSize)
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
#define ALIB_LOCK_WITH(lock)
Definition alib.inl:1339
#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:344
constexpr NString NULL_NSTRING
A nulled string of the narrow character type.
Definition string.inl:2280
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:2198
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
strings::TCString< nchar > NCString
Type alias in namespace alib.
Definition cstring.inl:484
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