PoDoFo  1.0.0-dev
StreamDevice.h
1 
7 #ifndef AUX_STREAM_DEVICE_H
8 #define AUX_STREAM_DEVICE_H
9 
10 #include <cstring>
11 #include <ostream>
12 #include <fstream>
13 #include <cstdio>
14 #include <vector>
15 
16 #include "basetypes.h"
17 
18 #include "InputDevice.h"
19 #include "OutputDevice.h"
20 
21 namespace PoDoFo {
22 
30 class PODOFO_API StreamDevice : public InputStreamDevice, public OutputStreamDevice
31 {
32 protected:
33  StreamDevice(DeviceAccess access);
34 
35 protected:
36  static size_t SeekPosition(size_t curpos, size_t devlen, ssize_t offset, SeekDirection direction);
37 };
38 
39 class PODOFO_API StandardStreamDevice : public StreamDevice
40 {
41 public:
46  StandardStreamDevice(std::ostream& stream);
47 
48  StandardStreamDevice(std::istream& stream);
49 
54  StandardStreamDevice(std::iostream& stream);
55 
56  ~StandardStreamDevice();
57 
58 public:
59  size_t GetLength() const override;
60 
61  size_t GetPosition() const override;
62 
63  bool CanSeek() const override;
64 
65  bool Eof() const override;
66 
67 protected:
68  StandardStreamDevice(DeviceAccess access, std::ios& stream, bool streamOwned);
69  void writeBuffer(const char* buffer, size_t size) override;
70  void flush() override;
71  size_t readBuffer(char* buffer, size_t size, bool& eof) override;
72  bool readChar(char& ch) override;
73  bool peek(char& ch) const override;
74  void seek(ssize_t offset, SeekDirection direction) override;
75 
76  inline std::ios& GetStream() { return *m_Stream; }
77 
78 private:
79  StandardStreamDevice(DeviceAccess access, std::ios* stream, std::istream* istream, std::ostream* ostream, bool streamOwned);
80 
81 private:
82  std::ios* m_Stream;
83  std::istream* m_istream;
84  std::ostream* m_ostream;
85  bool m_StreamOwned;
86 };
87 
88 // These are the .NET System.IO file opening modes
89 // https://docs.microsoft.com/en-us/dotnet/api/system.io.filemode?view=net-6.0
90 enum class FileMode
91 {
92  CreateNew = 1,
93  Create,
94  Open,
95  OpenOrCreate,
96  Truncate,
97  Append,
98 };
99 
100 class PODOFO_API FileStreamDevice : public StreamDevice
101 {
102 public:
105  FileStreamDevice(const std::string_view & filepath);
106 
109  FileStreamDevice(const std::string_view & filepath, FileMode mode);
110 
113  FileStreamDevice(const std::string_view& filepath, FileMode mode,
114  DeviceAccess access);
115 
116  ~FileStreamDevice();
117 
118 public:
119  const std::string& GetFilepath() const { return m_Filepath; }
120 
121  size_t GetLength() const override;
122 
123  size_t GetPosition() const override;
124 
125  bool CanSeek() const override;
126 
127  bool Eof() const override;
128 
129 protected:
130  void writeBuffer(const char* buffer, size_t size) override;
131  void flush() override;
132  size_t readBuffer(char* buffer, size_t size, bool& eof) override;
133  bool readChar(char& ch) override;
134  bool peek(char& ch) const override;
135  void seek(ssize_t offset, SeekDirection direction) override;
136  void close() override;
137 
138 private:
139  FILE* m_file;
140  std::string m_Filepath;
141 };
142 
143 template <typename TContainer>
144 class ContainerStreamDevice : public StreamDevice
145 {
146 public:
147  ContainerStreamDevice(TContainer& container,
148  DeviceAccess access, bool ate) :
149  StreamDevice(access),
150  m_container(&container),
151  m_Position(ate ? container.size() : 0) { }
152 
156  ContainerStreamDevice(const TContainer& container) :
157  ContainerStreamDevice(const_cast<TContainer&>(container), DeviceAccess::Read, false) { }
158 
162  ContainerStreamDevice(TContainer& container) :
163  ContainerStreamDevice(container, DeviceAccess::ReadWrite, true) { }
164 
165 public:
166  size_t GetLength() const override { return m_container->size(); }
167 
168  size_t GetPosition() const override { return m_Position; }
169 
170  bool CanSeek() const override { return true; }
171 
172  bool Eof() const override { return m_Position == m_container->size(); }
173 
174 protected:
175  void writeBuffer(const char* buffer, size_t size) override
176  {
177  if (m_Position + size > m_container->size())
178  m_container->resize(m_Position + size);
179 
180  std::memcpy(m_container->data() + m_Position, buffer, size);
181  m_Position += size;
182  }
183 
184  size_t readBuffer(char* buffer, size_t size, bool& eof) override
185  {
186  size_t readCount = std::min(size, m_container->size() - m_Position);
187  std::memcpy(buffer, m_container->data() + m_Position, readCount);
188  m_Position += readCount;
189  eof = m_Position == m_container->size();
190  return readCount;
191  }
192 
193  bool readChar(char& ch) override
194  {
195  if (m_Position == m_container->size())
196  {
197  ch = '\0';
198  return false;
199  }
200 
201  ch = m_container->data()[m_Position];
202  m_Position++;
203  return true;
204  }
205 
206  bool peek(char& ch) const override
207  {
208  if (m_Position == m_container->size())
209  {
210  ch = '\0';
211  return false;
212  }
213 
214  ch = m_container->data()[m_Position];
215  return true;
216  }
217 
218  void seek(ssize_t offset, SeekDirection direction) override
219  {
220  m_Position = SeekPosition(m_Position, m_container->size(), offset, direction);
221  }
222 
223 private:
224  TContainer* m_container;
225  size_t m_Position;
226 };
227 
228 class PODOFO_API SpanStreamDevice : public StreamDevice
229 {
230 public:
234  SpanStreamDevice(const char* buffer, size_t size);
235  SpanStreamDevice(const bufferview& buffer);
236  SpanStreamDevice(const std::string_view& view);
237  SpanStreamDevice(const std::string& str);
238  SpanStreamDevice(std::string& str,
239  DeviceAccess access = DeviceAccess::ReadWrite);
240  SpanStreamDevice(const char* str);
241  SpanStreamDevice(char* buffer, size_t size,
242  DeviceAccess access = DeviceAccess::ReadWrite);
243  SpanStreamDevice(const bufferspan& span,
244  DeviceAccess access = DeviceAccess::ReadWrite);
245 
246 public:
247  size_t GetLength() const override;
248 
249  size_t GetPosition() const override;
250 
251  bool Eof() const override;
252 
253  bool CanSeek() const override;
254 
255 protected:
256  void writeBuffer(const char* buffer, size_t size) override;
257  size_t readBuffer(char* buffer, size_t size, bool& eof) override;
258  bool readChar(char& ch) override;
259  bool peek(char& ch) const override;
260  void seek(ssize_t offset, SeekDirection direction) override;
261 
262 private:
263  SpanStreamDevice(std::nullptr_t) = delete;
264 
265 private:
266  char* m_buffer;
267  size_t m_Length;
268  size_t m_Position;
269 };
270 
274 class PODOFO_API NullStreamDevice final : public StreamDevice
275 {
276 public:
278 
279 public:
280  size_t GetLength() const override;
281 
282  size_t GetPosition() const override;
283 
284  bool Eof() const override;
285 
286 protected:
287  void writeBuffer(const char* buffer, size_t size) override;
288  size_t readBuffer(char* buffer, size_t size, bool& eof) override;
289  bool readChar(char& ch) override;
290  bool peek(char& ch) const override;
291  void seek(ssize_t offset, SeekDirection direction) override;
292 
293 private:
294  size_t m_Length;
295  size_t m_Position;
296 };
297 
298 using VectorStreamDevice = ContainerStreamDevice<std::vector<char>>;
299 using StringStreamDevice = ContainerStreamDevice<std::string>;
300 using BufferStreamDevice = ContainerStreamDevice<charbuff>;
301 
302 }
303 
304 #endif // AUX_STREAM_DEVICE_H
This class represents an input device It optionally supports peeking.
Definition: InputDevice.h:22
void Read(char *buffer, size_t size)
Read data from the device.
Definition: InputStream.cpp:21
An StreamDevice device that does nothing.
Definition: StreamDevice.h:275
This class provides an output device which operates either on a file or on a buffer in memory.
Definition: StreamDevice.h:31
SPDX-FileCopyrightText: (C) 2022 Francesco Pretto ceztko@gmail.com SPDX-License-Identifier: LGPL-2....
Definition: basetypes.h:16
mspan< char > bufferspan
Convenient writable char buffer span.
Definition: basetypes.h:23
FileMode
Definition: StreamDevice.h:91
@ CreateNew
Create a new file (throw if existing) for writing/reading.
@ OpenOrCreate
Open an existing file or create a new one for writing/reading.
@ Append
Open an existing file and seek to the end for writing.
@ Create
Create a new file or truncate existing one for writing/reading.
@ Truncate
Truncate an existing file for writing/reading.
@ Open
Open an existing file for reading and/or writing.
cspan< char > bufferview
Convenient read-only char buffer span.
Definition: basetypes.h:19