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 <cstdlib>
15 : #include <cstring>
16 : #include <string_view>
17 :
18 : namespace spb::io
19 : {
20 : #ifndef SPB_READ_BUFFER_SIZE
21 : #define SPB_READ_BUFFER_SIZE 256U
22 : #endif
23 :
24 : class buffered_reader
25 : {
26 : private:
27 : io::reader on_read;
28 : std::array<char, SPB_READ_BUFFER_SIZE> buffer;
29 : size_t begin_index = 0;
30 : size_t end_index = 0;
31 : bool eof_reached = false;
32 :
33 190756 : auto bytes_in_buffer() const noexcept -> size_t
34 : {
35 190756 : return end_index - begin_index;
36 : }
37 :
38 26333 : auto space_left_in_buffer() const noexcept -> size_t
39 : {
40 26333 : return SPB_READ_BUFFER_SIZE - end_index;
41 : }
42 :
43 27608 : void shift_data_to_start() noexcept
44 : {
45 27608 : if (begin_index > 0)
46 : {
47 47016 : memmove(buffer.data(), buffer.data() + begin_index, bytes_in_buffer());
48 23508 : end_index -= begin_index;
49 23508 : begin_index = 0;
50 : }
51 27608 : }
52 :
53 27608 : void read_buffer()
54 : {
55 27608 : shift_data_to_start();
56 :
57 53941 : while (bytes_in_buffer() < SPB_READ_BUFFER_SIZE && !eof_reached)
58 : {
59 26333 : auto bytes_in = on_read(&buffer[end_index], space_left_in_buffer());
60 26333 : eof_reached |= bytes_in == 0;
61 26333 : end_index += bytes_in;
62 : }
63 27608 : }
64 :
65 : public:
66 3941 : explicit buffered_reader(io::reader reader) : on_read(reader)
67 : {
68 3941 : }
69 :
70 36935 : [[nodiscard]] auto view(size_t minimal_size) -> std::string_view
71 : {
72 36935 : minimal_size = std::max<size_t>(minimal_size, 1U);
73 36935 : if (bytes_in_buffer() < minimal_size)
74 27608 : read_buffer();
75 :
76 36935 : return std::string_view(&buffer[begin_index], bytes_in_buffer());
77 : }
78 :
79 39437 : void skip(size_t size) noexcept
80 : {
81 39437 : begin_index += std::min(size, bytes_in_buffer());
82 39437 : }
83 : };
84 :
85 : } // namespace spb::io
|