ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
scopeinfo.cpp
1// #################################################################################################
2// alib::lox::detail - 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_ALOX)
11# include "alib/alox/alox.hpp"
12# endif
13
14# if !defined(HPP_ALIB_ALOXMODULE)
16# endif
17
18# if !defined(HPP_ALOX_DETAIL_SCOPEINFO)
19# define HPP_ALIB_LOX_PROPPERINCLUDE
21# undef HPP_ALIB_LOX_PROPPERINCLUDE
22# endif
23
24# if !defined(HPP_ALIB_LANG_COMMONENUMS)
26# endif
27
28# if !defined(HPP_ALIB_ENUMS_SERIALIZATION)
30# endif
31# if !defined(HPP_ALIB_STRINGS_UTIL_TOKENIZER)
33# endif
34#endif // !defined(ALIB_DOX)
35
36
37// conditional expression is constant (which is a great thing for the compiler by the way ;-)
38#if defined(_MSC_VER)
39 #pragma warning( push )
40 #pragma warning( disable : 4127 )
41#endif
42
43namespace alib { namespace lox { namespace detail {
44
45// #################################################################################################
46// Static
47// #################################################################################################
48
49std::vector<ScopeInfo::SourcePathTrimRule> ScopeInfo::GlobalSPTRs;
51
53
54ScopeInfo::ScopeInfo( const NString& pName, MonoAllocator* allocator, Variable& tempVar )
55#if ALIB_THREADS
56: threadDictionary( allocator )
57,
58#else
59:
60#endif
61 scopes ( *allocator )
62{
63 loxName= allocator->EmplaceString( pName );
64 characters::CharArray<nchar>::ToUpper( const_cast<char*>( loxName.Buffer() ), loxName.Length() );
65 ALIB_ASSERT_ERROR( !loxName.Equals<false>( "GLOBAL" ), "ALOX", "Name \"GLOBAL\" not allowed for Lox instances" )
66 cache= allocator->EmplaceArray<SourceFile>( cacheSize= DefaultCacheSize );
67
68 lastSourceFile= &cache[0];
69
70 ALIB_IF_THREADS( threadDictionary.EmplaceUnique(Thread::GetMain()->GetId(), "PROCESS" ); )
71
72 // read trim rules from config
73 // do 2 times, 0== local list, 1== global list
74 std::vector<SourcePathTrimRule>* trimInfoList;
75 for( int trimInfoNo= 0; trimInfoNo < 2 ; ++trimInfoNo )
76 {
77 // check if done... or set list
78 if ( trimInfoNo == 0 )
79 {
80 trimInfoList= &LocalSPTRs;
81 ALIB_STRINGS_FROM_NARROW(loxName,sLoxName, 1024)
82 tempVar.Declare( Variables::SPTR_LOX, sLoxName );
83 }
84 else
85 {
86 if ( GlobalSPTRsReadFromConfig )
87 continue;
88 GlobalSPTRsReadFromConfig= true;
89
90 trimInfoList= &GlobalSPTRs;
92 }
93 ALOX.GetConfig().Load( tempVar );
94
95 if( tempVar.Priority() != Priorities::NONE )
96 {
97 for( int ruleNo= 0; ruleNo < tempVar.Size(); ++ruleNo )
98 {
99 Tokenizer ruleTknzr( tempVar.GetString( ruleNo ), ',' );
100 trimInfoList->emplace_back();
101 SourcePathTrimRule& rule=trimInfoList->back();
102 rule.Priority= tempVar.Priority();
103
104 ruleTknzr.Next();
105 if( ( rule.IsPrefix= !ruleTknzr.Actual.StartsWith( A_CHAR("*") ) ) == false )
106 ruleTknzr.Actual.ConsumeChars(1);
107 rule.Path._( ruleTknzr.Actual );
108 if ( rule.Path.CharAtEnd() == '*' )
109 rule.Path.DeleteEnd( 1 );
110
111 if ( rule.Path.IsEmpty() )
112 {
113 trimInfoList->pop_back();
114 continue;
115 }
116
117 if( DirectorySeparator == '/' )
118 rule.Path.SearchAndReplace( '\\', '/' );
119 else
120 rule.Path.SearchAndReplace( '/' , '\\' );
121
123 ruleTknzr.Next().ConsumeInt( rule.TrimOffset );
125
126 rule.TrimReplacement.Reset( ruleTknzr.Next() );
127 }
128 }
129 }
130}
131
132void ScopeInfo::Set ( const NCString& sourceFileName, int lineNumber, const NCString& methodName
133 ALIB_IF_THREADS(, Thread* pThread ) )
134{
137 if( scopes.size() == static_cast<size_t>(actScopeDepth) )
138 scopes.emplace_back();
139 Scope& s= scopes[static_cast<size_t>(actScopeDepth)];
140
141
143 s.origLine= lineNumber;
144 s.origMethod= methodName;
146
148 this->thread= pThread;
149 threadName= nullptr; )
150
151 // if different file than before, search file in cache
152 if ( s.sourceFile->origFile.Buffer() != sourceFileName.Buffer() )
153 {
155 int oldestIdx= -1;
156 uint64_t oldestTime= ++cacheRun;
157
158 s.sourceFile= nullptr;
159 for( int i= 0; i< cacheSize; ++i )
160 {
161 if ( cache[i].origFile.Buffer() == sourceFileName.Buffer() )
162 {
163 s.sourceFile= &cache[i];
164 break;
165 }
166
167 if( oldestTime > cache[i].timeStamp )
168 {
169 oldestTime= cache[i].timeStamp;
170 oldestIdx= i;
171 }
172 }
173
174 // not found? Use the oldest
175 if ( s.sourceFile == nullptr )
176 {
177 s.sourceFile= &cache[oldestIdx];
178 s.sourceFile->Clear();
179 s.sourceFile->origFile= sourceFileName;
180 }
181
182 // mark as used
185 }
186}
187
189 lang::Inclusion includeString,
190 int trimOffset,
191 lang::Case sensitivity,
192 const NString& trimReplacement,
193 lang::Reach reach,
194 Priorities priority )
195{
196 // clear cache to have lazy variables reset with the next invocation
198 for ( int i= 0; i< cacheSize; ++i )
199 cache[i].Clear();
201
202 // clear command
203 if ( trimOffset == 999999 )
204 {
205 LocalSPTRs.clear();
206 if ( reach == lang::Reach::Global )
207 GlobalSPTRs.clear();
209
210 // reset config read flag. This is done for unit testing. Not really useful/needed in real life.
212 return;
213 }
214
215 // choose local or global list
216 std::vector<SourcePathTrimRule>* trimInfoList=
218 : &LocalSPTRs;
219
220 // insert sorted by priority
221 auto it= trimInfoList->begin();
222 while( it != trimInfoList->end() && priority < it->Priority )
223 ++it;
224
225 it= trimInfoList->emplace(it);
226 SourcePathTrimRule& rule= *it;
227 rule.Priority= priority;
228
229 // if path starts with '*', it is not a prefix. We store without *
230 rule.Path._(path, (rule.IsPrefix= (path.CharAtStart() != '*') ) == true ? 0 : 1 );
231 if ( rule.Path.CharAtEnd() == '*' )
232 rule.Path.DeleteEnd( 1 );
233 if ( rule.Path.IsEmpty() )
234 {
235 trimInfoList->erase( it );
236 return;
237 }
238
239 if( DirectorySeparator == '/' )
240 rule.Path.SearchAndReplace( '\\', '/' );
241 else
242 rule.Path.SearchAndReplace( '/' , '\\' );
243
244 rule.IncludeString= includeString;
245 rule.TrimOffset= trimOffset;
246 rule.Sensitivity= sensitivity;
247 rule.TrimReplacement.Reset( trimReplacement );
248 if( DirectorySeparator == '/' )
249 rule.TrimReplacement.SearchAndReplace( '\\', '/' );
250 else
251 rule.TrimReplacement.SearchAndReplace( '/' , '\\' );
252}
253
254
256{
257 bool trimmed= false;
258
259 SourceFile* actual= scopes[static_cast<size_t>(actScopeDepth)].sourceFile;
260 integer idx= getPathLength();
261 if( idx < 0 )
262 {
263 actual->trimmedPath= "";
264 return;
265 }
266 actual->trimmedPath= NString( actual->origFile.Buffer(), idx );
267
268
269 // do 2 times, 0== local list, 1== global list
270 for( int trimInfoNo= 0; trimInfoNo < 2 ; ++trimInfoNo )
271 {
272 // choose local or global list
273 std::vector<SourcePathTrimRule>* trimInfoList=
274 trimInfoNo == 0 ? &LocalSPTRs
275 : &GlobalSPTRs;
276
277 // loop over trimInfo
278 for ( auto& ti : *trimInfoList )
279 {
280 if( ti.IsPrefix )
281 idx= ( ti.Sensitivity == lang::Case::Sensitive ? actual->trimmedPath.StartsWith<true,lang::Case::Sensitive>( ti.Path )
282 : actual->trimmedPath.StartsWith<true,lang::Case::Ignore >( ti.Path )
283 )
284
285 ? 0 : -1;
286 else
287 idx= ti.Sensitivity == lang::Case::Sensitive ? actual->trimmedPath.IndexOf<true, lang::Case::Sensitive>( ti.Path )
288 : actual->trimmedPath.IndexOf<true, lang::Case::Ignore >( ti.Path );
289 if ( idx >= 0 )
290 {
291 integer startIdx= idx + ( ti.IncludeString == lang::Inclusion::Include ? ti.Path.Length() : 0 ) + ti.TrimOffset;
292 actual->trimmedPath= actual->trimmedPath.Substring( startIdx, actual->trimmedPath.Length() - startIdx );
293 actual->trimmedPathPrefix= ti.TrimReplacement;
294
295 trimmed= true;
296 break;
297 }
298 }
299
300 if (trimmed)
301 break;
302 }
303
304 // if nothing was found and the flag is still set, try once to auto-detect rule
305 // from the 'difference' of source path and current working directory
306 if( !trimmed && AutoDetectTrimableSourcePath )
307 {
308 AutoDetectTrimableSourcePath= false; // do this only once
309
310 // get system execution path and compare to file path
311 String256 currentDir;
313
314 Directory::CurrentDirectory( currentDir );
315
316 // Get the prefix that is the same in both paths
317 integer i= 0;
318 integer maxIdx= currentDir.Length();
319 if ( maxIdx > actual->trimmedPath.Length() )
320 maxIdx= actual->trimmedPath.Length();
321
322 while ( i < maxIdx && characters::CharArray<character>::ToUpper( currentDir[i] )
324 ++i;
325
326 if ( i > 1 )
327 {
328 currentDir.ShortenTo( i );
329 NCString origFile= actual->origFile;
330 ALIB_STRINGS_TO_NARROW(currentDir,nCurrentDir,1024)
332 lang::Reach::Local, Priorities::AutoDetected );
333 actual->origFile= origFile;
334 trimPath(); // one recursive call
335 }
336 }
337}
338
339
340}}} // namespace [alib::lox::detail]
341
342#if defined(_MSC_VER)
343 #pragma warning( pop )
344#endif
ALIB_API Priorities Load(Variable &variable)
integer Size() const
Definition variable.hpp:708
ALIB_API Variable & Declare(const VariableDecl &declaration, const Box &replacements)
Definition variable.cpp:77
const String & GetString(int idx=0)
Definition variable.hpp:780
Priorities Priority() const
Definition variable.hpp:617
config::Configuration & GetConfig()
Definition camp.hpp:231
static ALIB_API bool CurrentDirectory(AString &target)
static ALIB_API int DefaultCacheSize
Definition scopeinfo.inl:83
std::vector< SourcePathTrimRule > LocalSPTRs
static ALIB_API std::vector< SourcePathTrimRule > GlobalSPTRs
ALIB_API ScopeInfo(const NString &name, MonoAllocator *allocator, config::Variable &tempVar)
Definition scopeinfo.cpp:54
static ALIB_API bool GlobalSPTRsReadFromConfig
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)
T * EmplaceArray(TSize length, TArgs &&... args)
strings::TString< TChar > EmplaceString(const strings::TString< TChar > &src)
TAString & ShortenTo(integer newLength)
Definition astring.hpp:908
TAString & DeleteEnd(integer regionLength)
Definition astring.hpp:1589
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
Definition astring.hpp:1056
void DbgDisableBufferReplacementWarning()
Definition astring.hpp:353
ALIB_API integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0)
Definition astring.cpp:330
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:889
constexpr bool IsEmpty() const
Definition string.hpp:414
constexpr integer Length() const
Definition string.hpp:357
TChar CharAtStart() const
Definition string.hpp:459
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.hpp:314
TChar CharAtEnd() const
Definition string.hpp:481
bool StartsWith(const TString &needle) const
Definition string.hpp:813
constexpr const TChar * Buffer() const
Definition string.hpp:350
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
virtual ThreadID GetId()
Definition thread.hpp:217
static ALIB_API Thread * GetMain()
Definition thread.cpp:351
#define A_CHAR(STR)
#define ALIB_IF_THREADS(...)
Definition alib.hpp:303
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_STRINGS_TO_NARROW( src, dest, bufSize)
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:984
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
#define ALIB_STRINGS_FROM_NARROW( src, dest, bufSize)
#define ALIB_ASSERT(cond)
Definition alib.hpp:983
bool ParseEnumOrTypeBool(strings::TSubstring< TChar > &input, TEnum &result, TEnum falseValue, TEnum trueValue)
@ Exclude
Chooses exclusion.
@ Include
Chooses inclusion.
@ Global
Denotes global reach.
@ Local
Denotes local reach.
Definition alib.cpp:57
constexpr nchar DirectorySeparator
strings::TString< nchar > NString
Type alias in namespace alib.
lox::ALox ALOX
constexpr NString NullNString()
Definition string.hpp:2510
characters::character character
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
static TChar ToUpper(TChar c)
NAString TrimReplacement
Optional replacement string for trimmed paths.
int TrimOffset
Additional offset of the trim position.
Definition scopeinfo.inl:99
lang::Inclusion IncludeString
Denotes if Path itself should be included when trimmed.
Definition scopeinfo.inl:97
Priorities Priority
The priority of the rule. Depends on origin: source code, config...)
lang::Case Sensitivity
The sensitivity of the comparison when trimming.
Definition scopeinfo.inl:98
bool IsPrefix
true if path was not starting with '*' when provided.
Definition scopeinfo.inl:96