Stroika Library 3.0d23x
 
Loading...
Searching...
No Matches
OutputStreamFromStdOStream.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
5#include "Stroika/Foundation/Execution/Exceptions.h"
7#include "Stroika/Foundation/Execution/Throw.h"
9#include "Stroika/Foundation/Streams/InternallySynchronizedOutputStream.h"
10
11namespace Stroika::Foundation::Streams::iostream::OutputStreamFromStdOStream {
12
13 namespace Private_ {
14 template <typename ELEMENT_TYPE, typename BASIC_OSTREAM_ELEMENT_TYPE, typename BASIC_OSTREAM_TRAITS_TYPE>
15 class Rep_ : public OutputStream::IRep<ELEMENT_TYPE> {
16 private:
17 bool fOpen_{true};
18
19 public:
20 Rep_ (basic_ostream<BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>& originalStream)
21 : fOriginalStreamRef_{originalStream}
22 {
23 }
24
25 protected:
26 virtual bool IsSeekable () const override
27 {
28 Debug::AssertExternallySynchronizedMutex::ReadContext declareContext{fThisAssertExternallySynchronized_};
29 return true;
30 }
31 virtual void CloseWrite () override
32 {
33 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
34 fOpen_ = false;
35 Ensure (not IsOpenWrite ());
36 }
37 virtual bool IsOpenWrite () const override
38 {
39 Debug::AssertExternallySynchronizedMutex::ReadContext declareContext{fThisAssertExternallySynchronized_};
40 return fOpen_;
41 }
42 virtual SeekOffsetType GetWriteOffset () const override
43 {
44 // instead of tellg () - avoids issue with EOF where fail bit set???
45 Debug::AssertExternallySynchronizedMutex::ReadContext declareContext{fThisAssertExternallySynchronized_};
46 Require (IsOpenWrite ());
47 return fOriginalStreamRef_.rdbuf ()->pubseekoff (0, ios_base::cur, ios_base::out);
48 }
49 virtual SeekOffsetType SeekWrite (Whence whence, SignedSeekOffsetType offset) override
50 {
51 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
52 Require (IsOpenWrite ());
53 switch (whence) {
54 case eFromStart:
55 fOriginalStreamRef_.seekp (offset, ios::beg);
56 break;
57 case eFromCurrent:
58 fOriginalStreamRef_.seekp (offset, ios::cur);
59 break;
60 case eFromEnd:
61 fOriginalStreamRef_.seekp (offset, ios::end);
62 break;
63 }
64 return fOriginalStreamRef_.tellp ();
65 }
66 virtual void Write (span<const ELEMENT_TYPE> elts) override
67 {
68 Require (not elts.empty ());
69 Require (IsOpenWrite ());
70 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
71
72 using StreamElementType = BASIC_OSTREAM_ELEMENT_TYPE;
73 fOriginalStreamRef_.write (reinterpret_cast<const StreamElementType*> (elts.data ()), elts.size ());
74 if (fOriginalStreamRef_.fail ()) [[unlikely]] {
75 static const Execution::RuntimeErrorException kException_{"Failed to write from ostream"sv};
76 Execution::Throw (kException_);
77 }
78 }
79 virtual void Flush () override
80 {
81 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
82 Require (IsOpenWrite ());
83 fOriginalStreamRef_.flush ();
84 if (fOriginalStreamRef_.fail ()) [[unlikely]] {
85 static const Execution::RuntimeErrorException kException_{"Failed to flush ostream"sv};
86 Execution::Throw (kException_);
87 }
88 }
89
90 private:
91 basic_ostream<BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>& fOriginalStreamRef_;
92 [[no_unique_address]] Debug::AssertExternallySynchronizedMutex fThisAssertExternallySynchronized_;
93 };
94 }
95
96 /*
97 ********************************************************************************
98 **************** OutputStreamFromStdOStream<ELEMENT_TYPE>::New *****************
99 ********************************************************************************
100 */
101 template <typename ELEMENT_TYPE, typename BASIC_OSTREAM_ELEMENT_TYPE, typename BASIC_OSTREAM_TRAITS_TYPE>
102 inline auto New (basic_ostream<BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>& originalStream) -> Ptr<ELEMENT_TYPE>
103 requires ((same_as<ELEMENT_TYPE, byte> and same_as<BASIC_OSTREAM_ELEMENT_TYPE, char>) or
104 (same_as<ELEMENT_TYPE, Characters::Character> and same_as<BASIC_OSTREAM_ELEMENT_TYPE, wchar_t>))
105 {
106 return Ptr<ELEMENT_TYPE>{Memory::MakeSharedPtr<Private_::Rep_<ELEMENT_TYPE, BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>> (originalStream)};
107 }
108 template <typename ELEMENT_TYPE, typename BASIC_OSTREAM_ELEMENT_TYPE, typename BASIC_OSTREAM_TRAITS_TYPE>
109 inline auto New (Execution::InternallySynchronized internallySynchronized,
110 basic_ostream<BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>& originalStream) -> Ptr<ELEMENT_TYPE>
111 requires ((same_as<ELEMENT_TYPE, byte> and same_as<BASIC_OSTREAM_ELEMENT_TYPE, char>) or
112 (same_as<ELEMENT_TYPE, Characters::Character> and same_as<BASIC_OSTREAM_ELEMENT_TYPE, wchar_t>))
113 {
114 switch (internallySynchronized) {
115 case Execution::eInternallySynchronized:
116 return InternallySynchronizedOutputStream::New<Private_::Rep_<ELEMENT_TYPE, BASIC_OSTREAM_ELEMENT_TYPE, BASIC_OSTREAM_TRAITS_TYPE>> (
117 {}, originalStream);
118 case Execution::eNotKnownInternallySynchronized:
119 return New<ELEMENT_TYPE> (originalStream);
120 default:
122 return nullptr;
123 }
124 }
125
126}
#define RequireNotReached()
Definition Assertions.h:385
shared_lock< const AssertExternallySynchronizedMutex > ReadContext
Instantiate AssertExternallySynchronizedMutex::ReadContext to designate an area of code where protect...
unique_lock< AssertExternallySynchronizedMutex > WriteContext
Instantiate AssertExternallySynchronizedMutex::WriteContext to designate an area of code where protec...
A Streams::Ptr<ELEMENT_TYPE> is a smart-pointer to a stream of elements of type T.
Definition Stream.h:170
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Definition Throw.inl:43