Belle II Software light-2607-kasei
IOIntercept.h
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#pragma once
10
11#include <iostream>
12#include <string>
13#include <framework/logging/LogConfig.h>
14
15namespace Belle2 {
21 namespace IOIntercept {
24 public:
32 StreamInterceptor(std::ostream& stream, FILE* fileObject);
35
38 bool start()
39 {
40 // only start if we are not already running
42 return m_capturing;
43 }
44
46 bool finish()
47 {
48 if (!m_capturing) return false;
49 m_capturing = false;
50 return replaceFD(m_savedFD);
51 }
52 protected:
54 void setReplacementFD(int fd) { m_replacementFD = fd; }
59 static void readFD(int fd, std::string& out);
63 bool replaceFD(int fileDescriptor);
65 std::ostream& m_stream;
69 int m_savedFD{ -1};
73 bool m_capturing{false};
74 };
75
77 class KeepStream {
78 public:
80 KeepStream(std::ostream&, FILE*) {}
82 static bool start() { return true; }
84 static bool finish() { return true; }
85 };
86
89 public:
91 DiscardStream(std::ostream& stream, FILE* fileObject);
92 };
93
104 public:
106 CaptureStream(std::ostream& stream, FILE* fileObject);
110 const std::string& getOutput() const { return m_outputStr; }
112 // cppcheck-suppress duplInheritedMember ; intentionally hides the base class member
113 bool start();
115 // cppcheck-suppress duplInheritedMember ; intentionally hides the base class member
116 bool finish();
117 private:
119 int m_pipeReadFD{ -1};
121 std::string m_outputStr;
124 };
125
126
152 template<class STDOUT, class STDERR>
154 public:
157 bool start() { return m_stdout.start() && m_stderr.start(); }
160 bool finish() { return m_stdout.finish() && m_stderr.finish(); }
162 const std::string& getStdOut() const
163 {
164 static_assert(std::is_same<STDOUT, CaptureStream>::value, "Only valid if stdout is captured using CaptureStream");
165 return m_stdout.getOutput();
166 }
167
168 const std::string& getStdErr() const
169 {
170 static_assert(std::is_same<STDERR, CaptureStream>::value, "Only valid if stderr is captured using CaptureStream");
171 return m_stderr.getOutput();
172 }
173
174 private:
176 STDOUT m_stdout{std::cout, stdout};
178 STDERR m_stderr{std::cerr, stderr};
179 };
180
197
229 public:
237 OutputToLogMessages(const std::string& name, LogConfig::ELogLevel stdoutLevel, LogConfig::ELogLevel stderrLevel,
238 int stdoutDebugLevel, int stderrDebugLevel):
239 m_name(name), m_indent(name + ": "), m_stdoutLevel(stdoutLevel), m_stderrLevel(stderrLevel),
240 m_stdoutDebugLevel(stdoutDebugLevel), m_stderrDebugLevel(stderrDebugLevel)
241 {}
242
248 OutputToLogMessages(const std::string& name, LogConfig::ELogLevel stdoutLevel, LogConfig::ELogLevel stderrLevel):
249 OutputToLogMessages(name, stdoutLevel, stderrLevel, 100, 100)
250 {}
251
254 explicit OutputToLogMessages(const std::string& name): OutputToLogMessages(name, LogConfig::c_Info, LogConfig::c_Error)
255 {}
256
259 void setIndent(const std::string& indent) { m_indent = indent; }
261 // cppcheck-suppress duplInheritedMember ; intentionally hides the base class member
262 bool finish();
263 private:
265 const std::string m_name;
267 std::string m_indent;
276 };
277
304 template<class T> class InterceptorScopeGuard {
305 public:
310 explicit InterceptorScopeGuard(T& interceptor): m_interceptor(&interceptor)
311 {
312 m_interceptor->start();
313 }
314
316 {
317 b.m_interceptor = nullptr;
318 }
319
325 {
326 if (m_interceptor) m_interceptor->finish();
327 }
328 private:
331 };
332
348 template<class T> InterceptorScopeGuard<T> start_intercept(T& interceptor)
349 {
350 return InterceptorScopeGuard<T> {interceptor};
351 }
352 }
353
354}
CaptureStream(std::ostream &stream, FILE *fileObject)
Create a StreamInterceptor which writes into a pipe.
std::string m_outputStr
string with the output, only filled after finish()
const std::string & getOutput() const
Get the output, only set after finish()
int m_pipeReadFD
file descriptor of the read end of the pipe
friend class CaptureStreamAbortHandler
allow handling of SIGABRT
bool start()
Start intercepting the output.
~CaptureStream()
Close file descriptors.
bool finish()
Restore the stream and get the output from the pipe.
DiscardStream(std::ostream &stream, FILE *fileObject)
Create StreamInterceptor which will redirect to /dev/null.
Class to intercept stdout and stderr and either capture, discard or keep them unmodified depending on...
const std::string & getStdOut() const
Return the captured stdout output if any.
bool start()
Start intercepting the output.
bool finish()
Finish intercepting the output.
const std::string & getStdErr() const
Return the captured stderr output if any.
Simple RAII guard for output interceptor.
InterceptorScopeGuard(InterceptorScopeGuard< T > &&b)
Move constructor which will take over the interception state.
~InterceptorScopeGuard()
Finish interception on cleanup.
InterceptorScopeGuard(const InterceptorScopeGuard< T > &)=delete
We don't want copying.
InterceptorScopeGuard(T &interceptor)
Construct a new instance for a given interceptor object and start intercepting io.
InterceptorScopeGuard & operator=(const InterceptorScopeGuard &)=delete
Also no assignment.
T * m_interceptor
pointer to the interceptor we guard
KeepStream(std::ostream &, FILE *)
This class is basically empty so the constructor does nothing.
Definition IOIntercept.h:80
static bool finish()
doing nothing always succeeds
Definition IOIntercept.h:84
static bool start()
doing nothing always succeeds
Definition IOIntercept.h:82
OutputToLogMessages(const std::string &name)
Simple constructor which uses c_Info for output on stdout and c_Error for output on stderr.
LogConfig::ELogLevel m_stderrLevel
severity of the log message to be emitted for output on stderr
OutputToLogMessages(const std::string &name, LogConfig::ELogLevel stdoutLevel, LogConfig::ELogLevel stderrLevel)
Constructor to choose the log levels both stdout and stderr.
const std::string m_name
Name of the output producing tool/library.
int m_stderrDebugLevel
debug level for the log message to be emitted for output on stderr if m_stderrLevel is c_Debug
void setIndent(const std::string &indent)
Set the indent for each line of the output, default is the supplied name + ": "
~OutputToLogMessages()
Destructor to make sure that output is converted to messages on destruction.
OutputToLogMessages(const std::string &name, LogConfig::ELogLevel stdoutLevel, LogConfig::ELogLevel stderrLevel, int stdoutDebugLevel, int stderrDebugLevel)
Full constructor to choose the log levels and debug levels for both stdout and stderr.
LogConfig::ELogLevel m_stdoutLevel
severity of the log message to be emitted for output on stdout
bool finish()
Finish the capture and emit the message if output has appeard on stdout or stderr.
int m_stdoutDebugLevel
debug level for the log message to be emitted for output on stdout if m_stdoutLevel is c_Debug
std::string m_indent
Indentation to add to the beginning of each line of output.
static void readFD(int fd, std::string &out)
Read the contents of a file descriptor until there is no more input and place them in out.
std::ostream & m_stream
C++ stream object, only needed to flush before replacement.
Definition IOIntercept.h:65
bool replaceFD(int fileDescriptor)
Replace the file descriptor of m_fileObject with the one passed.
~StreamInterceptor()
close file descriptors
FILE * m_fileObject
File object of the file we want to replace, needed to obtain file descriptor and to flush.
Definition IOIntercept.h:67
void setReplacementFD(int fd)
set the replacement file descriptor, should be called in the constructor of derived classes
Definition IOIntercept.h:54
bool start()
start intercepting the stream.
Definition IOIntercept.h:38
StreamInterceptor(std::ostream &stream, FILE *fileObject)
Construct keeping a reference to the std::ostream and the file descriptor which are associated with t...
int m_replacementFD
Replacement file descriptor to be used while capturing.
Definition IOIntercept.h:71
int m_savedFD
Saved file descriptor: a duplicate of the file descriptor of m_fileObject.
Definition IOIntercept.h:69
bool finish()
stop intercepting the stream.
Definition IOIntercept.h:46
bool m_capturing
Check whether we are already capturing.
Definition IOIntercept.h:73
The LogConfig class.
Definition LogConfig.h:22
ELogLevel
Definition of the supported log levels.
Definition LogConfig.h:26
Encapsulate all classes needed to intercept stdout and stderr.
Definition IOIntercept.h:21
InterceptOutput< DiscardStream, DiscardStream > DiscardStdOutStdErr
Discard both stdout and stderr.
InterceptOutput< CaptureStream, KeepStream > CaptureStdOut
Capture only stdout and don't modify stderr.
InterceptOutput< CaptureStream, DiscardStream > CaptureStdOutDiscardStdErr
Capture stdout and discard stderr.
InterceptorScopeGuard< T > start_intercept(T &interceptor)
Convenience wrapper to simplify use of InterceptorScopeGuard<T>.
InterceptOutput< CaptureStream, CaptureStream > CaptureStdOutStdErr
Capture both stdout and stderr as strings.
InterceptOutput< DiscardStream, KeepStream > DiscardStdOut
Discard only stdout and don't modify stderr.
InterceptOutput< KeepStream, DiscardStream > DiscardStdErr
Discard only stderr and don't modify stdout.
InterceptOutput< DiscardStream, CaptureStream > DiscardStdOutCaptureStdErr
Capture stderr and discard stdout.
InterceptOutput< KeepStream, CaptureStream > CaptureStdErr
Capture only stderr and don't modify stdout.
Abstract base class for different kinds of events.