6#include "Stroika/Foundation/Execution/Exceptions.h"
8#include "Stroika/Foundation/Execution/Throw.h"
11#include "Stroika/Foundation/Streams/InternallySynchronizedOutputStream.h"
13namespace Stroika::Foundation::Streams::iostream::OutputStreamFromStdOStream {
16 template <
typename ELEMENT_TYPE,
typename BASIC_OSTREAM_ELEMENT_TYPE,
typename BASIC_OSTREAM_TRAITS_TYPE>
17 class Rep_ :
public OutputStream::IRep<ELEMENT_TYPE> {
23 static constexpr bool kTranscodes =
sizeof (ELEMENT_TYPE) !=
sizeof (BASIC_OSTREAM_ELEMENT_TYPE);
29 Rep_ (basic_ostream<BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>& originalStream)
30 : fOriginalStreamRef_{originalStream}
35 virtual bool IsSeekable ()
const override
38 return not kTranscodes;
40 virtual void CloseWrite ()
override
44 Ensure (not IsOpenWrite ());
46 virtual bool IsOpenWrite ()
const override
54 Require (IsOpenWrite ());
55 if constexpr (kTranscodes) {
60 return fOriginalStreamRef_.rdbuf ()->pubseekoff (0, ios_base::cur, ios_base::out);
63 virtual SeekOffsetType SeekWrite (Whence whence, SignedSeekOffsetType offset)
override
66 Require (IsOpenWrite ());
67 Require (IsSeekable ());
70 fOriginalStreamRef_.seekp (offset, ios::beg);
73 fOriginalStreamRef_.seekp (offset, ios::cur);
76 fOriginalStreamRef_.seekp (offset, ios::end);
79 return fOriginalStreamRef_.tellp ();
81 virtual void Write (span<const ELEMENT_TYPE> elts)
override
83 Require (not elts.empty ());
84 Require (IsOpenWrite ());
87 if constexpr (kTranscodes) {
88 Memory::StackBuffer<BASIC_OSTREAM_ELEMENT_TYPE> units{
89 Memory::eUninitialized, Characters::UTFConvert::ComputeTargetBufferSize<BASIC_OSTREAM_ELEMENT_TYPE> (elts)};
91 fOriginalStreamRef_.write (converted.data (), converted.size ());
92 fOffset_ += elts.size ();
95 fOriginalStreamRef_.write (
reinterpret_cast<const BASIC_OSTREAM_ELEMENT_TYPE*
> (elts.data ()), elts.size ());
97 if (fOriginalStreamRef_.fail ()) [[unlikely]] {
98 static const Execution::Exception<runtime_error> kException_{
"Failed to write from ostream"sv};
102 virtual void Flush ()
override
105 Require (IsOpenWrite ());
106 fOriginalStreamRef_.flush ();
107 if (fOriginalStreamRef_.fail ()) [[unlikely]] {
108 static const Execution::Exception<runtime_error> kException_{
"Failed to flush ostream"sv};
114 basic_ostream<BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>& fOriginalStreamRef_;
125 template <
typename ELEMENT_TYPE,
typename BASIC_OSTREAM_ELEMENT_TYPE,
typename BASIC_OSTREAM_TRAITS_TYPE>
126 inline auto New (basic_ostream<BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>& originalStream) ->
Ptr<ELEMENT_TYPE>
127 requires ((same_as<ELEMENT_TYPE, byte> and same_as<BASIC_OSTREAM_ELEMENT_TYPE, char>) or
128 (same_as<ELEMENT_TYPE, Characters::Character> and same_as<BASIC_OSTREAM_ELEMENT_TYPE, wchar_t>))
130 return Ptr<ELEMENT_TYPE>{Memory::MakeSharedPtr<Private_::Rep_<ELEMENT_TYPE, BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>> (originalStream)};
132 template <
typename ELEMENT_TYPE,
typename BASIC_OSTREAM_ELEMENT_TYPE,
typename BASIC_OSTREAM_TRAITS_TYPE>
134 basic_ostream<BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>& originalStream) ->
Ptr<ELEMENT_TYPE>
135 requires ((same_as<ELEMENT_TYPE, byte> and same_as<BASIC_OSTREAM_ELEMENT_TYPE, char>) or
136 (same_as<ELEMENT_TYPE, Characters::Character> and same_as<BASIC_OSTREAM_ELEMENT_TYPE, wchar_t>))
138 switch (internallySynchronized) {
139 case Execution::eInternallySynchronized:
140 return InternallySynchronizedOutputStream::New<Private_::Rep_<ELEMENT_TYPE, BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>> (
142 case Execution::eNotKnownInternallySynchronized:
143 return New<ELEMENT_TYPE> (originalStream);
#define RequireNotReached()
typename OutputStream::Ptr< ELEMENT_TYPE > Ptr
#define Stroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE
[[msvc::no_unique_address]] isn't always broken in MSVC. Annotate with this on things where its not b...
static const UTFConvert kThe
Nearly always use this default UTFConvert.
nonvirtual span< TRG_T > ConvertSpan(span< const SRC_T > source, span< TRG_T > target) const
Convert between UTF-N encoded (including the special case of ASCII, and Latin1) character spans (e....
unique_lock< AssertExternallySynchronizedChecker > WriteContext
Instantiate AssertExternallySynchronizedChecker::WriteContext to designate an area of code where prot...
shared_lock< const AssertExternallySynchronizedChecker > ReadContext
Instantiate AssertExternallySynchronizedChecker::ReadContext to designate an area of code where prote...
A Streams::Ptr<ELEMENT_TYPE> is a smart-pointer to a stream of elements of type T.
void Throw(T &&e2Throw)
like the builtin C++ 'throw', but stamps in the current Activity context and does helpful,...