Line data Source code
1 : /***************************************************************************\
2 : * Name : buffered reader *
3 : * Description : buffer between io::reader and detail::istream *
4 : * Author : antonin.kriz@gmail.com *
5 : * ------------------------------------------------------------------------- *
6 : * This is free software; you can redistribute it and/or modify it under the *
7 : * terms of the MIT license. A copy of the license can be found in the file *
8 : * "LICENSE" at the root of this distribution. *
9 : \***************************************************************************/
10 :
11 : #pragma once
12 : #include "io.hpp"
13 : #include <array>
14 : #include <cassert>
15 : #include <cstdlib>
16 : #include <cstring>
17 : #include <string_view>
18 : #include <sys/types.h>
19 :
20 : namespace spb::io
21 : {
22 : class buffered_reader
23 : {
24 : public:
25 : static constexpr size_t BUFFER_SIZE = 256;
26 :
27 : private:
28 : using buffer_index_type = uint16_t;
29 : std::array<char, BUFFER_SIZE> buffer;
30 : io::reader on_read;
31 : buffer_index_type begin_index = 0;
32 : buffer_index_type end_index = 0;
33 : bool eof_reached = false;
34 :
35 19443 : auto bytes_in_buffer() const noexcept -> size_t
36 : {
37 19443 : return end_index - begin_index;
38 : }
39 :
40 772 : auto space_left_in_buffer() const noexcept -> size_t
41 : {
42 1544 : return buffer.size() - end_index;
43 : }
44 :
45 1230 : void shift_data_to_start() noexcept
46 : {
47 1230 : if (begin_index == 0)
48 420 : return;
49 :
50 1620 : memmove(buffer.data(), buffer.data() + begin_index, bytes_in_buffer());
51 810 : end_index -= begin_index;
52 810 : begin_index = 0;
53 : }
54 :
55 1230 : void read_buffer()
56 : {
57 1230 : shift_data_to_start();
58 :
59 4004 : while (bytes_in_buffer() < buffer.size() && !eof_reached)
60 : {
61 : auto bytes_in =
62 772 : static_cast<buffer_index_type>(on_read(&buffer[end_index], space_left_in_buffer()));
63 772 : eof_reached |= bytes_in == 0;
64 772 : end_index += bytes_in;
65 : }
66 1230 : }
67 :
68 : public:
69 386 : explicit buffered_reader(io::reader reader) : on_read(reader)
70 : {
71 386 : }
72 :
73 6158 : [[nodiscard]] auto view(size_t minimal_size) -> std::string_view
74 : {
75 6158 : minimal_size = std::max<size_t>(minimal_size, 1U);
76 6158 : if (bytes_in_buffer() < minimal_size)
77 1230 : read_buffer();
78 :
79 6158 : return std::string_view(&buffer[begin_index], bytes_in_buffer());
80 : }
81 :
82 4315 : void skip(size_t size) noexcept
83 : {
84 4315 : assert(size <= bytes_in_buffer());
85 4315 : begin_index += static_cast<buffer_index_type>(size);
86 4315 : }
87 : };
88 :
89 : } // namespace spb::io
|