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 181491 : auto bytes_in_buffer( ) const noexcept -> size_t
34 : {
35 181491 : return end_index - begin_index;
36 : }
37 :
38 26041 : auto space_left_in_buffer( ) const noexcept -> size_t
39 : {
40 26041 : return SPB_READ_BUFFER_SIZE - end_index;
41 : }
42 :
43 26995 : void shift_data_to_start( ) noexcept
44 : {
45 26995 : if( begin_index > 0 )
46 : {
47 46082 : memmove( buffer.data( ), buffer.data( ) + begin_index, bytes_in_buffer( ) );
48 23041 : end_index -= begin_index;
49 23041 : begin_index = 0;
50 : }
51 26995 : }
52 :
53 26995 : void read_buffer( )
54 : {
55 26995 : shift_data_to_start( );
56 :
57 53036 : while( bytes_in_buffer( ) < SPB_READ_BUFFER_SIZE && !eof_reached )
58 : {
59 26041 : auto bytes_in = on_read( &buffer[ end_index ], space_left_in_buffer( ) );
60 26041 : eof_reached |= bytes_in == 0;
61 26041 : end_index += bytes_in;
62 : }
63 26995 : }
64 :
65 : public:
66 3795 : explicit buffered_reader( io::reader reader )
67 3795 : : on_read( reader )
68 : {
69 3795 : }
70 :
71 34576 : [[nodiscard]] auto view( size_t minimal_size ) -> std::string_view
72 : {
73 34576 : minimal_size = std::max< size_t >( minimal_size, 1U );
74 34576 : if( bytes_in_buffer( ) < minimal_size )
75 : {
76 26995 : read_buffer( );
77 : }
78 34576 : return std::string_view( &buffer[ begin_index ], bytes_in_buffer( ) );
79 : }
80 :
81 36262 : void skip( size_t size ) noexcept
82 : {
83 36262 : begin_index += std::min( size, bytes_in_buffer( ) );
84 36262 : }
85 : };
86 :
87 : }// namespace spb::io
|