Belle II Software development
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 }
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 bool start() const { return true; }
84 bool finish() const { 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 bool start();
114 bool finish();
115 private:
117 int m_pipeReadFD{ -1};
119 std::string m_outputStr;
122 };
123
124
150 template<class STDOUT, class STDERR>
152 public:
155 bool start() { return m_stdout.start() && m_stderr.start(); }
158 bool finish() { return m_stdout.finish() && m_stderr.finish(); }
160 const std::string& getStdOut() const
161 {
162 static_assert(std::is_same<STDOUT, CaptureStream>::value, "Only valid if stdout is captured using CaptureStream");
163 return m_stdout.getOutput();
164 }
166 const std::string& getStdErr() const
167 {
168 static_assert(std::is_same<STDERR, CaptureStream>::value, "Only valid if stderr is captured using CaptureStream");
169 return m_stderr.getOutput();
170 }
171
172 private:
174 STDOUT m_stdout{std::cout, stdout};
176 STDERR m_stderr{std::cerr, stderr};
177 };
178
195
227 public:
235 OutputToLogMessages(const std::string& name, LogConfig::ELogLevel stdoutLevel, LogConfig::ELogLevel stderrLevel,
236 int stdoutDebugLevel, int stderrDebugLevel):
237 m_name(name), m_indent(name + ": "), m_stdoutLevel(stdoutLevel), m_stderrLevel(stderrLevel),
238 m_stdoutDebugLevel(stdoutDebugLevel), m_stderrDebugLevel(stderrDebugLevel)
239 {}
246 OutputToLogMessages(const std::string& name, LogConfig::ELogLevel stdoutLevel, LogConfig::ELogLevel stderrLevel):
247 OutputToLogMessages(name, stdoutLevel, stderrLevel, 100, 100)
248 {}
252 explicit OutputToLogMessages(const std::string& name): OutputToLogMessages(name, LogConfig::c_Info, LogConfig::c_Error)
253 {}
257 void setIndent(const std::string& indent) { m_indent = indent; }
259 bool finish();
260 private:
262 const std::string m_name;
264 std::string m_indent;
273 };
274
301 template<class T> class InterceptorScopeGuard {
302 public:
307 explicit InterceptorScopeGuard(T& interceptor): m_interceptor(&interceptor)
308 {
309 m_interceptor->start();
310 }
313 {
314 b.m_interceptor = nullptr;
315 }
322 {
323 if (m_interceptor) m_interceptor->finish();
324 }
325 private:
328 };
329
345 template<class T> InterceptorScopeGuard<T> start_intercept(T& interceptor)
346 {
347 return InterceptorScopeGuard<T> {interceptor};
348 }
349 }
351}
Small class to handle std::abort() calls by external libraries.
Definition: IOIntercept.cc:34
Class to capture anything written to stream into a string.
Definition: IOIntercept.h:103
std::string m_outputStr
string with the output, only filled after finish()
Definition: IOIntercept.h:119
const std::string & getOutput() const
Get the output, only set after finish()
Definition: IOIntercept.h:110
int m_pipeReadFD
file descriptor of the read end of the pipe
Definition: IOIntercept.h:117
bool start()
Start intercepting the output.
Definition: IOIntercept.cc:176
~CaptureStream()
Close file descriptors.
Definition: IOIntercept.cc:167
bool finish()
Restore the stream and get the output from the pipe.
Definition: IOIntercept.cc:185
Simple class to just discard anything written to stream by redirecting it to /dev/null.
Definition: IOIntercept.h:88
Class to intercept stdout and stderr and either capture, discard or keep them unmodified depending on...
Definition: IOIntercept.h:151
STDOUT m_stdout
StreamInterceptor for stdout.
Definition: IOIntercept.h:174
STDERR m_stderr
StreamInterceptor for stderr.
Definition: IOIntercept.h:176
const std::string & getStdOut() const
Return the captured stdout output if any.
Definition: IOIntercept.h:160
bool start()
Start intercepting the output.
Definition: IOIntercept.h:155
bool finish()
Finish intercepting the output.
Definition: IOIntercept.h:158
const std::string & getStdErr() const
Return the captured stderr output if any.
Definition: IOIntercept.h:166
Simple RAII guard for output interceptor.
Definition: IOIntercept.h:301
InterceptorScopeGuard(InterceptorScopeGuard< T > &&b)
Move constructor which will take over the interception state.
Definition: IOIntercept.h:312
~InterceptorScopeGuard()
Finish interception on cleanup.
Definition: IOIntercept.h:321
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.
Definition: IOIntercept.h:307
InterceptorScopeGuard & operator=(const InterceptorScopeGuard &)=delete
Also no assignment.
T * m_interceptor
pointer to the interceptor we guard
Definition: IOIntercept.h:327
Dummy class which keeps the stream unmodified.
Definition: IOIntercept.h:77
KeepStream(std::ostream &, FILE *)
This class is basically empty so the constructor does nothing.
Definition: IOIntercept.h:80
bool start() const
doing nothing always succeds
Definition: IOIntercept.h:82
bool finish() const
doing nothing always succeds
Definition: IOIntercept.h:84
Capture stdout and stderr and convert into log messages.
Definition: IOIntercept.h:226
OutputToLogMessages(const std::string &name)
Simple constructor which uses c_Info for output on stdout and c_Error for output on stderr.
Definition: IOIntercept.h:252
LogConfig::ELogLevel m_stderrLevel
severity of the log message to be emitted for output on stderr
Definition: IOIntercept.h:268
OutputToLogMessages(const std::string &name, LogConfig::ELogLevel stdoutLevel, LogConfig::ELogLevel stderrLevel)
Constructor to choose the log levels both stdout and stderr.
Definition: IOIntercept.h:246
const std::string m_name
Name of the output producing tool/library.
Definition: IOIntercept.h:262
int m_stderrDebugLevel
debug level for the log message to be emitted for output on stderr if m_stderrLevel is c_Debug
Definition: IOIntercept.h:272
void setIndent(const std::string &indent)
Set the indent for each line of the output, default is the supplied name + ": "
Definition: IOIntercept.h:257
~OutputToLogMessages()
Destructor to make sure that output is converted to messages on destruction.
Definition: IOIntercept.h:255
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.
Definition: IOIntercept.h:235
LogConfig::ELogLevel m_stdoutLevel
severity of the log message to be emitted for output on stdout
Definition: IOIntercept.h:266
bool finish()
Finish the capture and emit the message if output has appeard on stdout or stderr.
Definition: IOIntercept.cc:236
int m_stdoutDebugLevel
debug level for the log message to be emitted for output on stdout if m_stdoutLevel is c_Debug
Definition: IOIntercept.h:270
std::string m_indent
Identation to add to the beginning of each line of output.
Definition: IOIntercept.h:264
Base class with all necessary features to intercept output to a file descriptor.
Definition: IOIntercept.h:23
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.
Definition: IOIntercept.cc:102
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.
Definition: IOIntercept.cc:120
~StreamInterceptor()
close file descriptors
Definition: IOIntercept.cc:95
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
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
InterceptorScopeGuard< T > start_intercept(T &interceptor)
Convenience wrapper to simplify use of InterceptorScopeGuard<T>.
Definition: IOIntercept.h:345
Abstract base class for different kinds of events.