Stroika Library 3.0d23x
 
Loading...
Searching...
No Matches
InputStreamFromStdIStream.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
6#include "Stroika/Foundation/Execution/Exceptions.h"
7#include "Stroika/Foundation/Execution/Throw.h"
9
10namespace Stroika::Foundation::Streams::iostream::InputStreamFromStdIStream {
11
12 namespace Private_ {
13 template <typename ELEMENT_TYPE, typename BASIC_ISTREAM_ELEMENT_TYPE, typename BASIC_ISTREAM_TRAITS_TYPE>
14 class Rep_ : public InputStream::IRep<ELEMENT_TYPE> {
15 private:
16 bool fOpen_{true};
17
18 public:
19 Rep_ (basic_istream<BASIC_ISTREAM_ELEMENT_TYPE, BASIC_ISTREAM_TRAITS_TYPE>& originalStream)
20 : Rep_{originalStream, eSeekable}
21 {
22 }
23 Rep_ (basic_istream<BASIC_ISTREAM_ELEMENT_TYPE, BASIC_ISTREAM_TRAITS_TYPE>& originalStream, SeekableFlag seekable)
24 : fOriginalStreamRef_{originalStream}
25 , fSeekable_{seekable}
26 {
27 }
28
29 protected:
30 virtual bool IsSeekable () const override
31 {
32 return fSeekable_ == eSeekable;
33 }
34 virtual void CloseRead () override
35 {
36 fOpen_ = false;
37 Ensure (not IsOpenRead ());
38 }
39 virtual bool IsOpenRead () const override
40 {
41 return fOpen_;
42 }
43 virtual optional<size_t> AvailableToRead () override
44 {
45 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
46 streamsize sz = fOriginalStreamRef_.rdbuf ()->in_avail ();
47 // http://en.cppreference.com/w/cpp/io/basic_streambuf/in_avail
48 if (sz == 0) {
49 return nullopt;
50 }
51 else if (sz == -1) {
52 return 0;
53 }
54 return static_cast<size_t> (sz);
55 }
56 virtual optional<SeekOffsetType> RemainingLength () override
57 {
58 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
59 Require (IsOpenRead ());
61 return nullopt; // pretty easy, but @todo
62 }
63 virtual optional<span<ELEMENT_TYPE>> Read (span<ELEMENT_TYPE> intoBuffer, NoDataAvailableHandling blockFlag) override
64 {
65 Require (not intoBuffer.empty ());
66 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
67 Require (IsOpenRead ());
68 if (fOriginalStreamRef_.eof ()) {
69 return span<ELEMENT_TYPE>{};
70 }
71 if (blockFlag == NoDataAvailableHandling::eDontBlock and AvailableToRead () == nullopt) {
72 return nullopt;
73 }
74 size_t maxToRead = intoBuffer.size ();
75 fOriginalStreamRef_.clear (); // clear any failures before read - it will report if a failure found
76 fOriginalStreamRef_.read (reinterpret_cast<BASIC_ISTREAM_ELEMENT_TYPE*> (intoBuffer.data ()), maxToRead);
77 size_t n = static_cast<size_t> (fOriginalStreamRef_.gcount ()); // cast safe cuz amount asked to read was also size_t
78 Assert (n <= maxToRead);
79 // apparently based on http://www.cplusplus.com/reference/iostream/istream/read/ EOF sets the EOF bit AND the fail bit
80 if (not fOriginalStreamRef_.eof () and fOriginalStreamRef_.fail ()) [[unlikely]] {
81 static const Execution::RuntimeErrorException kException_{"Failed to read from istream"sv};
82 Execution::Throw (kException_);
83 }
84 return intoBuffer.subspan (0, n);
85 }
86 virtual SeekOffsetType GetReadOffset () const override
87 {
88 // instead of tellg () - avoids issue with EOF where fail bit set???
89 Debug::AssertExternallySynchronizedMutex::ReadContext declareContext{fThisAssertExternallySynchronized_};
90 Require (IsOpenRead ());
91 return fOriginalStreamRef_.rdbuf ()->pubseekoff (0, ios_base::cur, ios_base::in);
92 }
93 virtual SeekOffsetType SeekRead (Whence whence, SignedSeekOffsetType offset) override
94 {
95 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
96 Require (IsOpenRead ());
97 fOriginalStreamRef_.clear (); // in case we hit eof (causing fail) - eof gets cleared by seeking, but not failbit - it appears...--LGP 2024-02-11
98 switch (whence) {
99 case eFromStart:
100 fOriginalStreamRef_.seekg (offset, ios::beg);
101 break;
102 case eFromCurrent:
103 fOriginalStreamRef_.seekg (offset, ios::cur);
104 break;
105 case eFromEnd:
106 fOriginalStreamRef_.seekg (offset, ios::end);
107 break;
108 }
109 // instead of tellg () - avoids issue with EOF where fail bit set???
110 return fOriginalStreamRef_.rdbuf ()->pubseekoff (0, ios_base::cur, ios_base::in);
111 }
112
113 private:
114 basic_istream<BASIC_ISTREAM_ELEMENT_TYPE, BASIC_ISTREAM_TRAITS_TYPE>& fOriginalStreamRef_;
115 SeekableFlag fSeekable_;
116 [[no_unique_address]] Debug::AssertExternallySynchronizedMutex fThisAssertExternallySynchronized_;
117 };
118 }
119
120 /*
121 ********************************************************************************
122 ***************** InputStreamFromStdIStream<ELEMENT_TYPE>::New *****************
123 ********************************************************************************
124 */
125 template <typename ELEMENT_TYPE, typename BASIC_ISTREAM_ELEMENT_TYPE, typename BASIC_ISTREAM_TRAITS_TYPE>
126 inline auto New (basic_istream<BASIC_ISTREAM_ELEMENT_TYPE, BASIC_ISTREAM_TRAITS_TYPE>& originalStream) -> Ptr<ELEMENT_TYPE>
127 requires ((same_as<ELEMENT_TYPE, byte> and same_as<BASIC_ISTREAM_ELEMENT_TYPE, char>) or
128 (same_as<ELEMENT_TYPE, Characters::Character> and same_as<BASIC_ISTREAM_ELEMENT_TYPE, wchar_t>))
129 {
130 return Ptr<ELEMENT_TYPE>{Memory::MakeSharedPtr<Private_::Rep_<ELEMENT_TYPE, BASIC_ISTREAM_ELEMENT_TYPE, BASIC_ISTREAM_TRAITS_TYPE>> (originalStream)};
131 }
132 template <typename ELEMENT_TYPE, typename BASIC_ISTREAM_ELEMENT_TYPE, typename BASIC_ISTREAM_TRAITS_TYPE>
133 inline auto New (basic_istream<BASIC_ISTREAM_ELEMENT_TYPE, BASIC_ISTREAM_TRAITS_TYPE>& originalStream, SeekableFlag seekable) -> Ptr<ELEMENT_TYPE>
134 requires ((same_as<ELEMENT_TYPE, byte> and same_as<BASIC_ISTREAM_ELEMENT_TYPE, char>) or
135 (same_as<ELEMENT_TYPE, Characters::Character> and same_as<BASIC_ISTREAM_ELEMENT_TYPE, wchar_t>))
136 {
137 return Ptr<ELEMENT_TYPE>{Memory::MakeSharedPtr<Private_::Rep_<ELEMENT_TYPE, BASIC_ISTREAM_ELEMENT_TYPE, BASIC_ISTREAM_TRAITS_TYPE>> (
138 originalStream, seekable)};
139 }
140 template <typename ELEMENT_TYPE, typename BASIC_ISTREAM_ELEMENT_TYPE, typename BASIC_ISTREAM_TRAITS_TYPE>
141 inline auto New (Execution::InternallySynchronized internallySynchronized,
142 basic_istream<BASIC_ISTREAM_ELEMENT_TYPE, BASIC_ISTREAM_TRAITS_TYPE>& originalStream) -> Ptr<ELEMENT_TYPE>
143 requires ((same_as<ELEMENT_TYPE, byte> and same_as<BASIC_ISTREAM_ELEMENT_TYPE, char>) or
144 (same_as<ELEMENT_TYPE, Characters::Character> and same_as<BASIC_ISTREAM_ELEMENT_TYPE, wchar_t>))
145 {
146 switch (internallySynchronized) {
147 case Execution::eInternallySynchronized:
148 return InternallySynchronizedInputStream::New<Private_::Rep_<ELEMENT_TYPE, BASIC_ISTREAM_ELEMENT_TYPE, BASIC_ISTREAM_TRAITS_TYPE>> (
149 {}, originalStream);
150 case Execution::eNotKnownInternallySynchronized:
151 return New<ELEMENT_TYPE> (originalStream);
152 default:
154 return nullptr;
155 }
156 }
157 template <typename ELEMENT_TYPE, typename BASIC_ISTREAM_ELEMENT_TYPE, typename BASIC_ISTREAM_TRAITS_TYPE>
158 inline auto New (Execution::InternallySynchronized internallySynchronized,
159 basic_istream<BASIC_ISTREAM_ELEMENT_TYPE, BASIC_ISTREAM_TRAITS_TYPE>& originalStream, SeekableFlag seekable) -> Ptr<ELEMENT_TYPE>
160 requires ((same_as<ELEMENT_TYPE, byte> and same_as<BASIC_ISTREAM_ELEMENT_TYPE, char>) or
161 (same_as<ELEMENT_TYPE, Characters::Character> and same_as<BASIC_ISTREAM_ELEMENT_TYPE, wchar_t>))
162 {
163 switch (internallySynchronized) {
164 case Execution::eInternallySynchronized:
165 return InternallySynchronizedInputStream::New<Private_::Rep_<ELEMENT_TYPE, BASIC_ISTREAM_ELEMENT_TYPE, BASIC_ISTREAM_TRAITS_TYPE>> (
166 {}, originalStream);
167 case Execution::eNotKnownInternallySynchronized:
168 return New<ELEMENT_TYPE> (originalStream, seekable);
169 default:
171 return nullptr;
172 }
173 }
174
175}
#define AssertNotImplemented()
Definition Assertions.h:401
#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...
InputStream<>::Ptr is Smart pointer (with abstract Rep) class defining the interface to reading from ...
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