18 namespace tdc {
namespace io {
20 class RestrictedBuffer {
22 static const size_t npos = -1;
25 View m_restricted_data;
27 io::InputRestrictions m_restrictions;
40 size_t m_mmap_page_offset = 0;
42 template<
typename I,
typename J>
43 inline void escape_with_iters(I read_begin, I read_end, J write_end,
bool do_copy =
false) {
44 if (!m_restrictions.has_no_escape_restrictions()) {
45 FastEscapeMap fast_escape_map;
49 EscapeMap em(m_restrictions);
50 fast_escape_map = FastEscapeMap(em);
51 escape_byte = fast_escape_map.escape_byte();
54 while(read_begin != read_end) {
58 uint8_t current_byte = *read_end;
60 *write_end = fast_escape_map.lookup_byte(current_byte);
62 if (fast_escape_map.lookup_flag_bool(current_byte)) {
64 *write_end = escape_byte;
68 while(read_begin != read_end) {
71 *write_end = *read_end;
81 inline size_t extra_size_needed_due_restrictions(T begin, T end,
size_t len) {
84 if (!m_restrictions.has_no_escape_restrictions()) {
87 FastEscapeMap fast_escape_map{EscapeMap(m_restrictions)};
89 while((begin != end) && (i < len)) {
90 uint8_t current_byte = *begin;
92 extra += fast_escape_map.lookup_flag(current_byte);
101 if (m_restrictions.null_terminate()) {
108 inline void init(
size_t m_from,
size_t m_to) {
109 if (m_source.is_view()) {
112 s = m_source.view().
slice(m_from);
114 s = m_source.view().
slice(m_from, m_to);
117 size_t extra_size = extra_size_needed_due_restrictions(
118 s.cbegin(), s.cend(), s.size());
120 if (extra_size != 0) {
121 size_t size = s.
size() + extra_size;
125 GenericView<uint8_t> target = m_map.view();
126 size_t noff = m_restrictions.null_terminate()? 1 : 0;
127 escape_with_iters(s.cbegin(), s.cend(), target.end() - noff,
true);
131 m_restricted_data = m_map.view();
133 m_restricted_data = s;
135 }
else if (m_source.is_file()) {
138 size_t unrestricted_size;
140 unrestricted_size = read_file_size(m_source.file()) - m_from;
142 unrestricted_size = m_to - m_from;
145 auto path = m_source.file();
146 auto c_path = path.c_str();
148 size_t extra_size = 0;
150 auto ifs = create_tdc_ifstream(c_path, m_from);
152 std::istreambuf_iterator<char> begin (ifs);
153 std::istreambuf_iterator<char> end;
155 extra_size = extra_size_needed_due_restrictions(
156 begin, end, unrestricted_size);
159 size_t aligned_offset = MMap::next_valid_offset(m_from);
160 m_mmap_page_offset = m_from - aligned_offset;
162 DCHECK_EQ(aligned_offset + m_mmap_page_offset, m_from);
164 size_t map_size = unrestricted_size + extra_size + m_mmap_page_offset;
166 if (m_restrictions.has_no_restrictions()) {
167 m_map = MMap(path, MMap::Mode::Read, map_size, aligned_offset);
169 const auto& m = m_map;
170 m_restricted_data = m.view().slice(m_mmap_page_offset);
172 m_map = MMap(path, MMap::Mode::ReadWrite, map_size, aligned_offset);
174 size_t noff = m_restrictions.null_terminate()? 1 : 0;
176 uint8_t* begin_file_data = m_map.view().begin() + m_mmap_page_offset;
177 uint8_t* end_file_data = begin_file_data + unrestricted_size;
178 uint8_t* end_data = end_file_data + extra_size - noff;
179 escape_with_iters(begin_file_data, end_file_data, end_data);
180 if (m_restrictions.null_terminate()) {
184 m_restricted_data = m_map.view().slice(m_mmap_page_offset);
186 }
else if (m_source.is_stream()) {
187 DCHECK_EQ(m_from, 0);
188 DCHECK_EQ(m_to, npos);
192 size_t capacity = pagesize();
194 size_t extra_size = 0;
195 FastEscapeMap fast_escape_map;
196 if (!m_restrictions.has_no_escape_restrictions()) {
197 fast_escape_map = FastEscapeMap {
198 EscapeMap(m_restrictions)
202 size_t noff = m_restrictions.null_terminate()? 1 : 0;
207 m_map = MMap(capacity);
211 std::istream& is = *(m_source.stream());
216 uint8_t* ptr = m_map.view().begin() + size;
217 while(size < capacity) {
226 extra_size += fast_escape_map.lookup_flag(uint8_t(c));
233 m_map.remap(capacity);
239 m_map.remap(size + extra_size);
241 m_restricted_data = m_map.view();
246 uint8_t* begin_stream_data = m_map.view().begin();
247 uint8_t* end_stream_data = begin_stream_data + size;
248 uint8_t* end_data = end_stream_data + extra_size - noff;
249 escape_with_iters(begin_stream_data, end_stream_data, end_data);
252 DCHECK(
false) <<
"This should not happen";
257 inline static RestrictedBuffer unrestrict(RestrictedBuffer&& other) {
258 DCHECK(other.source().is_stream());
259 if (other.restrictions().has_no_restrictions()) {
260 return std::move(other);
262 DCHECK(other.restrictions().has_restrictions());
263 DCHECK(other.m_mmap_page_offset == 0);
265 auto x = std::move(other);
267 auto r = x.m_restrictions;
269 auto start = x.m_map.view().begin();
270 auto end = x.m_map.view().end();
272 FastUnescapeMap fast_unescape_map { EscapeMap(r) };
275 auto write_p = start;
277 size_t noff = x.m_restrictions.null_terminate()? 1 : 0;
279 auto data_end = end - noff;
281 while (read_p != data_end) {
282 if (*read_p == fast_unescape_map.escape_byte()) {
284 *write_p = fast_unescape_map.lookup_byte(*read_p);
292 auto old_size = x.m_map.view().size();
293 auto reduced_size = (read_p - write_p) + noff;
295 x.m_map.remap(old_size - reduced_size);
296 x.m_restrictions = InputRestrictions();
297 x.m_restricted_data = x.m_map.view();
303 inline static RestrictedBuffer restrict(RestrictedBuffer&& other,
304 const io::InputRestrictions& restrictions) {
305 DCHECK(other.source().is_stream());
306 if (other.restrictions() == restrictions) {
307 return std::move(other);
309 DCHECK(other.restrictions().has_no_restrictions());
310 DCHECK(other.m_mmap_page_offset == 0);
317 View s = other.view();
318 other.m_restrictions = restrictions;
319 extra_size = other.extra_size_needed_due_restrictions(
320 s.cbegin(), s.cend(), s.size()
327 if (extra_size == 0) {
328 return std::move(other);
333 other.m_map.remap(old_size + extra_size);
334 other.m_restricted_data = other.m_map.view();
337 size_t noff = other.m_restrictions.null_terminate()? 1 : 0;
339 uint8_t* start = other.m_map.view().begin();
340 uint8_t* old_end = start + old_size;
341 uint8_t* new_end = old_end + extra_size - noff;
343 other.escape_with_iters(start, old_end, new_end);
344 if (other.m_restrictions.null_terminate()) {
348 DCHECK_EQ(new_end + noff, other.m_map.view().end());
351 return std::move(other);
357 inline RestrictedBuffer change_restrictions(
358 const io::InputRestrictions& restrictions) &&
361 auto buf = unrestrict(std::move(other));
362 auto r = restrict(std::move(buf), restrictions);
366 inline RestrictedBuffer(
const InputSource&
src,
369 io::InputRestrictions restrictions):
370 m_restrictions(restrictions),
376 inline const InputRestrictions& restrictions()
const {
return m_restrictions; }
377 inline const InputSource& source()
const {
return m_source; }
379 inline View view()
const {
return m_restricted_data; }
381 inline RestrictedBuffer() =
delete;
Contains the text compression and encoding framework.
size_type size() const
Returns size of the View.
ConstGenericView slice(size_type from, size_type to=npos) const
Construct a new View that is a sub view into the current one.