ALib C++ Library
Library Version: 2412 R0
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 !DOXYGEN
10# include "alib/alox/alox.hpp"
11# include "alib/alox/aloxcamp.hpp"
12# define HPP_ALIB_LOX_PROPPERINCLUDE
14# undef HPP_ALIB_LOX_PROPPERINCLUDE
18#endif // !DOXYGEN
19
20
21// conditional expression is constant (which is a great thing for the compiler by the way ;-)
22#if defined(_MSC_VER)
23 #pragma warning( push )
24 #pragma warning( disable : 4127 )
25#endif
26
27using namespace alib::lang::system;
28
29namespace alib { namespace lox { namespace detail {
30
31// #################################################################################################
32// Static
33// #################################################################################################
34
35std::vector<ScopeInfo::SourcePathTrimRule> ScopeInfo::GlobalSPTRs;
37
38ScopeInfo::ScopeInfo( const NString& pName, MonoAllocator& allocator )
39#if ALIB_THREADS
40: threadDictionary (allocator)
41,
42#else
43:
44#endif
45 parsedFileNameCache(allocator, 4, 6)
46, callStack (allocator)
47, loxName (allocator, pName)
48{
49 callStack.reserve(2);
50 characters::ToUpper( const_cast<char*>( loxName.Buffer() ), loxName.Length() );
51 ALIB_ASSERT_ERROR( !loxName.Equals<NC>( "GLOBAL" ), "ALOX", "Name \"GLOBAL\" not allowed for Lox instances" )
52
53 IF_ALIB_THREADS( threadDictionary.EmplaceUnique(Thread::GetMain()->GetID(), "PROCESS" ); )
54
55 // read trim rules from config
56 // do 2 times, 0== local list, 1== global list
57 std::vector<SourcePathTrimRule>* trimInfoList;
58 for( int trimInfoNo= 0; trimInfoNo < 2 ; ++trimInfoNo )
60 Variable variable(ALOX);
61
62 // check if done... or set list
63 if ( trimInfoNo == 0 )
64 {
65 trimInfoList= &LocalSPTRs;
66 ALIB_STRINGS_FROM_NARROW(loxName,sLoxName, 1024)
67 variable.Declare( Variables::SPTR_LOX, sLoxName );
68 }
69 else
70 {
71 if ( GlobalSPTRsReadFromConfig )
72 continue;
73 GlobalSPTRsReadFromConfig= true;
74
75 trimInfoList= &GlobalSPTRs;
77 }
78
79 if( variable.IsDefined() )
80 {
81 Tokenizer tokOuter;
82 tokOuter.Set(variable, ';', true);
83 while(tokOuter.HasNext())
84 {
85 Tokenizer ruleTknzr( tokOuter.Next(), ',' );
86 trimInfoList->emplace_back();
87 SourcePathTrimRule& rule=trimInfoList->back();
88 rule.Priority= variable.GetPriority();
89
90 ruleTknzr.Next();
91 if( ( rule.IsPrefix= !ruleTknzr.Actual.StartsWith( A_CHAR("*") ) ) == false )
92 ruleTknzr.Actual.ConsumeChars(1);
93 rule.Path._( ruleTknzr.Actual );
94 if ( rule.Path.CharAtEnd() == '*' )
95 rule.Path.DeleteEnd( 1 );
96
97 if ( rule.Path.IsEmpty() )
98 {
99 trimInfoList->pop_back();
100 continue;
101 }
102
103 if( DIRECTORY_SEPARATOR == '/' )
104 rule.Path.SearchAndReplace( '\\', '/' );
105 else
106 rule.Path.SearchAndReplace( '/' , '\\' );
107
109 ruleTknzr.Next().ConsumeInt( rule.TrimOffset );
111
112 rule.TrimReplacement.Reset( ruleTknzr.Next() );
113 }
114 }
115 }
116}
117
119{
122 if( callStack.size() == size_t(callStackSize) )
123 callStack.emplace_back();
124
125 FrameRecord& scope= callStack[size_t(callStackSize)];
126
127 scope.timeStamp = Ticks::Now();
128 scope.origLine = ci.Line;
129 scope.origMethod= ci.Func;
130 auto resultPair = parsedFileNameCache.Try( ci.File ); // search file in cache
131 if( resultPair.first == false )
132 resultPair.second.Construct(ci.File);
133 scope.Parsed = &*resultPair.second;
134
135 // we must not use ci.ThreadID, because this might be nulled with release logging
136 IF_ALIB_THREADS( threadNativeIDx= std::this_thread::get_id();
137 thread = nullptr;
138 threadName = nullptr;
139 )
140}
141
143 lang::Inclusion includeString,
144 int trimOffset,
145 lang::Case sensitivity,
146 const NString& trimReplacement,
147 lang::Reach reach,
148 Priority priority )
149{
150 // clear cache to have lazy variables reset with the next invocation
151 parsedFileNameCache.Clear();
152
153 // clear command
154 if ( trimOffset == 999999 )
155 {
156 LocalSPTRs.clear();
157 if ( reach == lang::Reach::Global )
158 GlobalSPTRs.clear();
160
161 // reset config read flag. This is done for unit testing. Not really useful/needed in real life.
163 return;
164 }
165
166 // choose local or global list
167 std::vector<SourcePathTrimRule>* trimInfoList=
169 : &LocalSPTRs;
170
171 // insert sorted by priority
172 auto it= trimInfoList->begin();
173 while( it != trimInfoList->end() && priority < it->Priority )
174 ++it;
175
176 it= trimInfoList->emplace(it);
177 SourcePathTrimRule& rule= *it;
178 rule.Priority= priority;
179
180 // if path starts with '*', it is not a prefix. We store without *
181 rule.Path._(path, (rule.IsPrefix= (path.CharAtStart() != '*') ) == true ? 0 : 1 );
182 if ( rule.Path.CharAtEnd() == '*' )
183 rule.Path.DeleteEnd( 1 );
184 if ( rule.Path.IsEmpty() )
185 {
186 trimInfoList->erase( it );
187 return;
188 }
189
190 if( DIRECTORY_SEPARATOR == '/' )
191 rule.Path.SearchAndReplace( '\\', '/' );
192 else
193 rule.Path.SearchAndReplace( '/' , '\\' );
194
195 rule.IncludeString= includeString;
196 rule.TrimOffset= trimOffset;
197 rule.Sensitivity= sensitivity;
198 rule.TrimReplacement.Reset( trimReplacement );
199 if( DIRECTORY_SEPARATOR == '/' )
200 rule.TrimReplacement.SearchAndReplace( '\\', '/' );
201 else
202 rule.TrimReplacement.SearchAndReplace( '/' , '\\' );
203}
204
205
207{
208 bool trimmed= false;
209
210 ParsedFileName* actual= callStack[size_t(callStackSize)].Parsed;
211 integer idx= getPathLength();
212 if( idx < 0 )
213 {
214 actual->trimmedPath= "";
215 return;
216 }
217 actual->trimmedPath= NString( actual->origFile.Buffer(), idx );
218
219
220 // do 2 times, 0== local list, 1== global list
221 for( int trimInfoNo= 0; trimInfoNo < 2 ; ++trimInfoNo )
222 {
223 // choose local or global list
224 std::vector<SourcePathTrimRule>* trimInfoList=
225 trimInfoNo == 0 ? &LocalSPTRs
226 : &GlobalSPTRs;
227
228 // loop over trimInfo
229 for ( auto& ti : *trimInfoList )
230 {
231 if( ti.IsPrefix )
232 idx= ( ti.Sensitivity == lang::Case::Sensitive ? actual->trimmedPath.StartsWith<CHK,lang::Case::Sensitive>( ti.Path )
233 : actual->trimmedPath.StartsWith<CHK,lang::Case::Ignore >( ti.Path )
234 )
235
236 ? 0 : -1;
237 else
238 idx= ti.Sensitivity == lang::Case::Sensitive ? actual->trimmedPath.IndexOf<CHK, lang::Case::Sensitive>( ti.Path )
239 : actual->trimmedPath.IndexOf<CHK, lang::Case::Ignore >( ti.Path );
240 if ( idx >= 0 )
241 {
242 integer startIdx= idx + ( ti.IncludeString == lang::Inclusion::Include ? ti.Path.Length() : 0 ) + ti.TrimOffset;
243 actual->trimmedPath= actual->trimmedPath.Substring( startIdx, actual->trimmedPath.Length() - startIdx );
244 actual->trimmedPathPrefix= ti.TrimReplacement;
245
246 trimmed= true;
247 break;
248 }
249 }
250
251 if (trimmed)
252 break;
253 }
254
255 // if nothing was found and the flag is still set, try once to auto-detect rule
256 // from the 'difference' of source path and current working directory
257 if( !trimmed && AutoDetectTrimableSourcePath )
258 {
259 AutoDetectTrimableSourcePath= false; // do this only once
260
261 // get system execution path and compare to file path
262 Path currentDir(SystemFolders::Current);
263
264 // Get the prefix that is the same in both paths
265 integer i= 0;
266 integer maxIdx= currentDir.Length();
267 if ( maxIdx > actual->trimmedPath.Length() )
268 maxIdx= actual->trimmedPath.Length();
269
270 while ( i < maxIdx && characters::ToUpper( currentDir[i] )
271 == characters::ToUpper( static_cast<character>(actual->trimmedPath[i]) ) )
272 ++i;
273
274 if ( i > 1 )
275 {
276 currentDir.ShortenTo( i );
277 NCString origFile= actual->origFile;
278 ALIB_PATH_TO_NARROW(currentDir,nCurrentDir,1024)
280 lang::Reach::Local, Priority::AutoDetected );
281 actual->origFile= origFile;
282 trimPath(); // one recursive call
283 }
284 }
285}
286
287
288}}} // namespace [alib::lox::detail]
289
290#if defined(_MSC_VER)
291 #pragma warning( pop )
292#endif
293
ALIB_API Variable & Declare(const String &name, const String &typeName, const String &defaultValue=NULL_STRING)
Definition variable.cpp:193
Priority GetPriority() const
threads::SharedLock & GetConfigLock()
Definition camp.hpp:219
std::vector< SourcePathTrimRule > LocalSPTRs
List of trim definitions for portions of source paths to be ignored.
Definition scopeinfo.inl:88
StdVectorMono< FrameRecord > callStack
A stack of scopes (allows recursive calls/nested logging).
static ALIB_API std::vector< SourcePathTrimRule > GlobalSPTRs
List of trim definitions for portions of source paths to be ignored.
Definition scopeinfo.inl:85
static ALIB_API bool GlobalSPTRsReadFromConfig
Flag to determine if global rules have been read from config already.
Definition scopeinfo.inl:92
Thread * thread
The thread passed with Set.
ALIB_API void Set(const lang::CallerInfo &ci)
std::thread::id threadNativeIDx
The C++ native ID.
int callStackSize
The current depth of recursive invocations.
ALIB_API void SetSourcePathTrimRule(const NCString &path, lang::Inclusion includeString, int trimOffset, lang::Case sensitivity, const NString &trimReplacement, lang::Reach reach, Priority priority)
String threadName
The name of the thread that executed the log.
LRUCacheTable< MonoAllocator, ValueDescriptorPFN, std::hash< NString > > parsedFileNameCache
Least recently used cache of parsed file name.
ALIB_API ScopeInfo(const NString &name, MonoAllocator &allocator)
Definition scopeinfo.cpp:38
TAString & ShortenTo(integer newLength)
Definition tastring.inl:971
ALIB_API integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0, integer endIdx=strings::MAX_LEN)
TAString & DeleteEnd(integer regionLength)
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:896
constexpr bool IsEmpty() const
Definition string.hpp:383
constexpr integer Length() const
Definition string.hpp:326
TChar CharAtStart() const
Definition string.hpp:466
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.hpp:406
TChar CharAtEnd() const
Definition string.hpp:488
bool StartsWith(const TString &needle) const
Definition string.hpp:820
constexpr const TChar * Buffer() const
Definition string.hpp:319
ALIB_API TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
Definition tokenizer.cpp:16
TSubstring< TChar > Actual
Definition tokenizer.hpp:73
void Set(const TString< TChar > &src, TChar delimiter, bool skipEmptyTokens=false)
ThreadID GetID() const
Definition thread.hpp:207
static ALIB_API Thread * GetMain()
Definition thread.cpp:320
#define IF_ALIB_THREADS(...)
Definition alib.hpp:352
#define A_CHAR(STR)
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:1271
#define ALIB_PATH_TO_NARROW( src, dest, bufSize)
Definition path.hpp:66
#define ALIB_LOCK_WITH(lock)
Definition owner.hpp:456
#define ALIB_STRINGS_FROM_NARROW( src, dest, bufSize)
#define ALIB_ASSERT(cond)
Definition alib.hpp:1270
TChar ToUpper(TChar c)
bool ParseEnumOrTypeBool(strings::TSubstring< TChar > &input, TEnum &result, TEnum falseValue, TEnum trueValue)
This is the reference documentation of sub-namespace system of module ALib BaseCamp.
Definition basecamp.cpp:75
static constexpr PathCharType DIRECTORY_SEPARATOR
The standard path separator character. Defaults to '\' on Windows OS, '/' else.
Definition path.hpp:99
Inclusion
Denotes how members of a set something should be taken into account.
@ Exclude
Chooses exclusion.
@ Include
Chooses inclusion.
Reach
Denotes the reach of something.
@ Global
Denotes global reach.
@ Local
Denotes local reach.
Case
Denotes upper and lower case character treatment.
@ SPTR_GLOBAL
Denotes configuration variable ALOX/GLOBAL_SOURCE_PATH_TRIM_RULES.
@ SPTR_LOX
Denotes configuration variable ALOX/LOXNAME/SOURCE_PATH_TRIM_RULES used by class Lox.
Definition alib.cpp:69
lox::ALoxCamp ALOX
The singleton instance of ALib Camp class ALoxCamp.
Definition aloxcamp.cpp:33
constexpr NString NULL_NSTRING
A nulled string of the narrow character type.
Definition string.hpp:2558
strings::TString< nchar > NString
Type alias in namespace alib.
characters::character character
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273
See sibling type NC.
Definition alib.hpp:1097
const char * Func
Definition alib.hpp:1132
const char * File
The name of the source file as given by compiler.
Definition alib.hpp:1130
int Line
The line number within File.
Definition alib.hpp:1131
Ticks timeStamp
Time of the call that created this record.
ParsedFileName * Parsed
The entry from the parsedFileNameCache.
NCString origMethod
Function/method name (given by the C++ preprocessor)
int origLine
Line number within the source file (given by the C++ preprocessor)
Information of a single source file. Stored in field parsedFileNameCache.
NCString origFile
Path and name of source file (given by the C++ preprocessor).
NString trimmedPath
Trimmed path of source file (evaluated).
NAString TrimReplacement
Optional replacement string for trimmed paths.
Definition scopeinfo.inl:75
int TrimOffset
Additional offset of the trim position.
Definition scopeinfo.inl:76
lang::Inclusion IncludeString
Denotes if Path itself should be included when trimmed.
Definition scopeinfo.inl:77
lang::Case Sensitivity
The sensitivity of the comparison when trimming.
Definition scopeinfo.inl:78
config::Priority Priority
The priority of the rule. Depends on origin: source code, config...)
Definition scopeinfo.inl:79
bool IsPrefix
true if path was not starting with '*', when provided.
Definition scopeinfo.inl:80