libkazv
file-desc.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of libkazv.
3  * SPDX-FileCopyrightText: 2021 Tusooa Zhu <tusooa@kazv.moe>
4  * SPDX-License-Identifier: AGPL-3.0-or-later
5  */
6 
7 
8 #pragma once
9 #include "libkazv-config.hpp"
10 
11 #include <optional>
12 #include <string>
13 #include <variant>
14 #include <functional>
15 #include <immer/box.hpp>
16 #include <immer/flex_vector.hpp>
17 
18 namespace Kazv
19 {
20  enum struct FileOpRetCode
21  {
22  Error,
23  Success,
24  Eof
25  };
26 
27  enum struct FileOpenMode
28  {
29  Read,
30  Write
31  };
32 
33  using FileContent = immer::flex_vector<char>;
34 
35  class FileStream
36  {
37  public:
38  using DataT = FileContent;
39 
51  template<class DeriveT>
52  FileStream(DeriveT &&o)
53  : m_d(std::make_unique<Model<std::decay_t<DeriveT>>>(
54  std::forward<DeriveT>(o))) {}
55 
64  template<class Callback>
65  void read(int maxSize, Callback readCallback) { m_d->read(maxSize, readCallback); }
66 
74  template<class Callback>
75  void write(DataT data, Callback writeCallback) { m_d->write(data, writeCallback); }
76 
77 
78  private:
79  struct Concept
80  {
81  virtual ~Concept() = default;
82  using ReadCallback = std::function<void(FileOpRetCode, DataT)>;
83  using WriteCallback = std::function<void(FileOpRetCode, int)>;
84 
85  virtual void read(int maxSize, ReadCallback callback) = 0;
86  virtual void write(DataT data, WriteCallback callback) = 0;
87  };
88 
89  template<class DeriveT>
90  struct Model : public Concept
91  {
92  explicit Model(const DeriveT &o) : obj(o) {}
93  explicit Model(DeriveT &&o) : obj(std::move(o)) {}
94  ~Model() override = default;
95  void read(int maxSize, ReadCallback callback) override {
96  return obj.read(maxSize, callback);
97  }
98  void write(DataT data, WriteCallback callback) override {
99  return obj.write(data, callback);
100  }
101 
102  DeriveT obj;
103  };
104 
105  std::unique_ptr<Concept> m_d;
106  };
107 
109  {
110  public:
128  template<class DeriveT>
129  FileProvider(DeriveT &&o)
130  : m_d(std::make_unique<Model<std::decay_t<DeriveT>>>(
131  std::forward<DeriveT>(o))) {}
132 
133  inline FileProvider(const FileProvider &that) : m_d(that.m_d->clone()) {}
134  inline FileProvider(FileProvider &&that) : m_d(std::move(that.m_d)) {}
135 
136  inline FileProvider &operator=(const FileProvider &that) {
137  m_d = that.m_d->clone();
138  return *this;
139  }
140 
142  m_d = std::move(that.m_d);
143  return *this;
144  }
145 
153  return m_d->getStream(mode);
154  }
155 
156  private:
157  struct Concept
158  {
159  virtual ~Concept() = default;
160  virtual std::unique_ptr<Concept> clone() const = 0;
161  virtual FileStream getStream(FileOpenMode mode) const = 0;
162  };
163 
164  template<class DeriveT>
165  struct Model : public Concept
166  {
167  explicit Model(const DeriveT &o) : obj(o) {}
168  explicit Model(DeriveT &&o) : obj(std::move(o)) {}
169  ~Model() override = default;
170  std::unique_ptr<Concept> clone() const override {
171  return std::make_unique<Model>(obj);
172  }
173  FileStream getStream(FileOpenMode mode) const override {
174  return obj.getStream(mode);
175  }
176 
177  DeriveT obj;
178  };
179 
180  std::unique_ptr<Concept> m_d;
181  };
182 
183  class FileDesc;
184 
185  class FileInterface;
186 
188  {
189  inline explicit DumbFileStream(FileContent r) : remaining(r) {}
190 
191  template<class Callback>
192  void read(int maxSize, Callback callback) {
193  if (remaining.empty()) {
194  callback(FileOpRetCode::Eof, remaining);
195  } else {
196  auto taken = remaining.take(maxSize);
197  remaining = remaining.drop(maxSize);
198  callback(FileOpRetCode::Success, taken);
199  }
200  }
201 
202  template<class Callback>
203  void write(FileContent data, Callback callback) {
204  remaining = remaining + data;
205  callback(FileOpRetCode::Success, data.size());
206  }
207 
209  };
210 
212  {
213  inline explicit DumbFileProvider(FileContent content)
214  : m_content(content)
215  {}
216 
217  inline DumbFileStream getStream(FileOpenMode /* mode */) const {
218  return DumbFileStream(m_content);
219  }
220 
222  };
223 
224  class FileDesc
225  {
226  public:
230  explicit FileDesc(FileContent content)
231  : m_inMemory{true}
232  , m_content(content)
233  {}
234 
238  explicit FileDesc(std::string name,
239  std::optional<std::string> contentType = std::nullopt)
240  : m_inMemory{false}
241  , m_name(std::move(name))
242  , m_contentType(std::move(contentType)) {}
243 
253  FileProvider provider(const FileInterface &fh) const;
254 
258  inline std::optional<std::string> name() const { return m_name; }
259 
263  inline std::optional<std::string> contentType() const { return m_contentType; }
264 
265  bool operator==(const FileDesc &that) const;
266 
267  private:
268  bool m_inMemory;
269  FileContent m_content;
270  std::optional<std::string> m_name;
271  std::optional<std::string> m_contentType;
272  };
273 
275  {
276  public:
278  };
279 
281  {
282  public:
294  template<class DeriveT>
295  inline FileInterface(DeriveT &&o)
296  : m_d(std::make_unique<Model<std::decay_t<DeriveT>>>(
297  std::forward<DeriveT>(o))) {}
298 
305  inline FileProvider getProviderFor(FileDesc desc) const {
306  return m_d->getProviderFor(std::move(desc));
307  }
308 
309  private:
310  struct Concept
311  {
312  virtual ~Concept() = default;
313  virtual FileProvider getProviderFor(FileDesc desc) const = 0;
314  };
315 
316  template<class DeriveT>
317  struct Model : public Concept
318  {
319  explicit Model(const DeriveT &o) : obj(o) {}
320  explicit Model(DeriveT &&o) : obj(std::move(o)) {}
321  ~Model() override = default;
322  FileProvider getProviderFor(FileDesc desc) const override {
323  return obj.getProviderFor(std::move(desc));
324  }
325 
326  DeriveT obj;
327  };
328 
329  std::unique_ptr<Concept> m_d;
330  };
331 }
Kazv::DumbFileProvider::DumbFileProvider
DumbFileProvider(FileContent content)
Definition: file-desc.hpp:213
Kazv::FileOpRetCode::Eof
@ Eof
Kazv::FileDesc::FileDesc
FileDesc(std::string name, std::optional< std::string > contentType=std::nullopt)
Construct a FileDesc with name and contentType.
Definition: file-desc.hpp:238
Kazv::FileStream::DataT
FileContent DataT
Definition: file-desc.hpp:38
Kazv::FileStream::read
void read(int maxSize, Callback readCallback)
Read at most maxSize bytes from the stream.
Definition: file-desc.hpp:65
Kazv::FileOpenMode::Write
@ Write
Kazv::FileProvider::FileProvider
FileProvider(DeriveT &&o)
Constructor.
Definition: file-desc.hpp:129
Kazv::FileInterface::getProviderFor
FileProvider getProviderFor(FileDesc desc) const
Get the provider for desc from this.
Definition: file-desc.hpp:305
Kazv::FileOpenMode::Read
@ Read
Kazv::FileDesc::FileDesc
FileDesc(FileContent content)
Construct an in-memory FileDesc with content.
Definition: file-desc.hpp:230
Kazv::FileDesc::provider
FileProvider provider(const FileInterface &fh) const
Get the FileProvider for this FileDesc using FileInterface.
Definition: file-desc.cpp:17
Kazv::FileProvider::getStream
FileStream getStream(FileOpenMode mode=FileOpenMode::Read) const
Get the file stream provided by this.
Definition: file-desc.hpp:152
Kazv::DumbFileProvider::m_content
FileContent m_content
Definition: file-desc.hpp:221
Kazv::DumbFileStream::DumbFileStream
DumbFileStream(FileContent r)
Definition: file-desc.hpp:189
Kazv::DumbFileInterface
Definition: file-desc.hpp:274
Kazv::DumbFileStream::write
void write(FileContent data, Callback callback)
Definition: file-desc.hpp:203
Kazv::FileStream::FileStream
FileStream(DeriveT &&o)
Constructor.
Definition: file-desc.hpp:52
Kazv::FileOpRetCode::Error
@ Error
Kazv
Definition: location.hpp:10
Kazv::DumbFileStream
Definition: file-desc.hpp:187
Kazv::DumbFileProvider::getStream
DumbFileStream getStream(FileOpenMode) const
Definition: file-desc.hpp:217
Kazv::FileInterface
Definition: file-desc.hpp:280
Kazv::DumbFileStream::read
void read(int maxSize, Callback callback)
Definition: file-desc.hpp:192
Kazv::DumbFileProvider
Definition: file-desc.hpp:211
Kazv::FileProvider
Definition: file-desc.hpp:108
Kazv::FileStream::write
void write(DataT data, Callback writeCallback)
Write data into the stream.
Definition: file-desc.hpp:75
Kazv::FileDesc::contentType
std::optional< std::string > contentType() const
Get the content type for this FileDesc.
Definition: file-desc.hpp:263
Kazv::FileProvider::FileProvider
FileProvider(FileProvider &&that)
Definition: file-desc.hpp:134
Kazv::FileOpRetCode
FileOpRetCode
Definition: file-desc.hpp:20
Kazv::FileContent
immer::flex_vector< char > FileContent
Definition: file-desc.hpp:33
Kazv::FileOpenMode
FileOpenMode
Definition: file-desc.hpp:27
Kazv::FileDesc::name
std::optional< std::string > name() const
Get the name for this FileDesc.
Definition: file-desc.hpp:258
Kazv::FileDesc::operator==
bool operator==(const FileDesc &that) const
Definition: file-desc.cpp:45
Kazv::FileOpRetCode::Success
@ Success
Kazv::FileProvider::FileProvider
FileProvider(const FileProvider &that)
Definition: file-desc.hpp:133
std
Definition: clientutil.hpp:216
Kazv::FileInterface::FileInterface
FileInterface(DeriveT &&o)
Constructor.
Definition: file-desc.hpp:295
Kazv::FileDesc
Definition: file-desc.hpp:224
libkazv-config.hpp
Kazv::DumbFileInterface::getProviderFor
DumbFileProvider getProviderFor(FileDesc desc) const
Definition: file-desc.cpp:25
Kazv::FileStream
Definition: file-desc.hpp:35
Kazv::FileProvider::operator=
FileProvider & operator=(FileProvider &&that)
Definition: file-desc.hpp:141
Kazv::FileProvider::operator=
FileProvider & operator=(const FileProvider &that)
Definition: file-desc.hpp:136
Kazv::DumbFileStream::remaining
FileContent remaining
Definition: file-desc.hpp:208