tudocomp
– The TU Dortmund Compression Framework
RestrictedIOStream.hpp
Go to the documentation of this file.
1 #pragma once
2 
4 
5 namespace tdc {namespace io {
6  // TODO: Make these adapters use buffers to reduce
7  // virtual call overhead.
8 
13  class RestrictedOStreamBuf: public std::streambuf {
14  private:
15  std::ostream* m_stream;
16  FastUnescapeMap m_fast_unescape_map;
17  bool m_saw_escape = false;
18  bool m_saw_null = false;
19 
20  /*
21  Null termination logic is going to be a bit funky:
22  If null termination is enabled, this adapter will
23  hold on to each null character that should be output,
24  and only output it if there are further characters after it.
25  This way, the very last null will be ellided but no earlier ones.
26  */
27 
28  inline void internal_flush() {
29  // Nothing to do here, as any state needs further input to react
30  }
31 
32  inline void push_unescape(uint8_t c) {
33  auto put_internal = [&](uint8_t d){
34  m_stream->put(char(d));
35  };
36 
37  if (m_saw_escape) {
38  m_saw_escape = false;
39  if (m_saw_null) {
40  put_internal(0);
41  m_saw_null = false;
42  }
43  put_internal(m_fast_unescape_map.lookup_byte(c));
44  } else if (m_fast_unescape_map.has_escape_bytes()
45  && (c == m_fast_unescape_map.escape_byte())) {
46  m_saw_escape = true;
47  } else if (c == 0 && m_fast_unescape_map.null_terminate()) {
48  if (m_saw_null) {
49  put_internal(0);
50  m_saw_null = false;
51  }
52  // drop it temporarily
53  m_saw_null = true;
54  } else {
55  if (m_saw_null) {
56  put_internal(0);
57  m_saw_null = false;
58  }
59  put_internal(c);
60  }
61  }
62 
63  public:
64  inline RestrictedOStreamBuf(std::ostream& stream,
65  const InputRestrictions& restrictions):
66  m_stream(&stream),
67  m_fast_unescape_map(EscapeMap(restrictions)) {}
68 
69  inline RestrictedOStreamBuf() = delete;
70  inline RestrictedOStreamBuf(const RestrictedOStreamBuf& other) = delete;
71  inline RestrictedOStreamBuf(RestrictedOStreamBuf&& other) = delete;
72 
73  inline virtual ~RestrictedOStreamBuf() {
74  if (m_fast_unescape_map.null_terminate()) {
75  DCHECK(m_saw_null) << "Text to be unescaped did not end with a 0";
76  }
77  }
78 
79  protected:
80  inline virtual int overflow(int ch) override {
81  if (ch == traits_type::eof()) {
82  internal_flush();
83  } else {
84  push_unescape(traits_type::to_char_type(ch));
85  }
86 
87  return ch;
88  }
89  };
90 
94  class RestrictedIStreamBuf: public std::streambuf {
95  private:
96  std::istream* m_stream;
97  FastEscapeMap m_fast_escape_map;
98  int m_char_buf = traits_type::eof();
99  bool m_nt_done = false;
100  int m_current;
101 
102  inline int pull_escape() {
103  if (m_char_buf != traits_type::eof()) {
104  int tmp = m_char_buf;
105  m_char_buf = traits_type::eof();
106  return tmp;
107  }
108 
109  char c;
110  if (m_stream->get(c)) {
111  auto byte = uint8_t(c);
112  if (m_fast_escape_map.lookup_flag(byte)) {
113  m_char_buf = m_fast_escape_map.lookup_byte(byte);
114  return m_fast_escape_map.escape_byte();
115  } else {
116  return byte;
117  }
118  } else {
119  if (m_fast_escape_map.null_terminate() && !m_nt_done) {
120  m_nt_done = true;
121  return 0;
122  }
123  return traits_type::eof();
124  }
125  }
126 
127  public:
128  inline RestrictedIStreamBuf(std::istream& stream,
129  InputRestrictions restrictions):
130  m_stream(&stream),
131  m_fast_escape_map(EscapeMap(restrictions)) {
132  m_current = pull_escape();
133  }
134 
135  inline RestrictedIStreamBuf() = delete;
136  inline RestrictedIStreamBuf(const RestrictedIStreamBuf& other) = delete;
137  inline RestrictedIStreamBuf(RestrictedIStreamBuf&& other) = delete;
138 
139  inline virtual ~RestrictedIStreamBuf() {
140  }
141 
142  protected:
143  inline virtual int underflow() override {
144  return m_current;
145  }
146  inline virtual int uflow() override {
147  int tmp = m_current;
148  m_current = pull_escape();
149  return tmp;
150  }
151  };
152 
153 }}
bool null_terminate() const
Definition: EscapeMap.hpp:174
bool has_escape_bytes() const
Definition: EscapeMap.hpp:178
Contains the text compression and encoding framework.
Definition: namespaces.hpp:11
Adapter class over a std::ostream that reverse the escaping and null termination of data written to i...
uint8_t escape_byte() const
Definition: EscapeMap.hpp:170
Describes a set of restrictions placed on input data.
uint8_t lookup_byte(size_t i) const
Definition: EscapeMap.hpp:165
uint8_t lookup_flag(size_t i) const
Definition: EscapeMap.hpp:118
RestrictedOStreamBuf(std::ostream &stream, const InputRestrictions &restrictions)
uint8_t lookup_byte(size_t i) const
Definition: EscapeMap.hpp:127
bool null_terminate() const
Definition: EscapeMap.hpp:136
virtual int overflow(int ch) override
Adapter class over a std::istream that escapes and null terminates the data read from it according to...
RestrictedIStreamBuf(std::istream &stream, InputRestrictions restrictions)
uint8_t escape_byte() const
Definition: EscapeMap.hpp:132
virtual int underflow() override