1 // 231-Cfg-OutputStreams.cpp
2 // Show how to replace the streams with a simple custom made streambuf.
3 
4 // Note that this reimplementation _does not_ follow `std::cerr`
5 // semantic, because it buffers the output. For most uses however,
6 // there is no important difference between having `std::cerr` buffered
7 // or unbuffered.
8 
9 #define CATCH_CONFIG_NOSTDOUT
10 #define CATCH_CONFIG_MAIN
11 #include <catch2/catch.hpp>
12 
13 
14 class out_buff : public std::stringbuf {
15     std::FILE* m_stream;
16 public:
out_buff(std::FILE * stream)17     out_buff(std::FILE* stream):m_stream(stream) {}
18     ~out_buff();
sync()19     int sync() override {
20         int ret = 0;
21         for (unsigned char c : str()) {
22             if (putc(c, m_stream) == EOF) {
23                 ret = -1;
24                 break;
25             }
26         }
27         // Reset the buffer to avoid printing it multiple times
28         str("");
29         return ret;
30     }
31 };
32 
~out_buff()33 out_buff::~out_buff() { pubsync(); }
34 
35 #if defined(__clang__)
36 #pragma clang diagnostic ignored "-Wexit-time-destructors" // static variables in cout/cerr/clog
37 #endif
38 
39 namespace Catch {
cout()40     std::ostream& cout() {
41         static std::ostream ret(new out_buff(stdout));
42         return ret;
43     }
clog()44     std::ostream& clog() {
45         static std::ostream ret(new out_buff(stderr));
46         return ret;
47     }
cerr()48     std::ostream& cerr() {
49         return clog();
50     }
51 }
52 
53 
54 TEST_CASE("This binary uses putc to write out output", "[compilation-only]") {
55     SUCCEED("Nothing to test.");
56 }
57