Stroika Library 3.0d23x
 
Loading...
Searching...
No Matches
LoggingInputOutputStream.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
5#include "Stroika/Foundation/Streams/InternallySynchronizedInputOutputStream.h"
6
7namespace Stroika::Foundation::Streams::LoggingInputOutputStream {
8
9 namespace Private_ {
10
11 template <typename ELEMENT_TYPE>
12 class Rep_ final : public InputOutputStream::IRep<ELEMENT_TYPE> {
13 public:
14 Rep_ (const typename InputOutputStream::Ptr<ELEMENT_TYPE>& realStream, const typename OutputStream::Ptr<ELEMENT_TYPE>& logInput,
15 const typename OutputStream::Ptr<ELEMENT_TYPE>& logOutput)
16 : fRealStream_{realStream}
17 , fLogInput_{logInput}
18 , fLogOutput_{logOutput}
19 {
20 Require (not realStream.IsSeekable () or (logInput.IsSeekable () and logOutput.IsSeekable ())); // since may need to delegate seeks
21 }
22
23 // Streams::_IRep<ELEMENT_TYPE>
24 public:
25 virtual bool IsSeekable () const override
26 {
27 return fRealStream_.IsSeekable ();
28 }
29
30 // InputStream::IRep
31 public:
32 virtual void CloseRead () override
33 {
34 if (IsOpenRead ()) {
35 fRealStream_.CloseRead ();
36 fLogInput_.Close ();
37 }
38 Ensure (not IsOpenRead ());
39 }
40 virtual bool IsOpenRead () const override
41 {
42 return fRealStream_.IsOpenRead ();
43 }
44 virtual SeekOffsetType GetReadOffset () const override
45 {
46 return fRealStream_.GetReadOffset ();
47 }
48 virtual SeekOffsetType SeekRead (Whence whence, SignedSeekOffsetType offset) override
49 {
50 SeekOffsetType result = fRealStream_.SeekRead (whence, offset);
51 // @todo - perhaps should seek the fLogInput_ stream? But not clear by how much
52 // DEFINITELY should or read logging will produce weird ansers - and least write SOME SORT OF NOTE that a seek happened! (like seeked from pos X to Y in stream)
53 return result;
54 }
55 virtual optional<size_t> AvailableToRead () override
56 {
57 return fRealStream_.AvailableToRead ();
58 }
59 virtual optional<span<ELEMENT_TYPE>> Read (span<ELEMENT_TYPE> intoBuffer, NoDataAvailableHandling blockFlag) override
60 {
61 optional<span<ELEMENT_TYPE>> result = fRealStream_.Read (intoBuffer, blockFlag);
62 if (result) {
63 fLogInput_.Write (*result);
64 }
65 return result;
66 }
67
68 // OutputStream::IRep
69 public:
70 virtual void CloseWrite () override
71 {
72 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
73 if (IsOpenWrite ()) {
74 fRealStream_.CloseWrite ();
75 }
76 Assert (fRealStream_ == nullptr);
77 Ensure (not IsOpenWrite ());
78 }
79 virtual bool IsOpenWrite () const override
80 {
81 Debug::AssertExternallySynchronizedMutex::ReadContext declareContext{fThisAssertExternallySynchronized_};
82 return fRealStream_.IsOpenWrite ();
83 }
84 virtual SeekOffsetType GetWriteOffset () const override
85 {
86 Debug::AssertExternallySynchronizedMutex::ReadContext declareContext{fThisAssertExternallySynchronized_};
87 return fRealStream_.GetWriteOffset ();
88 }
89 virtual SeekOffsetType SeekWrite (Whence whence, SignedSeekOffsetType offset) override
90 {
91 Require (IsOpenWrite ());
92 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
93 SeekOffsetType o1 = fRealStream_.SeekWrite (whence, offset);
94 [[maybe_unused]] SeekOffsetType o2 = fLogOutput_.Seek (whence, offset); // @todo - not sure if/how mcuh to see - since not totally in sync
95 return o1;
96 }
97 virtual void Flush () override
98 {
99 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
100 Require (IsOpenWrite ());
101 fRealStream_.Flush ();
102 }
103 // pointer must refer to valid memory at least bufSize long, and cannot be nullptr. BufSize must always be >= 1.
104 // Writes always succeed fully or throw.
105 virtual void Write (span<const ELEMENT_TYPE> elts) override
106 {
107 Require (not elts.empty ()); // for OutputStream<byte> - this function requires non-empty write
108 Require (IsOpenWrite ());
109 Debug::AssertExternallySynchronizedMutex::WriteContext declareContext{fThisAssertExternallySynchronized_};
110 fRealStream_.Write (elts);
111 fLogOutput_.Write (elts);
112 }
113
114 private:
115 typename InputOutputStream::Ptr<ELEMENT_TYPE> fRealStream_;
116 typename OutputStream::Ptr<ELEMENT_TYPE> fLogInput_;
117 typename OutputStream::Ptr<ELEMENT_TYPE> fLogOutput_;
118 [[no_unique_address]] Debug::AssertExternallySynchronizedMutex fThisAssertExternallySynchronized_;
119 };
120 }
121
122 /*
123 ********************************************************************************
124 **************** Streams::LoggingInputOutputStream::Rep_ ***********************
125 ********************************************************************************
126 */
127 template <typename ELEMENT_TYPE>
128 inline Ptr<ELEMENT_TYPE> New (const typename InputOutputStream::Ptr<ELEMENT_TYPE>& realStream,
129 const typename OutputStream::Ptr<ELEMENT_TYPE>& logInput, const typename OutputStream::Ptr<ELEMENT_TYPE>& logOutput)
130 {
131 return _mkPtr (Memory::MakeSharedPtr<Private_::Rep_> (realStream, logInput, logOutput));
132 }
133 template <typename ELEMENT_TYPE>
134 inline Ptr<ELEMENT_TYPE> New (Execution::InternallySynchronized internallySynchronized, const typename InputOutputStream::Ptr<ELEMENT_TYPE>& realStream,
135 const typename OutputStream::Ptr<ELEMENT_TYPE>& logInput, const typename OutputStream::Ptr<ELEMENT_TYPE>& logOutput)
136 {
137 switch (internallySynchronized) {
138 case Execution::eInternallySynchronized:
139 return InternallySynchronizedInputOutputStream::New<Private_::Rep_> ({}, realStream, logInput, logOutput);
140 case Execution::eNotKnownInternallySynchronized:
141 return New<ELEMENT_TYPE> (realStream, logInput, logOutput);
142 default:
144 return nullptr;
145 }
146 }
147
148}
#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...
InputOutputStream is single stream object that acts much as a InputStream::Ptr and an OutputStream::P...
OutputStream<>::Ptr is Smart pointer to a stream-based sink of data.
A Streams::Ptr<ELEMENT_TYPE> is a smart-pointer to a stream of elements of type T.
Definition Stream.h:170