CppCommon  1.0.4.1
C++ Common Library
stream.cpp
Go to the documentation of this file.
1 
9 #include "system/stream.h"
10 
11 #include "errors/fatal.h"
13 
14 #include <cassert>
15 
16 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
17 #include <stdio.h>
18 #elif defined(_WIN32) || defined(_WIN64)
19 #include <windows.h>
20 #endif
21 
22 namespace CppCommon {
23 
25 
26 class StdInput::Impl
27 {
28 public:
29  Impl()
30  {
31 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
32  _stream = stdin;
33  if (_stream == nullptr)
34  throwex SystemException("Failed to get a valid standard input stream!");
35 #elif defined(_WIN32) || defined(_WIN64)
36  _stream = GetStdHandle(STD_INPUT_HANDLE);
37  if (_stream == INVALID_HANDLE_VALUE)
38  throwex SystemException("Failed to get a valid standard input stream!");
39 #endif
40  }
41 
42  ~Impl() = default;
43 
44  void* stream() const noexcept
45  {
46  return _stream;
47  }
48 
49  bool IsValid() const noexcept
50  {
51 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
52  return (_stream != nullptr);
53 #elif defined(_WIN32) || defined(_WIN64)
54  return (_stream != INVALID_HANDLE_VALUE);
55 #endif
56  }
57 
58  size_t Read(void* buffer, size_t size)
59  {
60  if ((buffer == nullptr) || (size == 0))
61  return 0;
62 
63  assert(IsValid() && "Standard input stream is not valid!");
64  if (!IsValid())
65  throwex SystemException("Cannot read from the invalid standard input stream!");
66 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
67  size_t result = fread(buffer, 1, size, _stream);
68  if (ferror(_stream) != 0)
69  throwex SystemException("Cannot read from the standard input stream!");
70  return result;
71 #elif defined(_WIN32) || defined(_WIN64)
72  DWORD result;
73  if (!ReadFile(_stream, buffer, (DWORD)size, &result, nullptr))
74  throwex SystemException("Cannot read from the standard input stream!");
75  return (size_t)result;
76 #endif
77  }
78 
79 private:
80 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
81  FILE* _stream;
82 #elif defined(_WIN32) || defined(_WIN64)
83  HANDLE _stream;
84 #endif
85 };
86 
87 class StdOutput::Impl
88 {
89 public:
90  Impl()
91  {
92 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
93  _stream = stdout;
94  if (_stream == nullptr)
95  throwex SystemException("Failed to get a valid standard output stream!");
96 #elif defined(_WIN32) || defined(_WIN64)
97  _stream = GetStdHandle(STD_OUTPUT_HANDLE);
98  if (_stream == INVALID_HANDLE_VALUE)
99  throwex SystemException("Failed to get a valid standard output stream!");
100 #endif
101  }
102 
103  ~Impl() = default;
104 
105  void* stream() const noexcept
106  {
107  return _stream;
108  }
109 
110  bool IsValid() const noexcept
111  {
112 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
113  return (_stream != nullptr);
114 #elif defined(_WIN32) || defined(_WIN64)
115  return (_stream != INVALID_HANDLE_VALUE);
116 #endif
117  }
118 
119  size_t Write(const void* buffer, size_t size)
120  {
121  if ((buffer == nullptr) || (size == 0))
122  return 0;
123 
124  assert(IsValid() && "Standard output stream is not valid!");
125  if (!IsValid())
126  throwex SystemException("Cannot write into the invalid standard output stream!");
127 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
128  size_t result = fwrite(buffer, 1, size, _stream);
129  if (ferror(_stream) != 0)
130  throwex SystemException("Cannot write into the standard output stream!");
131  return result;
132 #elif defined(_WIN32) || defined(_WIN64)
133  DWORD result;
134  if (!WriteFile(_stream, buffer, (DWORD)size, &result, nullptr))
135  throwex SystemException("Cannot write into the standard output stream!");
136  return (size_t)result;
137 #endif
138  }
139 
140  void Flush()
141  {
142 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
143  int result = fflush(_stream);
144  if (result != 0)
145  throwex SystemException("Cannot flush the standard output stream!");
146 #elif defined(_WIN32) || defined(_WIN64)
147  if (!FlushFileBuffers(_stream))
148  throwex SystemException("Cannot flush the standard output stream!");
149 #endif
150  }
151 
152 private:
153 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
154  FILE* _stream;
155 #elif defined(_WIN32) || defined(_WIN64)
156  HANDLE _stream;
157 #endif
158 };
159 
160 class StdError::Impl
161 {
162 public:
163  Impl()
164  {
165 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
166  _stream = stderr;
167  if (_stream == nullptr)
168  throwex SystemException("Failed to get a valid standard error stream!");
169 #elif defined(_WIN32) || defined(_WIN64)
170  _stream = GetStdHandle(STD_ERROR_HANDLE);
171  if (_stream == INVALID_HANDLE_VALUE)
172  throwex SystemException("Failed to get a valid standard error stream!");
173 #endif
174  }
175 
176  ~Impl() = default;
177 
178  void* stream() const noexcept
179  {
180  return _stream;
181  }
182 
183  bool IsValid() const noexcept
184  {
185 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
186  return (_stream != nullptr);
187 #elif defined(_WIN32) || defined(_WIN64)
188  return (_stream != INVALID_HANDLE_VALUE);
189 #endif
190  }
191 
192  size_t Write(const void* buffer, size_t size)
193  {
194  if ((buffer == nullptr) || (size == 0))
195  return 0;
196 
197  assert(IsValid() && "Standard error stream is not valid!");
198  if (!IsValid())
199  throwex SystemException("Cannot write into the invalid standard error stream!");
200 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
201  size_t result = fwrite(buffer, 1, size, _stream);
202  if (ferror(_stream) != 0)
203  throwex SystemException("Cannot write into the standard error stream!");
204  return result;
205 #elif defined(_WIN32) || defined(_WIN64)
206  DWORD result;
207  if (!WriteFile(_stream, buffer, (DWORD)size, &result, nullptr))
208  throwex SystemException("Cannot write into the standard error stream!");
209  return (size_t)result;
210 #endif
211  }
212 
213  void Flush()
214  {
215 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
216  int result = fflush(_stream);
217  if (result != 0)
218  throwex SystemException("Cannot flush the standard error stream!");
219 #elif defined(_WIN32) || defined(_WIN64)
220  if (!FlushFileBuffers(_stream))
221  throwex SystemException("Cannot flush the standard error stream!");
222 #endif
223  }
224 
225 private:
226 #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
227  FILE* _stream;
228 #elif defined(_WIN32) || defined(_WIN64)
229  HANDLE _stream;
230 #endif
231 };
232 
234 
236 {
237  // Check implementation storage parameters
238  [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
239  static_assert((StorageSize >= sizeof(Impl)), "StdInput::StorageSize must be increased!");
240  static_assert(((StorageAlign % alignof(Impl)) == 0), "StdInput::StorageAlign must be adjusted!");
241 
242  // Create the implementation instance
243  new(&_storage)Impl();
244 }
245 
247 {
248  // Delete the implementation instance
249  reinterpret_cast<Impl*>(&_storage)->~Impl();
250 }
251 
252 void* StdInput::stream() const noexcept { return impl().stream(); }
253 bool StdInput::IsValid() const noexcept { return impl().IsValid(); }
254 size_t StdInput::Read(void* buffer, size_t size) { return impl().Read(buffer, size); }
255 
256 void StdInput::swap(StdInput& stream) noexcept
257 {
258  using std::swap;
259  swap(_storage, stream._storage);
260 }
261 
263 {
264  // Check implementation storage parameters
265  [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
266  static_assert((StorageSize >= sizeof(Impl)), "StdOutput::StorageSize must be increased!");
267  static_assert(((StorageAlign % alignof(Impl)) == 0), "StdOutput::StorageAlign must be adjusted!");
268 
269  // Create the implementation instance
270  new(&_storage)Impl();
271 }
272 
274 {
275  // Delete the implementation instance
276  reinterpret_cast<Impl*>(&_storage)->~Impl();
277 }
278 
279 void* StdOutput::stream() const noexcept { return impl().stream(); }
280 bool StdOutput::IsValid() const noexcept { return impl().IsValid(); }
281 size_t StdOutput::Write(const void* buffer, size_t size) { return impl().Write(buffer, size); }
282 void StdOutput::Flush() { return impl().Flush(); }
283 
284 void StdOutput::swap(StdOutput& stream) noexcept
285 {
286  using std::swap;
287  swap(_storage, stream._storage);
288 }
289 
291 {
292  // Check implementation storage parameters
293  [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
294  static_assert((StorageSize >= sizeof(Impl)), "StdError::StorageSize must be increased!");
295  static_assert(((StorageAlign % alignof(Impl)) == 0), "StdError::StorageAlign must be adjusted!");
296 
297  // Create the implementation instance
298  new(&_storage)Impl();
299 }
300 
302 {
303  // Delete the implementation instance
304  reinterpret_cast<Impl*>(&_storage)->~Impl();
305 }
306 
307 void* StdError::stream() const noexcept { return impl().stream(); }
308 bool StdError::IsValid() const noexcept { return impl().IsValid(); }
309 size_t StdError::Write(const void* buffer, size_t size) { return impl().Write(buffer, size); }
310 void StdError::Flush() { return impl().Flush(); }
311 
312 void StdError::swap(StdError& stream) noexcept
313 {
314  using std::swap;
315  swap(_storage, stream._storage);
316 }
317 
318 } // namespace CppCommon
Standard error stream.
Definition: stream.h:128
void * stream() const noexcept
Get the native stream handler.
Definition: stream.cpp:307
virtual ~StdError()
Definition: stream.cpp:301
virtual size_t Write(const void *buffer, size_t size)=0
Write a byte buffer base method.
void Flush() override
Flush the stream.
Definition: stream.cpp:310
void swap(StdError &stream) noexcept
Swap two instances.
Definition: stream.cpp:312
bool IsValid() const noexcept
Is stream valid?
Definition: stream.cpp:308
Standard input stream.
Definition: stream.h:25
bool IsValid() const noexcept
Is stream valid?
Definition: stream.cpp:253
virtual ~StdInput()
Definition: stream.cpp:246
void swap(StdInput &stream) noexcept
Swap two instances.
Definition: stream.cpp:256
void * stream() const noexcept
Get the native stream handler.
Definition: stream.cpp:252
size_t Read(void *buffer, size_t size) override
Read a bytes buffer from the stream.
Definition: stream.cpp:254
Standard output stream.
Definition: stream.h:76
void swap(StdOutput &stream) noexcept
Swap two instances.
Definition: stream.cpp:284
virtual ~StdOutput()
Definition: stream.cpp:273
virtual size_t Write(const void *buffer, size_t size)=0
Write a byte buffer base method.
void * stream() const noexcept
Get the native stream handler.
Definition: stream.cpp:279
void Flush() override
Flush the stream.
Definition: stream.cpp:282
bool IsValid() const noexcept
Is stream valid?
Definition: stream.cpp:280
#define throwex
Throw extended exception macro.
Definition: exceptions.h:23
Fatal abort execution definition.
C++ Common project definitions.
Definition: token_bucket.h:15
void swap(FileCache &cache1, FileCache &cache2) noexcept
Definition: filecache.inl:23
Standard input/output/error stream definition.
Aligned storage validator definition.