Moved a lot of stream related stuff out of the public headers and replaced more ostream dependencies with iosfwd

This commit is contained in:
Phil Nash 2017-11-07 15:55:09 +00:00
parent c9cdb9a48f
commit 868e125d49
9 changed files with 118 additions and 154 deletions

View File

@ -159,7 +159,6 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_session.h ${HEADER_DIR}/internal/catch_session.h
${HEADER_DIR}/internal/catch_startup_exception_registry.h ${HEADER_DIR}/internal/catch_startup_exception_registry.h
${HEADER_DIR}/internal/catch_stream.h ${HEADER_DIR}/internal/catch_stream.h
${HEADER_DIR}/internal/catch_streambuf.h
${HEADER_DIR}/internal/catch_stringref.h ${HEADER_DIR}/internal/catch_stringref.h
${HEADER_DIR}/internal/catch_string_manip.h ${HEADER_DIR}/internal/catch_string_manip.h
${HEADER_DIR}/internal/catch_suppress_warnings.h ${HEADER_DIR}/internal/catch_suppress_warnings.h
@ -220,7 +219,6 @@ set(IMPL_SOURCES
${HEADER_DIR}/internal/catch_session.cpp ${HEADER_DIR}/internal/catch_session.cpp
${HEADER_DIR}/internal/catch_startup_exception_registry.cpp ${HEADER_DIR}/internal/catch_startup_exception_registry.cpp
${HEADER_DIR}/internal/catch_stream.cpp ${HEADER_DIR}/internal/catch_stream.cpp
${HEADER_DIR}/internal/catch_streambuf.cpp
${HEADER_DIR}/internal/catch_stringref.cpp ${HEADER_DIR}/internal/catch_stringref.cpp
${HEADER_DIR}/internal/catch_string_manip.cpp ${HEADER_DIR}/internal/catch_string_manip.cpp
${HEADER_DIR}/internal/catch_tag_alias.cpp ${HEADER_DIR}/internal/catch_tag_alias.cpp

View File

@ -7,7 +7,7 @@
#include "catch_config.hpp" #include "catch_config.hpp"
#include "catch_enforce.h" #include "catch_enforce.h"
#include "catch_stream.h" #include "catch_stringref.h"
namespace Catch { namespace Catch {
@ -58,16 +58,7 @@ namespace Catch {
Verbosity Config::verbosity() const { return m_data.verbosity; } Verbosity Config::verbosity() const { return m_data.verbosity; }
IStream const* Config::openStream() { IStream const* Config::openStream() {
if( m_data.outputFilename.empty() ) return Catch::makeStream(m_data.outputFilename);
return new CoutStream();
else if( m_data.outputFilename[0] == '%' ) {
if( m_data.outputFilename == "%debug" )
return new DebugOutStream();
else
CATCH_ERROR( "Unrecognised stream: '" << m_data.outputFilename << "'" );
}
else
return new FileStream( m_data.outputFilename );
} }
} // end namespace Catch } // end namespace Catch

View File

@ -14,13 +14,15 @@
#ifdef CATCH_PLATFORM_MAC #ifdef CATCH_PLATFORM_MAC
#include <assert.h> # include <assert.h>
#include <stdbool.h> # include <stdbool.h>
#include <sys/types.h> # include <sys/types.h>
#include <unistd.h> # include <unistd.h>
#include <sys/sysctl.h> # include <sys/sysctl.h>
# include <cstddef>
# include <ostream>
namespace Catch { namespace Catch {
// The following function is taken directly from the following technical note: // The following function is taken directly from the following technical note:
// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html

View File

@ -11,7 +11,7 @@
#include "catch_tostring.h" #include "catch_tostring.h"
#include "catch_stringref.h" #include "catch_stringref.h"
#include <ostream> #include <iosfwd>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)

View File

@ -11,88 +11,129 @@
#include "catch_enforce.h" #include "catch_enforce.h"
#include "catch_stream.h" #include "catch_stream.h"
#include "catch_debug_console.h" #include "catch_debug_console.h"
#include "catch_stringref.h"
#include <stdexcept> #include <stdexcept>
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
#include <fstream>
namespace Catch { namespace Catch {
template<typename WriterF, std::size_t bufferSize=256> Catch::IStream::~IStream() = default;
class StreamBufImpl : public StreamBufBase {
char data[bufferSize];
WriterF m_writer;
public: namespace detail { namespace {
StreamBufImpl() { template<typename WriterF, std::size_t bufferSize=256>
setp( data, data + sizeof(data) ); class StreamBufImpl : public std::streambuf {
} char data[bufferSize];
WriterF m_writer;
~StreamBufImpl() noexcept { public:
StreamBufImpl::sync(); StreamBufImpl() {
} setp( data, data + sizeof(data) );
private:
int overflow( int c ) override {
sync();
if( c != EOF ) {
if( pbase() == epptr() )
m_writer( std::string( 1, static_cast<char>( c ) ) );
else
sputc( static_cast<char>( c ) );
} }
return 0;
}
int sync() override { ~StreamBufImpl() noexcept {
if( pbase() != pptr() ) { StreamBufImpl::sync();
m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
setp( pbase(), epptr() );
} }
return 0;
} private:
}; int overflow( int c ) override {
sync();
if( c != EOF ) {
if( pbase() == epptr() )
m_writer( std::string( 1, static_cast<char>( c ) ) );
else
sputc( static_cast<char>( c ) );
}
return 0;
}
int sync() override {
if( pbase() != pptr() ) {
m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
setp( pbase(), epptr() );
}
return 0;
}
};
///////////////////////////////////////////////////////////////////////////
struct OutputDebugWriter {
void operator()( std::string const&str ) {
writeToDebugConsole( str );
}
};
///////////////////////////////////////////////////////////////////////////
class FileStream : public IStream {
mutable std::ofstream m_ofs;
public:
FileStream( StringRef filename ) {
m_ofs.open( filename.c_str() );
CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" );
}
~FileStream() override = default;
public: // IStream
std::ostream& stream() const override {
return m_ofs;
}
};
///////////////////////////////////////////////////////////////////////////
class CoutStream : public IStream {
mutable std::ostream m_os;
public:
// Store the streambuf from cout up-front because
// cout may get redirected when running tests
CoutStream() : m_os( Catch::cout().rdbuf() ) {}
~CoutStream() override = default;
public: // IStream
std::ostream& stream() const override { return m_os; }
};
///////////////////////////////////////////////////////////////////////////
class DebugOutStream : public IStream {
std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
mutable std::ostream m_os;
public:
DebugOutStream()
: m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
m_os( m_streamBuf.get() )
{}
~DebugOutStream() override = default;
public: // IStream
std::ostream& stream() const override { return m_os; }
};
}} // namespace anon::detail
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
auto makeStream( StringRef const &filename ) -> IStream const* {
Catch::IStream::~IStream() = default; if( filename.empty() )
return new detail::CoutStream();
FileStream::FileStream( std::string const& filename ) { else if( filename[0] == '%' ) {
m_ofs.open( filename.c_str() ); if( filename == "%debug" )
CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); return new detail::DebugOutStream();
} else
CATCH_ERROR( "Unrecognised stream: '" << filename << "'" );
std::ostream& FileStream::stream() const {
return m_ofs;
}
struct OutputDebugWriter {
void operator()( std::string const&str ) {
writeToDebugConsole( str );
} }
}; else
return new detail::FileStream( filename );
DebugOutStream::DebugOutStream()
: m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
m_os( m_streamBuf.get() )
{}
std::ostream& DebugOutStream::stream() const {
return m_os;
} }
// Store the streambuf from cout up-front because ///////////////////////////////////////////////////////////////////////////
// cout may get redirected when running tests
CoutStream::CoutStream()
: m_os( Catch::cout().rdbuf() )
{}
std::ostream& CoutStream::stream() const {
return m_os;
}
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
std::ostream& cout() { std::ostream& cout() {

View File

@ -9,12 +9,7 @@
#ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED #ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
#include "catch_streambuf.h" #include <iosfwd>
#include <streambuf>
#include <ostream>
#include <fstream>
#include <memory>
namespace Catch { namespace Catch {
@ -22,43 +17,14 @@ namespace Catch {
std::ostream& cerr(); std::ostream& cerr();
std::ostream& clog(); std::ostream& clog();
class StringRef;
struct IStream { struct IStream {
virtual ~IStream(); virtual ~IStream();
virtual std::ostream& stream() const = 0; virtual std::ostream& stream() const = 0;
}; };
class FileStream : public IStream { auto makeStream( StringRef const &filename ) -> IStream const*;
mutable std::ofstream m_ofs;
public:
FileStream( std::string const& filename );
~FileStream() override = default;
public: // IStream
std::ostream& stream() const override;
};
class CoutStream : public IStream {
mutable std::ostream m_os;
public:
CoutStream();
~CoutStream() override = default;
public: // IStream
std::ostream& stream() const override;
};
class DebugOutStream : public IStream {
std::unique_ptr<StreamBufBase> m_streamBuf;
mutable std::ostream m_os;
public:
DebugOutStream();
~DebugOutStream() override = default;
public: // IStream
std::ostream& stream() const override;
};
} }
#endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED #endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED

View File

@ -1,12 +0,0 @@
/*
* Created by Martin on 31/08/2017.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "catch_streambuf.h"
namespace Catch {
StreamBufBase::~StreamBufBase() = default;
}

View File

@ -1,21 +0,0 @@
/*
* Created by Phil on 27/11/2012.
* Copyright 2012 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
#include <streambuf>
namespace Catch {
class StreamBufBase : public std::streambuf {
public:
virtual ~StreamBufBase();
};
}
#endif // TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED

View File

@ -39,7 +39,6 @@
#include "../../../include/internal/catch_session.cpp" #include "../../../include/internal/catch_session.cpp"
#include "../../../include/internal/catch_startup_exception_registry.cpp" #include "../../../include/internal/catch_startup_exception_registry.cpp"
#include "../../../include/internal/catch_stream.cpp" #include "../../../include/internal/catch_stream.cpp"
#include "../../../include/internal/catch_streambuf.cpp"
#include "../../../include/internal/catch_string_manip.cpp" #include "../../../include/internal/catch_string_manip.cpp"
#include "../../../include/internal/catch_stringref.cpp" #include "../../../include/internal/catch_stringref.cpp"
#include "../../../include/internal/catch_tag_alias.cpp" #include "../../../include/internal/catch_tag_alias.cpp"