2020-08-30 15:43:45 +02:00
|
|
|
|
|
|
|
|
// Copyright Catch2 Authors
|
|
|
|
|
// Distributed under the Boost Software License, Version 1.0.
|
2022-10-28 11:22:53 +02:00
|
|
|
// (See accompanying file LICENSE.txt or copy at
|
2020-08-30 15:43:45 +02:00
|
|
|
// https://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
|
|
|
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
2022-04-16 15:00:41 +02:00
|
|
|
#include <catch2/internal/catch_reusable_string_stream.hpp>
|
2020-03-30 10:34:21 +02:00
|
|
|
#include <catch2/internal/catch_singletons.hpp>
|
2025-08-23 00:15:53 +02:00
|
|
|
#include <catch2/internal/catch_thread_support.hpp>
|
2020-05-25 09:45:24 +02:00
|
|
|
#include <catch2/internal/catch_unique_ptr.hpp>
|
2012-09-28 19:21:14 +01:00
|
|
|
|
2011-02-02 19:45:59 +00:00
|
|
|
#include <cstdio>
|
2017-11-07 18:01:10 +00:00
|
|
|
#include <sstream>
|
2025-09-25 04:31:49 -07:00
|
|
|
#include <tuple>
|
2017-11-07 18:01:10 +00:00
|
|
|
#include <vector>
|
|
|
|
|
|
2012-05-15 08:02:36 +01:00
|
|
|
namespace Catch {
|
|
|
|
|
|
2017-11-07 18:01:10 +00:00
|
|
|
// This class encapsulates the idea of a pool of ostringstreams that can be reused.
|
|
|
|
|
struct StringStreams {
|
2020-05-25 09:45:24 +02:00
|
|
|
std::vector<Detail::unique_ptr<std::ostringstream>> m_streams;
|
2017-11-07 18:01:10 +00:00
|
|
|
std::vector<std::size_t> m_unused;
|
|
|
|
|
std::ostringstream m_referenceStream; // Used for copy state/ flags from
|
2025-08-23 00:15:53 +02:00
|
|
|
Detail::Mutex m_mutex;
|
2017-11-07 18:01:10 +00:00
|
|
|
|
2025-09-25 04:31:49 -07:00
|
|
|
auto add() -> std::pair<std::size_t, std::ostringstream*> {
|
2025-08-23 00:15:53 +02:00
|
|
|
Detail::LockGuard _( m_mutex );
|
2017-11-07 18:01:10 +00:00
|
|
|
if( m_unused.empty() ) {
|
2021-08-10 00:16:05 +02:00
|
|
|
m_streams.push_back( Detail::make_unique<std::ostringstream>() );
|
2025-09-25 04:31:49 -07:00
|
|
|
return { m_streams.size()-1, m_streams.back().get() };
|
2017-11-07 18:01:10 +00:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
auto index = m_unused.back();
|
|
|
|
|
m_unused.pop_back();
|
2025-09-25 04:31:49 -07:00
|
|
|
return { index, m_streams[index].get() };
|
2017-11-07 18:01:10 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-23 00:15:53 +02:00
|
|
|
void release( std::size_t index, std::ostream* originalPtr ) {
|
|
|
|
|
assert( originalPtr );
|
|
|
|
|
originalPtr->copyfmt( m_referenceStream ); // Restore initial flags and other state
|
|
|
|
|
|
|
|
|
|
Detail::LockGuard _( m_mutex );
|
|
|
|
|
assert( originalPtr == m_streams[index].get() && "Mismatch between release index and stream ptr" );
|
|
|
|
|
m_unused.push_back( index );
|
2017-11-07 18:01:10 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-25 04:31:49 -07:00
|
|
|
ReusableStringStream::ReusableStringStream() {
|
|
|
|
|
std::tie( m_index, m_oss ) =
|
|
|
|
|
Singleton<StringStreams>::getMutable().add();
|
|
|
|
|
}
|
2017-11-07 18:01:10 +00:00
|
|
|
|
|
|
|
|
ReusableStringStream::~ReusableStringStream() {
|
|
|
|
|
static_cast<std::ostringstream*>( m_oss )->str("");
|
|
|
|
|
m_oss->clear();
|
2025-08-23 00:15:53 +02:00
|
|
|
Singleton<StringStreams>::getMutable().release( m_index, m_oss );
|
2017-11-07 18:01:10 +00:00
|
|
|
}
|
|
|
|
|
|
2020-08-02 18:50:56 +02:00
|
|
|
std::string ReusableStringStream::str() const {
|
2017-11-07 18:01:10 +00:00
|
|
|
return static_cast<std::ostringstream*>( m_oss )->str();
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-02 18:50:56 +02:00
|
|
|
void ReusableStringStream::str( std::string const& str ) {
|
|
|
|
|
static_cast<std::ostringstream*>( m_oss )->str( str );
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-07 18:01:10 +00:00
|
|
|
|
2011-01-18 09:20:06 +00:00
|
|
|
}
|