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 19074 : auto bytes_in_buffer() const noexcept -> size_t
36 : {
37 19074 : return end_index - begin_index;
38 : }
39 :
40 756 : auto space_left_in_buffer() const noexcept -> size_t
41 : {
42 1512 : return buffer.size() - end_index;
43 : }
44 :
45 1211 : void shift_data_to_start() noexcept
46 : {
47 1211 : if (begin_index == 0)
48 412 : return;
49 :
50 1598 : memmove(buffer.data(), buffer.data() + begin_index, bytes_in_buffer());
51 799 : end_index -= begin_index;
52 799 : begin_index = 0;
53 : }
54 :
55 1211 : void read_buffer()
56 : {
57 1211 : shift_data_to_start();
58 :
59 3934 : while (bytes_in_buffer() < buffer.size() && !eof_reached)
60 : {
61 : auto bytes_in =
62 756 : static_cast<buffer_index_type>(on_read(&buffer[end_index], space_left_in_buffer()));
63 756 : eof_reached |= bytes_in == 0;
64 756 : end_index += bytes_in;
65 : }
66 1211 : }
67 :
68 : public:
69 378 : explicit buffered_reader(io::reader reader) : on_read(reader)
70 : {
71 378 : }
72 :
73 6041 : [[nodiscard]] auto view(size_t minimal_size) -> std::string_view
74 : {
75 6041 : minimal_size = std::max<size_t>(minimal_size, 1U);
76 6041 : if (bytes_in_buffer() < minimal_size)
77 1211 : read_buffer();
78 :
79 6041 : return std::string_view(&buffer[begin_index], bytes_in_buffer());
80 : }
81 :
82 4226 : void skip(size_t size) noexcept
83 : {
84 4226 : assert(size <= bytes_in_buffer());
85 4226 : begin_index += static_cast<buffer_index_type>(size);
86 4226 : }
87 : };
88 :
89 : } // namespace spb::io
|