ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
report.cpp
1// #################################################################################################
2// ALib C++ 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
13# include <iostream>
14# if defined( _WIN32 )
16# endif
18# if ALIB_THREADS
19# include "alib/threads/lock.hpp"
20# endif
21#endif // !DOXYGEN
22
23
25
26
27namespace alib::lang {
28
29// #################################################################################################
30// static objects
31// #################################################################################################
32Report* Report::defaultReport = nullptr;
33
34// #################################################################################################
35// class Report
36// #################################################################################################
38{
39 IF_ALIB_THREADS( ALIB_DBG(lock.Dbg.Name= "alib::lang::Report";) )
40
41 PushHaltFlags( true, false );
43}
44
49
50
51void Report::PushHaltFlags( bool haltOnErrors, bool haltOnWarnings )
52{
54 haltAfterReport.push( (haltOnErrors ? 1 : 0)
55 + (haltOnWarnings ? 2 : 0));
56}
58{
60 bool stackEmptyError;
61 )
62
63 {
65 haltAfterReport.pop();
66
67 ALIB_DBG( stackEmptyError= haltAfterReport.size() == 0; )
68 }
69
71 if ( stackEmptyError )
72 {
73 PushHaltFlags( true, true );
74 ALIB_ERROR( "REPORT", "Stack empty, too many pop operations" );
75 }
76 )
77}
78
79void Report::PushWriter( ReportWriter* newReportWriter )
80{
82 if ( writers.size() > 0 )
83 writers.top()->NotifyActivation( lang::Phase::End );
84 writers.push( newReportWriter );
85 newReportWriter->NotifyActivation( lang::Phase::Begin );
86}
87
88void Report::PopWriter( ReportWriter* checkWriter )
89{
91 if ( writers.size() == 0 ) { ALIB_ERROR( "REPORT", "No Writer to remove" ) return; }
92 if ( writers.top() != checkWriter ) { ALIB_ERROR( "REPORT", "Report Writer is not actual" ) return; }
93 writers.top()->NotifyActivation( lang::Phase::End );
94 writers.pop();
95 if ( writers.size() > 0 )
96 writers.top()->NotifyActivation( lang::Phase::Begin );
97}
98
104
105void Report::DoReport( Message& message )
106{
109 return;
110 recursionBlocker= true;
111
112 try
113 {
114 if ( writers.size() > 0 )
115 writers.top()->Report( message );
116 }
117 catch( Exception& e )
118 {
120 throw;
121 }
122
123 #if ALIB_DEBUG
124 int haltFlags= haltAfterReport.top();
125 bool halt= (message.Type == Report::Types::Error && ( (haltFlags & 1) != 0) )
126 || (message.Type == Report::Types::Warning && ( (haltFlags & 2) != 0) );
127 (void) halt; // for release compiles with ALIB_DEBUG set
128 #if defined( _WIN32 )
129 if( halt )
130 {
131 #if ALIB_CAMP
133 DebugBreak();
134 else
135 #endif
136 assert( false );
137 }
138 #else
139 #if defined(__GNUC__) || defined(__clang__)
140 if (halt) __builtin_trap();
141 #elif defined ( _MSC_VER )
142 if (halt) __debugbreak();
143 #else
144 assert( !halt );
145 #endif
146
147 #endif
148
149 #endif
150 recursionBlocker= false;
151}
152
154{
155 String1K buffer( "ALib " );
157 if ( msg.Type.Integral() == 0 ) buffer._( "Error " );
158 else if ( msg.Type.Integral() == 1 ) buffer._( "Warning " );
159 else buffer._( "Report (type=" )._( msg.Type )._(") ");
160
161 auto* out = msg.Type.Integral() == 0 || msg.Type.Integral() == 1 ? &std::cerr : &std::cout;
162 auto* other= msg.Type.Integral() == 0 || msg.Type.Integral() == 1 ? &std::cout : &std::cerr;
163
164 // With ALox replacing this report writer (the usual thing), the first string might
165 // become auto-detected as an ALox domain name. To keep this consistent we do a similar
166 // effort here (code is copied from ALoxReportWriter::Report())
167 NString64 replacement;
168 if( msg.Size() > 1
169 && msg[0].IsArrayOf<nchar>()
170 && msg[0].UnboxLength() < 29 )
171 {
172 bool illegalCharacterFound= false;
173 NString firstArg= msg[0].Unbox<NString>();
174 for( integer idx= 0 ; idx< firstArg.Length() ; ++idx )
175 {
176 char c= firstArg[idx];
177 if (! ( isdigit( c )
178 || ( c >= 'A' && c <= 'Z' )
179 || c == '-'
180 || c == '_'
181 || c == '/'
182 || c == '.'
183 ) )
184 {
185 illegalCharacterFound= true;
186 break;
187 }
188 }
189
190 if(!illegalCharacterFound)
191 {
192 replacement << "in " << firstArg << ": ";
193 msg[0]= replacement;
194 }
195 }
196
197
199 if( Formatter::Default != nullptr)
200 {
201 try
202 {
203 Formatter::Default->FormatArgs( buffer, msg );
204 }
205 catch ( Exception & e )
206 {
207 buffer << BASECAMP.GetResource( "RepFmtExc" );
208 e.Format( buffer );
209 out = &std::cerr;
210 other = &std::cout;
211 }
212 }
213 else
214 {
215 for( auto& box : msg )
216 buffer << box << " ";
217 buffer.NewLine() << "(Note: Default Formatter was not available while writing Report)";
218 }
219 buffer.NewLine() << "At: " << msg.CI;
220
222
223 out ->flush();
224 other->flush();
225 *out << std::endl;
226
227 ALIB_STRINGS_TO_NARROW(buffer, nBuffer, 16*1024)
228 out->write( nBuffer.Buffer(), nBuffer.Length() );
229 * out << std::endl;
230 out ->flush();
231 other->flush();
232
233 #if defined( _WIN32 ) && ALIB_CAMP
235 {
236 #if !ALIB_CHARACTERS_WIDE
237 OutputDebugStringA( buffer );
238 OutputDebugStringA( "\r\n" );
239 #else
240 OutputDebugStringW( buffer );
241 OutputDebugStringW( L"\r\n" );
242 #endif
243 }
244 #endif
245 }
246}
247
248
249} // namespace [alib::lang]
integer Size() const
Definition boxes.inl:176
const String & GetResource(const NString &name)
Exception & Add(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
ALIB_API AString & Format(AString &target) const
virtual ALIB_API void Report(Message &msg) override
Definition report.cpp:153
virtual void NotifyActivation(lang::Phase phase)=0
ALIB_API void PushWriter(ReportWriter *newWriter)
Definition report.cpp:79
ALIB_API void DoReport(Message &message)
Definition report.cpp:105
std::stack< ReportWriter * > writers
Definition report.hpp:108
threads::RecursiveLock lock
A Lock to protect against multithreaded calls.
Definition report.hpp:118
ALIB_API ~Report()
Destructor.
Definition report.cpp:45
ALIB_API void PopWriter(ReportWriter *checkWriter)
Definition report.cpp:88
ALIB_API Report()
Constructor.
Definition report.cpp:37
ALIB_API void PushHaltFlags(bool haltOnErrors, bool haltOnWarnings)
Definition report.cpp:51
static ALIB_API Report * defaultReport
The default Report used internally by ALib and usually by processes that rely on ALib.
Definition report.hpp:104
Types
Types of reports.
Definition report.hpp:93
ALIB_API ReportWriter * PeekWriter()
Definition report.cpp:99
ALIB_API void PopHaltFlags()
Restores the previous values after an invocation to PushHaltFlags.
Definition report.cpp:57
std::stack< int > haltAfterReport
Definition report.hpp:125
ALIB_API bool IsDebuggerPresent()
static ALIB_API threads::RecursiveLock DefaultLock
static ALIB_API SPFormatter Default
Formatter & FormatArgs(AString &target)
static TDerivedClass & GetSingleton()
Definition singleton.hpp:59
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
void DbgDisableBufferReplacementWarning()
Definition tastring.inl:363
constexpr integer Length() const
Definition string.hpp:326
DbgLockAsserter Dbg
The debug tool instance.
#define ALIB_BOXING_VTABLE_DEFINE(TMapped, Identifier)
Definition vtable.inl:473
#define IF_ALIB_THREADS(...)
Definition alib.hpp:352
#define ALIB_STRINGS_TO_NARROW( src, dest, bufSize)
#define ALIB_ERROR(...)
Definition alib.hpp:1267
#define ALIB_LOCK_RECURSIVE_WITH(lock)
Definition owner.hpp:457
#define ALIB_DBG(...)
Definition alib.hpp:390
#define ALIB_LOCK_WITH(lock)
Definition owner.hpp:456
platform_specific integer
Definition integers.hpp:43
@ Begin
The start of a transaction.
@ End
The end of a transaction.
ALIB_API Lock STD_IOSTREAMS_LOCK
Definition locks.cpp:301
lang::basecamp::BaseCamp BASECAMP
The singleton instance of ALib Camp class BaseCamp.
Definition basecamp.cpp:70
characters::nchar nchar
Type alias in namespace alib.
integer Integral() const
Definition enum.hpp:119
CallerInfo CI
The source code location that this message relates to.
Definition message.hpp:34