19#ifndef MTCORE_READER_HPP
20#define MTCORE_READER_HPP
41 template<ReaderImpl Impl>
69 auto res =
read(buff);
70 if (res.is_success() && res.value().size() < buff.
size()) {
71 return error(ErrType::END_OF_FILE);
84 auto res =
read(buff);
88 auto resSlice = res.value();
89 if (resSlice.size() < buff.
size()) {
94 if (
auto ro =
read_one(); ro.is_success() || ro.error().code != ErrType::END_OF_FILE) {
95 return error(ErrType::SIZE_EXCEEDED);
114 ensure(maxSize > 0,
"BAD MAX SIZE");
116 if (maxSize == std::numeric_limits<size_t>::max() || maxSize >= 100000000) {
120 if (
auto res = fullBuff.
init(alloc, 10); res.is_error()) {
121 return error(ErrType::ALLOCATION_FAILED);
128 while (
iter.next().copy_if_present(curSlice)) {
140 auto curRes = alloc.
create_many<std::remove_const_t<ReadElem>>(8000);
141 if (curRes.is_error()) {
142 return error(ErrType::ALLOCATION_FAILED);
145 auto cur = curRes.value();
152 auto readRes =
read(cur);
153 if (readRes.is_error()) {
154 return error(ErrType::ALLOCATION_FAILED);
157 auto readData = readRes.value();
158 if (readData.empty()) {
162 auto toPush = cur.sub(0, readData.size());
163 if (
auto pushRes = fullBuff.
push(alloc, toPush); pushRes.is_error()) {
164 return error(ErrType::ALLOCATION_FAILED);
168 count += readData.size();
170 if (readData.size() < cur.size()) {
182 auto finalRes = alloc.
create_many<std::remove_const_t<ReadElem>>(count);
183 if (finalRes.is_error()) {
184 return error(ErrType::ALLOCATION_FAILED);
187 auto finalSlice = finalRes.value();
193 while (
iter.next().copy_if_present(curBuff)) {
194 if (
auto r = finalWriter.write_all(curBuff); r.is_error()) {
196 return error(ErrType::ALLOCATION_FAILED);
205 auto outRes = alloc.
create_many<std::remove_const_t<ReadElem>>(maxSize);
206 if (outRes.is_error()) {
207 return error(ErrType::ALLOCATION_FAILED);
209 auto out = outRes.value();
211 if (res.is_error()) {
215 auto finalRes = res.value();
219 if (finalRes.size() +
alignof(
ReadElem) < out.size()) {
220 if (finalRes.size() == 0) {
225 auto smallerRes = alloc.
create_many<std::remove_const_t<ReadElem>>(finalRes.size());
226 if (smallerRes.is_error()) {
228 return out.sub(0, finalRes.size());
230 auto smaller = smallerRes.value();
232 ensure(w.write_all(finalRes).is_success(),
"SOMETHING IS WRONG WITH SLICE WRITER!");
236 return success(out.sub(0, finalRes.size()));
246 std::remove_const_t<ReadElem> elem;
248 auto readRes =
read(s);
249 if (readRes.is_error()) {
250 return readRes.error();
252 auto res = readRes.value();
254 return error(ErrType::END_OF_FILE);
266 for (
size_t i = 0; i < n; ++i) {
283 template<ReaderImpl RI>
300 for (
size_t i = 0; i < buff.
size(); ++i) {
301 auto chRes = self.read_one();
302 if (chRes.is_error()) {
303 if (chRes.error().code == ErrType::END_OF_FILE) {
306 return chRes.error();
308 auto ch = chRes.value();
314 auto nxt = self.read_one();
315 if (nxt.is_error()) {
316 if (nxt.error().code == ErrType::END_OF_FILE) {
321 if (nxt.value() != delim) {
322 return error(ErrType::SIZE_EXCEEDED);
343 size_t maxSize = std::numeric_limits<size_t>::max()) {
347 ensure(maxSize > 0,
"BAD MAX SIZE");
349 if (maxSize == std::numeric_limits<size_t>::max() || maxSize >= 100000000) {
352 if (
auto res = fullBuff.
init(alloc, 4000); res.is_error()) {
353 return error(ErrType::ALLOCATION_FAILED);
362 auto readRes = self.read_one();
363 if (readRes.is_error()) {
364 if (readRes.error().code == ErrType::END_OF_FILE) {
367 return error(ErrType::ALLOCATION_FAILED);
370 auto cur = readRes.value();
374 if (
auto pushRes = fullBuff.
push(alloc, cur); pushRes.is_error()) {
375 return error(ErrType::ALLOCATION_FAILED);
381 return BuffSlice{
nullptr, 0};
386 auto finalRes = alloc.
create_many<std::remove_const_t<ReadElem>>(count);
387 if (finalRes.is_error()) {
388 return error(ErrType::ALLOCATION_FAILED);
391 auto finalSlice = finalRes.value();
396 std::remove_const_t<ReadElem> curElem;
397 while (
iter.next().copy_if_present(curElem)) {
398 if (
auto r = finalWriter.write(curElem); r.is_error()) {
400 return error(ErrType::ALLOCATION_FAILED);
409 auto outRes = alloc.
create_many<std::remove_const_t<ReadElem>>(maxSize);
410 if (outRes.is_error()) {
411 return error(ErrType::ALLOCATION_FAILED);
413 auto out = outRes.value();
415 if (res.is_error()) {
419 auto finalRes = res.value();
423 if (finalRes.size() +
alignof(ReadElem) < out.size()) {
424 if (finalRes.size() == 0) {
426 return BuffSlice{
nullptr, 0};
429 auto smallerRes = alloc.
create_many<std::remove_const_t<ReadElem>>(finalRes.size());
430 if (smallerRes.is_error()) {
432 return out.sub(0, finalRes.size());
434 auto smaller = smallerRes.value();
436 ensure(w.write_all(finalRes).is_success(),
"SOMETHING IS WRONG WITH SLICE WRITER!");
440 return success(out.sub(0, finalRes.size()));
460 for (
size_t i = 0; i < buff.
size(); ++i) {
461 auto chRes = self.read_one();
462 if (chRes.is_error()) {
463 if (chRes.error().code == ErrType::END_OF_FILE) {
464 return error(ErrType::END_OF_FILE);
466 return chRes.error();
468 auto ch = chRes.value();
474 auto nxt = self.read_one();
475 if (nxt.is_error()) {
478 if (nxt.value() != delim) {
479 return error(ErrType::SIZE_EXCEEDED);
501 size_t maxSize = std::numeric_limits<size_t>::max()) {
505 ensure(maxSize > 0,
"BAD MAX SIZE");
507 if (maxSize == std::numeric_limits<size_t>::max() || maxSize >= 100000000) {
510 if (
auto res = fullBuff.
init(alloc, 4000); res.is_error()) {
511 return error(ErrType::ALLOCATION_FAILED);
520 auto readRes = self.read_one();
521 if (readRes.is_error()) {
522 if (readRes.error().code == ErrType::END_OF_FILE) {
523 return error(ErrType::END_OF_FILE);
525 return error(ErrType::ALLOCATION_FAILED);
528 auto cur = readRes.value();
532 if (
auto pushRes = fullBuff.
push(alloc, cur); pushRes.is_error()) {
533 return error(ErrType::ALLOCATION_FAILED);
539 return BuffSlice{
nullptr, 0};
544 auto finalRes = alloc.
create_many<std::remove_const_t<ReadElem>>(count);
545 if (finalRes.is_error()) {
546 return error(ErrType::ALLOCATION_FAILED);
549 auto finalSlice = finalRes.value();
554 std::remove_const_t<ReadElem> curElem;
555 while (
iter.next().copy_if_present(curElem)) {
556 if (
auto r = finalWriter.write(curElem); r.is_error()) {
558 return error(ErrType::ALLOCATION_FAILED);
567 auto outRes = alloc.
create_many<std::remove_const_t<ReadElem>>(maxSize);
568 if (outRes.is_error()) {
569 return error(ErrType::ALLOCATION_FAILED);
571 auto out = outRes.value();
573 if (res.is_error()) {
577 auto finalRes = res.value();
581 if (finalRes.size() +
alignof(ReadElem) < out.size()) {
582 if (finalRes.size() == 0) {
584 return BuffSlice{
nullptr, 0};
587 auto smallerRes = alloc.
create_many<std::remove_const_t<ReadElem>>(finalRes.size());
588 if (smallerRes.is_error()) {
590 return out.sub(0, finalRes.size());
592 auto smaller = smallerRes.value();
594 ensure(w.write_all(finalRes).is_success(),
"SOMETHING IS WRONG WITH SLICE WRITER!");
598 return success(out.sub(0, finalRes.size()));
612 struct SliceReaderImpl {
614 size_t curReadIndex = 0;
625 if (!first && curReadIndex >= buff.
size()) {
626 return error(ErrType::END_OF_FILE);
630 for (; curReadIndex < buff.
size() && count < out.size(); ++curReadIndex, ++count) {
631 out[count] = buff[curReadIndex];
633 return success(out.sub(0, count).to_const());
SliceReaderError
Errors that can happen from the Slice Reader Note that these are all required by the Reader class as ...
#define ensure(check,...)
Ensures that a check holds true, aborts the program if not true Will print error if the condition is ...
#define mtdefer
Defer statement that will mtdefer execution until the scope is left, at which point the code will run...
Result< typename Reader< T >::ResSlice, typename Reader< T >::ErrType > read_until_or_eof(Reader< T > &self, typename Reader< T >::BuffSlice buff, const std::remove_const_t< typename Reader< T >::ReadElem > &delim)
Reads data from a reader into a Slice up until there is either a delimiter or end of file If the buff...
Result< typename Reader< T >::ResSlice, typename Reader< T >::ErrType > read_until_no_eof(Reader< T > &self, typename Reader< T >::BuffSlice buff, const std::remove_const_t< typename Reader< T >::ReadElem > &delim)
Reads data from a reader into a Slice up until there is either a delimiter If the buffer is not big e...
Reader< impl::SliceReaderImpl< T > > slice_reader(Slice< T > buff)
Creates a reader to read the contents of a Slice.
Success< void > success()
Creates a successful void Result object.
Error< Underlying > error(Underlying err)
Creates an error.
io::Writer< impl::SliceWriterImpl< T > > slice_writer(Slice< T > out)
Creates a writer to write to a Slice.
Additional algorithms that can be done on a reader without having to extend the reader type We're enc...
Generic iterator defaults built on common contracts Does not guarantee performance of iterators Actua...
Represents a memory allocator Exact behavior depends on the underlying VTable used Should use the a_*...
void destroy_many(Slice< T > s)
Destroys objects allocated by this allocator by calling the destructors and freeing memory.
Result< Slice< T >, AllocationError > create_many(size_t count=1)
Allocates some block of memory with an allocator with a known type Will call default constructor on t...
Represents a Result that may have an error (error code) or a success value A type of "void" means the...
Segmented list where each segment contains multiple nodes Allows growing the list without having to i...
Result< void, CollectionAddNoAllocationError > push(const T &elem) noexcept
Pushes a new element.
void deinit(Allocator &alloc)
Cleans up memory tied to segmented list.
Result< void, AllocationError > init(Allocator &alloc, size_t initCapacity)
Initializes a segmented list.
ConstIter iter() const noexcept
Const iterator that gives element references.
A Slice which is just a pointer + length Accessing elements through the array operator will do bounds...
constexpr Slice sub(size_t start) const noexcept
Gets a sub Slice from start.
constexpr size_t size() const noexcept
Gets the size of a Slice.
constexpr Slice< std::add_const_t< T > > to_const() const noexcept
Converts to a const Slice.
A reader that reads data from some sort of stream or buffer Note: the data elements read should be tr...
Result< ResSlice, ErrType > read_no_eof(BuffSlice buff)
Tries to read data from a reader into a buffer It will stop once the buffer is full,...
Slice< std::remove_const_t< ReadElem > > BuffSlice
Result< ResSlice, ErrType > read(BuffSlice buff)
Tries to read data from a reader into a buffer It will stop once the buffer is full,...
Result< ResSlice, ErrType > read_all(BuffSlice buff)
Tries to read all data from a reader into a buffer It will stop once the EOF is reached If the buffer...
typename Impl::ReadElem ReadElem
typename Impl::ErrType ErrType
Slice< std::add_const_t< ReadElem > > ResSlice
Result< void, ErrType > skip(size_t n)
Will skip n items (basically reads and discards them) If there are not n items left to skip (aka it h...
Result< ReadElem, ErrType > read_one()
Will try to read a single item from the reader If there is no item to read (aka at EOF),...
Result< BuffSlice, ErrType > read_all(Allocator &alloc, size_t maxSize=std::numeric_limits< size_t >::max())
Tries to read all data from a reader into an internally allocated buffer Will try to shrink the buffe...