6 namespace tdc {
namespace io {
14 class InputAllocChunk;
15 using InputAllocChunkHandle = std::shared_ptr<InputAllocChunk>;
16 using InputAlloc = std::vector<InputAllocChunkHandle>;
23 class InputAllocChunk {
26 std::weak_ptr<InputAlloc> m_alloc;
28 inline InputAllocChunk(
size_t from,
size_t to, std::weak_ptr<InputAlloc> alloc):
29 m_from(from), m_to(to), m_alloc(alloc) {
30 DCHECK(m_alloc.lock());
32 inline size_t from()
const {
35 inline size_t to()
const {
38 inline std::weak_ptr<InputAlloc> alloc()
const {
42 inline virtual ~InputAllocChunk() {}
43 virtual const InputRestrictions& restrictions()
const = 0;
44 virtual const InputSource& source()
const = 0;
45 virtual View view()
const = 0;
46 virtual RestrictedBuffer unwrap() && = 0;
47 virtual void debug_print_content()
const = 0;
51 class InputAllocChunkOwned:
public InputAllocChunk {
52 RestrictedBuffer m_buffer;
55 InputAllocChunkOwned(RestrictedBuffer&& buffer,
58 std::weak_ptr<InputAlloc> alloc):
59 InputAllocChunk(from, to, alloc),
60 m_buffer(
std::move(buffer)) {}
61 inline virtual const InputRestrictions& restrictions()
const {
62 return m_buffer.restrictions();
64 inline virtual const InputSource& source()
const {
65 return m_buffer.source();
67 inline virtual View view()
const {
68 return m_buffer.view();
70 inline virtual RestrictedBuffer unwrap() && {
71 return std::move(m_buffer);
73 inline virtual void debug_print_content()
const {
74 DVLOG(2) <<
" buf: " << m_buffer.view().size() <<
"\n";
80 class InputAllocChunkReferenced:
public InputAllocChunk {
82 std::shared_ptr<InputAllocChunk> m_parent;
84 inline InputAllocChunkReferenced(
88 const std::shared_ptr<InputAllocChunk>& parent
90 InputAllocChunk(from, to, parent->alloc()),
93 inline virtual const InputRestrictions& restrictions()
const {
94 return m_parent->restrictions();
96 inline virtual const InputSource& source()
const {
97 return m_parent->source();
99 inline virtual View view()
const {
102 inline virtual RestrictedBuffer unwrap() && {
103 throw std::runtime_error(
"This is only a view");
105 inline virtual void debug_print_content()
const {
106 DVLOG(2) <<
" parent: " << std::hex << size_t(&*m_parent) << std::dec <<
"\n";
111 class InputAllocHandle {
112 std::shared_ptr<InputAlloc> m_ptr;
114 inline void debug_print_content()
const {
117 DVLOG(2) <<
"Alloc registry:\n";
118 for (
auto& e : vec) {
121 DVLOG(2) <<
" self: " << std::hex << size_t(&ee) << std::dec <<
"\n";
122 DVLOG(2) <<
" kind: " << ee.source() <<
"\n";
123 DVLOG(2) <<
" from: " << ee.from() <<
"\n";
124 if (ee.to() == RestrictedBuffer::npos) {
125 DVLOG(2) <<
" to: <npos>" <<
"\n";
127 DVLOG(2) <<
" to: " << ee.to() <<
"\n";
129 DVLOG(2) <<
" rest: " << ee.restrictions() <<
"\n";
130 DVLOG(2) <<
" refs: " << e.use_count() <<
"\n";
131 ee.debug_print_content();
137 inline InputAllocChunkHandle create_buffer(F f)
const {
140 auto new_alloc = std::make_shared<InputAllocChunkOwned>(f(m_ptr));
141 m_ptr->push_back(new_alloc);
144 debug_print_content();
145 return m_ptr->back();
148 inline InputAllocChunkHandle create_ref(InputAllocChunkReferenced&& v)
const {
150 auto new_alloc = std::make_shared<InputAllocChunkReferenced>(std::move(v));
151 m_ptr->push_back(new_alloc);
154 debug_print_content();
155 return m_ptr->back();
158 inline InputAllocChunkHandle create_stream(
159 const InputSource&
src,
162 InputRestrictions restrictions,
163 std::vector<InputAllocChunkHandle*>& selection
165 InputAllocChunkHandle* parent_ptr =
nullptr;
168 for (
auto ch_ptr : selection) {
170 if (ch->from() == 0 && ch->to() == RestrictedBuffer::npos) {
177 if (parent_ptr ==
nullptr) {
178 create_buffer([&](std::weak_ptr<InputAlloc> ptr) {
179 return InputAllocChunkOwned {
180 RestrictedBuffer(src,
182 RestrictedBuffer::npos,
185 RestrictedBuffer::npos,
189 parent_ptr = &(m_ptr->back());
192 DVLOG(2) <<
"After parent create:\n";
193 debug_print_content();
197 auto& parent = *parent_ptr;
198 if (!(parent->restrictions() == restrictions)) {
199 CHECK(parent.unique())
200 <<
"Attempt to access stream `Input` in a way " 201 <<
"that would need to create a copy of the data.";
203 auto buf = std::move(*parent).unwrap();
204 parent = std::make_unique<InputAllocChunkOwned>(
205 InputAllocChunkOwned {
206 std::move(buf).change_restrictions(restrictions),
208 RestrictedBuffer::npos,
214 DVLOG(2) <<
"After parent restrict:\n";
215 debug_print_content();
218 if (from == 0 && to == RestrictedBuffer::npos) {
225 size_t escaped_from = 0;
226 size_t escaped_to = 0;
229 if(parent->restrictions().has_no_escape_restrictions()) {
233 uint8_t escape_byte = EscapeMap(parent->restrictions()).escape_byte();
234 auto v = parent->view();
237 size_t unescaped_i = 0;
239 for (; i < v.size(); i++) {
240 if (unescaped_i == from) {
244 if (v[i] != escape_byte) {
249 if (to != RestrictedBuffer::npos) {
250 for (; i < v.size(); i++) {
251 if (unescaped_i == to) {
255 if (v[i] != escape_byte) {
260 escaped_to = RestrictedBuffer::npos;
264 if (restrictions.null_terminate()) {
265 CHECK(escaped_to == RestrictedBuffer::npos)
266 <<
"Can not yet slice while adding a null terminator";
270 DVLOG(2) <<
"After ref create:\n";
271 return create_ref(InputAllocChunkReferenced {
272 parent->view().slice(escaped_from, escaped_to),
279 inline void cleanup_empty() {
286 new_vec.push_back(p);
293 inline void remove(InputAllocChunkHandle handle) {
294 for (
auto& ptr : *m_ptr) {
303 inline InputAllocChunkHandle find_or_construct(
304 const InputSource& src,
307 InputRestrictions restrictions)
const 309 auto pred = [&](
const InputSource& e) ->
bool {
313 std::vector<InputAllocChunkHandle*> selection;
314 for (
auto& eptr : *m_ptr) {
317 if (pred(e.source())) {
318 selection.push_back(&eptr);
324 for (
auto& eptr : selection) {
327 if (e.from() == from && e.to() == to && e.restrictions() == restrictions) {
333 if (src.is_stream()) {
338 return create_stream(src, from, to, restrictions, selection);
342 return create_buffer([&](std::weak_ptr<InputAlloc> ptr) {
343 return InputAllocChunkOwned {
344 RestrictedBuffer(src, from, to, restrictions),
353 inline InputAllocHandle(): m_ptr(
std::make_shared<InputAlloc>()) {}
354 inline InputAllocHandle(std::weak_ptr<InputAlloc> weak) {
355 DCHECK(!weak.expired());
360 friend void unregister_alloc_chunk_handle(InputAllocChunkHandle handle);
368 inline void unregister_alloc_chunk_handle(InputAllocChunkHandle handle) {
372 if (handle->source().is_stream()) {
373 if (handle->from() == 0 && handle->to() == RestrictedBuffer::npos) {
378 auto tmp = InputAllocHandle(handle->alloc());
Contains the text compression and encoding framework.