Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
catch_stream.cpp
Go to the documentation of this file.
1/*
2 * Created by Phil on 17/01/2011.
3 * Copyright 2011 Two Blue Cubes Ltd. All rights reserved.
4 *
5 * Distributed under the Boost Software License, Version 1.0. (See accompanying
6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 *
8 */
9
10#include "catch_common.h"
11#include "catch_enforce.h"
12#include "catch_stream.h"
13#include "catch_debug_console.h"
14#include "catch_stringref.h"
15#include "catch_singletons.hpp"
16
17#include <cstdio>
18#include <iostream>
19#include <fstream>
20#include <sstream>
21#include <vector>
22#include <memory>
23
24namespace Catch {
25
26 Catch::IStream::~IStream() = default;
27
28 namespace detail { namespace {
29 template<typename WriterF, std::size_t bufferSize=256>
30 class StreamBufImpl : public std::streambuf {
31 char data[bufferSize];
32 WriterF m_writer;
33
34 public:
35 StreamBufImpl() {
36 setp( data, data + sizeof(data) );
37 }
38
39 ~StreamBufImpl() noexcept {
40 StreamBufImpl::sync();
41 }
42
43 private:
44 int overflow( int c ) override {
45 sync();
46
47 if( c != EOF ) {
48 if( pbase() == epptr() )
49 m_writer( std::string( 1, static_cast<char>( c ) ) );
50 else
51 sputc( static_cast<char>( c ) );
52 }
53 return 0;
54 }
55
56 int sync() override {
57 if( pbase() != pptr() ) {
58 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
59 setp( pbase(), epptr() );
60 }
61 return 0;
62 }
63 };
64
66
67 struct OutputDebugWriter {
68
69 void operator()( std::string const&str ) {
71 }
72 };
73
75
76 class FileStream : public IStream {
77 mutable std::ofstream m_ofs;
78 public:
79 FileStream( StringRef filename ) {
80 m_ofs.open( filename.c_str() );
81 CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" );
82 }
83 ~FileStream() override = default;
84 public: // IStream
85 std::ostream& stream() const override {
86 return m_ofs;
87 }
88 };
89
91
92 class CoutStream : public IStream {
93 mutable std::ostream m_os;
94 public:
95 // Store the streambuf from cout up-front because
96 // cout may get redirected when running tests
97 CoutStream() : m_os( Catch::cout().rdbuf() ) {}
98 ~CoutStream() override = default;
99
100 public: // IStream
101 std::ostream& stream() const override { return m_os; }
102 };
103
105
106 class DebugOutStream : public IStream {
107 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
108 mutable std::ostream m_os;
109 public:
110 DebugOutStream()
111 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
112 m_os( m_streamBuf.get() )
113 {}
114
115 ~DebugOutStream() override = default;
116
117 public: // IStream
118 std::ostream& stream() const override { return m_os; }
119 };
120
121 }} // namespace anon::detail
122
124
125 auto makeStream( StringRef const &filename ) -> IStream const* {
126 if( filename.empty() )
127 return new detail::CoutStream();
128 else if( filename[0] == '%' ) {
129 if( filename == "%debug" )
130 return new detail::DebugOutStream();
131 else
132 CATCH_ERROR( "Unrecognised stream: '" << filename << "'" );
133 }
134 else
135 return new detail::FileStream( filename );
136 }
137
138
139 // This class encapsulates the idea of a pool of ostringstreams that can be reused.
141 std::vector<std::unique_ptr<std::ostringstream>> m_streams;
142 std::vector<std::size_t> m_unused;
143 std::ostringstream m_referenceStream; // Used for copy state/ flags from
144
145 auto add() -> std::size_t {
146 if( m_unused.empty() ) {
147 m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) );
148 return m_streams.size()-1;
149 }
150 else {
151 auto index = m_unused.back();
152 m_unused.pop_back();
153 return index;
154 }
155 }
156
157 void release( std::size_t index ) {
158 m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
159 m_unused.push_back(index);
160 }
161 };
162
164 : m_index( Singleton<StringStreams>::getMutable().add() ),
165 m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
166 {}
167
169 static_cast<std::ostringstream*>( m_oss )->str("");
170 m_oss->clear();
171 Singleton<StringStreams>::getMutable().release( m_index );
172 }
173
174 auto ReusableStringStream::str() const -> std::string {
175 return static_cast<std::ostringstream*>( m_oss )->str();
176 }
177
178
180
181
182#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
183 std::ostream& cout() { return std::cout; }
184 std::ostream& cerr() { return std::cerr; }
185 std::ostream& clog() { return std::clog; }
186#endif
187}
#define CATCH_ENFORCE(condition, msg)
#define CATCH_ERROR(msg)
auto str() const -> std::string
static auto getMutable() -> MutableInterfaceT &
auto c_str() const -> char const *
std::ostream & cout()
std::ostream & clog()
std::ostream & cerr()
void writeToDebugConsole(std::string const &text)
auto makeStream(StringRef const &filename) -> IStream const *
Definition name.hpp:106
int add(int a, int b)
virtual ~IStream()
auto add() -> std::size_t
std::ostringstream m_referenceStream
std::vector< std::size_t > m_unused
void release(std::size_t index)
std::vector< std::unique_ptr< std::ostringstream > > m_streams
void setp(const Operand &op)
bool overflow