tudocomp
– The TU Dortmund Compression Framework
OutputStream.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstddef>
4 #include <cstdint>
5 #include <fstream>
6 #include <iostream>
7 #include <string>
8 #include <utility>
9 #include <vector>
10 
13 
14 namespace tdc {
15 namespace io {
17  class OutputStreamInternal {
18  class Variant {
19  public:
20  virtual ~Variant() {}
21  virtual std::ostream& stream() = 0;
22 
23  virtual std::streampos tellp() {
24  return stream().tellp();
25  }
26  };
27 
28  class Memory: public Variant {
29  BackInsertStream m_stream;
30  public:
31  friend class OutputStreamInternal;
32 
33  inline Memory(BackInsertStream&& stream): m_stream(stream) {}
34 
35  inline std::ostream& stream() override {
36  return m_stream.stream();
37  }
38 
39  inline Memory(Memory&& other):
40  m_stream(std::move(other.m_stream)) {}
41 
42  inline Memory(const Memory& other) = delete;
43  inline Memory() = delete;
44 
45  virtual std::streampos tellp() override {
46  return m_stream.size();
47  }
48  };
49  class Stream: public Variant {
50  std::ostream* m_stream;
51  public:
52  friend class OutputStreamInternal;
53 
54  inline Stream(std::ostream* stream): m_stream(stream) {}
55 
56  inline std::ostream& stream() override {
57  return *m_stream;
58  }
59 
60  inline Stream(Stream&& other):
61  m_stream(std::move(other.m_stream)) {}
62 
63  inline Stream(const Stream& other) = delete;
64  inline Stream() = delete;
65  };
66  class File: public Variant {
67  std::string m_path;
68  std::unique_ptr<std::ofstream> m_stream;
69 
70  public:
71  friend class OutputStreamInternal;
72 
73  inline File(std::string&& path, bool overwrite = false) {
74  m_path = path;
75  if (overwrite) {
76  m_stream = std::make_unique<std::ofstream>(m_path,
77  std::ios::out | std::ios::binary);
78  } else {
79  m_stream = std::make_unique<std::ofstream>(m_path,
80  std::ios::out | std::ios::binary | std::ios::app);
81  }
82  if (!*m_stream) {
83  throw tdc_output_file_not_found_error(m_path);
84  }
85  }
86 
87  inline File(File&& other):
88  m_path(std::move(other.m_path)),
89  m_stream(std::move(other.m_stream)) {}
90 
91  inline std::ostream& stream() override {
92  return *m_stream;
93  }
94 
95  inline File(const File& other) = delete;
96  inline File() = delete;
97  };
98 
99  std::unique_ptr<Variant> m_variant;
100  std::unique_ptr<RestrictedOStreamBuf> m_restricted_ostream;
101 
102  friend class Output;
103  friend class OutputStream;
104 
105  inline OutputStreamInternal(const OutputStreamInternal& other) = delete;
106  inline OutputStreamInternal() = delete;
107 
108  inline OutputStreamInternal(OutputStreamInternal::Memory&& mem,
109  const InputRestrictions& restrictions):
110  m_variant(std::make_unique<Memory>(std::move(mem)))
111  {
112  if (!restrictions.has_no_restrictions()) {
113  m_restricted_ostream = std::make_unique<RestrictedOStreamBuf>(
114  m_variant->stream(),
115  restrictions
116  );
117  }
118  }
119  inline OutputStreamInternal(OutputStreamInternal::File&& s,
120  const InputRestrictions& restrictions):
121  m_variant(std::make_unique<File>(std::move(s)))
122  {
123  if (!restrictions.has_no_restrictions()) {
124  m_restricted_ostream = std::make_unique<RestrictedOStreamBuf>(
125  m_variant->stream(),
126  restrictions
127  );
128  }
129  }
130  inline OutputStreamInternal(OutputStreamInternal::Stream&& s,
131  const InputRestrictions& restrictions):
132  m_variant(std::make_unique<Stream>(std::move(s)))
133  {
134  if (!restrictions.has_no_restrictions()) {
135  m_restricted_ostream = std::make_unique<RestrictedOStreamBuf>(
136  m_variant->stream(),
137  restrictions
138  );
139  }
140  }
141 
142  inline OutputStreamInternal(OutputStreamInternal&& other):
143  m_variant(std::move(other.m_variant)),
144  m_restricted_ostream(std::move(other.m_restricted_ostream)) {}
145 
146  inline std::streambuf* internal_rdbuf() {
147  if (m_restricted_ostream) {
148  return &*m_restricted_ostream;
149  } else {
150  return m_variant->stream().rdbuf();
151  }
152  }
153 
154  inline std::streampos tellp() {
155  return m_variant->tellp();
156  }
157  };
159 
161  class OutputStream: OutputStreamInternal, public std::ostream {
162  friend class Output;
163 
164  inline OutputStream(OutputStreamInternal&& mem):
165  OutputStreamInternal(std::move(mem)),
166  std::ostream(OutputStreamInternal::internal_rdbuf()) {
167  }
168  public:
170  inline OutputStream(OutputStream&& mem):
171  OutputStreamInternal(std::move(mem)),
172  std::ostream(mem.rdbuf()) {}
173 
175  inline OutputStream(const OutputStream& other) = delete;
176 
178  inline OutputStream() = delete;
179 
180  inline std::streampos tellp() {
181  return OutputStreamInternal::tellp();
182  }
183  };
184 
185  inline OutputStream Output::Memory::as_stream() const {
186  return OutputStream {
187  OutputStreamInternal {
188  OutputStream::Memory {
189  BackInsertStream { *m_buffer }
190  },
191  restrictions()
192  }
193  };
194  }
195 
196  inline OutputStream Output::File::as_stream() const {
197  // TODO: Replace this mutation with a read-only solution
198  // Eg by making it always append-only
199  auto overwrite = m_overwrite;
200  m_overwrite = false;
201  return OutputStream {
202  OutputStreamInternal {
203  OutputStream::File {
204  std::string(m_path),
205  overwrite,
206  },
207  restrictions()
208  }
209  };
210  }
211 
212  inline OutputStream Output::Stream::as_stream() const {
213  return OutputStream {
214  OutputStreamInternal {
215  OutputStream::Stream {
216  m_stream
217  },
218  restrictions()
219  }
220  };
221  }
222 
224  return m_data->as_stream();
225  }
226 }}
Contains the text compression and encoding framework.
Definition: namespaces.hpp:11
Provides a character stream to the underlying output.
std::streampos tellp()
OutputStream as_stream() const
Creates a stream that allows for character-wise output.
An abstraction layer for algorithm output.
Definition: Output.hpp:23
uint64_t m_data
Definition: uint_t.hpp:30
OutputStream(OutputStream &&mem)
Move constructor.
io::Output Output
Convenience shortcut to io::Output.
Definition: io.hpp:20