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 #ifndef TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
10 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
11 
12 #include "catch_stream.h"
13 #include "catch_debugger.h"
14 
15 #include <stdexcept>
16 #include <cstdio>
17 #include <iostream>
18 
19 namespace Catch {
20 
21     template<typename WriterF, size_t bufferSize=256>
22     class StreamBufImpl : public StreamBufBase {
23         char data[bufferSize];
24         WriterF m_writer;
25 
26     public:
StreamBufImpl()27         StreamBufImpl() {
28             setp( data, data + sizeof(data) );
29         }
30 
~StreamBufImpl()31         ~StreamBufImpl() CATCH_NOEXCEPT {
32             sync();
33         }
34 
35     private:
overflow(int c)36         int overflow( int c ) {
37             sync();
38 
39             if( c != EOF ) {
40                 if( pbase() == epptr() )
41                     m_writer( std::string( 1, static_cast<char>( c ) ) );
42                 else
43                     sputc( static_cast<char>( c ) );
44             }
45             return 0;
46         }
47 
sync()48         int sync() {
49             if( pbase() != pptr() ) {
50                 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
51                 setp( pbase(), epptr() );
52             }
53             return 0;
54         }
55     };
56 
57     ///////////////////////////////////////////////////////////////////////////
58 
59 
FileStream(std::string const & filename)60     FileStream::FileStream( std::string const& filename ) {
61         m_ofs.open( filename.c_str() );
62         if( m_ofs.fail() ) {
63             std::ostringstream oss;
64             oss << "Unable to open file: '" << filename << '\'';
65             throw std::domain_error( oss.str() );
66         }
67     }
68 
stream() const69     std::ostream& FileStream::stream() const {
70         return m_ofs;
71     }
72 
73     struct OutputDebugWriter {
74 
operator ()Catch::OutputDebugWriter75         void operator()( std::string const&str ) {
76             writeToDebugConsole( str );
77         }
78     };
79 
DebugOutStream()80     DebugOutStream::DebugOutStream()
81     :   m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
82         m_os( m_streamBuf.get() )
83     {}
84 
stream() const85     std::ostream& DebugOutStream::stream() const {
86         return m_os;
87     }
88 
89     // Store the streambuf from cout up-front because
90     // cout may get redirected when running tests
CoutStream()91     CoutStream::CoutStream()
92     :   m_os( Catch::cout().rdbuf() )
93     {}
94 
stream() const95     std::ostream& CoutStream::stream() const {
96         return m_os;
97     }
98 
99 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
cout()100     std::ostream& cout() {
101         return std::cout;
102     }
cerr()103     std::ostream& cerr() {
104         return std::cerr;
105     }
clog()106     std::ostream& clog() {
107         return std::clog;
108     }
109 #endif
110 }
111 
112 #endif // TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
113