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