1 // Copyright (c) 2016-2018 Dr. Colin Hirsch and Daniel Frey
2 // Please see LICENSE for license or visit https://github.com/taocpp/PEGTL/
3 
4 #ifndef TAO_PEGTL_BUFFER_INPUT_HPP
5 #define TAO_PEGTL_BUFFER_INPUT_HPP
6 
7 #include <cstddef>
8 #include <cstdint>
9 #include <cstring>
10 #include <memory>
11 #include <string>
12 
13 #include "config.hpp"
14 #include "eol.hpp"
15 #include "memory_input.hpp"
16 #include "position.hpp"
17 #include "tracking_mode.hpp"
18 
19 #include "internal/action_input.hpp"
20 #include "internal/bump_impl.hpp"
21 #include "internal/iterator.hpp"
22 #include "internal/marker.hpp"
23 
24 namespace tao
25 {
26    namespace TAO_PEGTL_NAMESPACE
27    {
28       template< typename Reader, typename Eol = eol::lf_crlf, typename Source = std::string >
29       class buffer_input
30       {
31       public:
32          static constexpr tracking_mode tracking_mode_v = tracking_mode::IMMEDIATE;
33          using reader_t = Reader;
34 
35          using eol_t = Eol;
36          using source_t = Source;
37 
38          using iterator_t = internal::iterator;
39 
40          using action_t = internal::action_input< buffer_input >;
41 
42          template< typename T, typename... As >
buffer_input(T && in_source,const std::size_t maximum,As &&...as)43          buffer_input( T&& in_source, const std::size_t maximum, As&&... as )
44             : m_reader( std::forward< As >( as )... ),
45               m_maximum( maximum ),
46               m_buffer( new char[ maximum ] ),
47               m_current( m_buffer.get() ),
48               m_end( m_buffer.get() ),
49               m_source( std::forward< T >( in_source ) )
50          {
51          }
52 
53          buffer_input( const buffer_input& ) = delete;
54          buffer_input( buffer_input&& ) = delete;
55 
56          ~buffer_input() = default;
57 
58          void operator=( const buffer_input& ) = delete;
59          void operator=( buffer_input&& ) = delete;
60 
empty()61          bool empty()
62          {
63             require( 1 );
64             return m_current.data == m_end;
65          }
66 
size(const std::size_t amount)67          std::size_t size( const std::size_t amount )
68          {
69             require( amount );
70             return std::size_t( m_end - m_current.data );
71          }
72 
current() const73          const char* current() const noexcept
74          {
75             return m_current.data;
76          }
77 
end(const std::size_t amount)78          const char* end( const std::size_t amount )
79          {
80             require( amount );
81             return m_end;
82          }
83 
byte() const84          std::size_t byte() const noexcept
85          {
86             return m_current.byte;
87          }
88 
line() const89          std::size_t line() const noexcept
90          {
91             return m_current.line;
92          }
93 
byte_in_line() const94          std::size_t byte_in_line() const noexcept
95          {
96             return m_current.byte_in_line;
97          }
98 
source() const99          const Source& source() const noexcept
100          {
101             return m_source;
102          }
103 
peek_char(const std::size_t offset=0) const104          char peek_char( const std::size_t offset = 0 ) const noexcept
105          {
106             return m_current.data[ offset ];
107          }
108 
peek_byte(const std::size_t offset=0) const109          std::uint8_t peek_byte( const std::size_t offset = 0 ) const noexcept
110          {
111             return static_cast< std::uint8_t >( peek_char( offset ) );
112          }
113 
bump(const std::size_t in_count=1)114          void bump( const std::size_t in_count = 1 ) noexcept
115          {
116             internal::bump( m_current, in_count, Eol::ch );
117          }
118 
bump_in_this_line(const std::size_t in_count=1)119          void bump_in_this_line( const std::size_t in_count = 1 ) noexcept
120          {
121             internal::bump_in_this_line( m_current, in_count );
122          }
123 
bump_to_next_line(const std::size_t in_count=1)124          void bump_to_next_line( const std::size_t in_count = 1 ) noexcept
125          {
126             internal::bump_to_next_line( m_current, in_count );
127          }
128 
discard()129          void discard() noexcept
130          {
131             const auto s = m_end - m_current.data;
132             std::memmove( m_buffer.get(), m_current.data, s );
133             m_current.data = m_buffer.get();
134             m_end = m_buffer.get() + s;
135          }
136 
require(const std::size_t amount)137          void require( const std::size_t amount )
138          {
139             if( m_current.data + amount > m_end ) {
140                if( m_current.data + amount <= m_buffer.get() + m_maximum ) {
141                   if( const auto r = m_reader( m_end, amount - std::size_t( m_end - m_current.data ) ) ) {
142                      m_end += r;
143                   }
144                   else {
145                      m_maximum = 0;
146                   }
147                }
148             }
149          }
150 
151          template< rewind_mode M >
mark()152          internal::marker< iterator_t, M > mark() noexcept
153          {
154             return internal::marker< iterator_t, M >( m_current );
155          }
156 
position(const iterator_t & it) const157          TAO_PEGTL_NAMESPACE::position position( const iterator_t& it ) const
158          {
159             return TAO_PEGTL_NAMESPACE::position( it, m_source );
160          }
161 
position() const162          TAO_PEGTL_NAMESPACE::position position() const
163          {
164             return position( m_current );
165          }
166 
iterator() const167          const iterator_t& iterator() const noexcept
168          {
169             return m_current;
170          }
171 
172       private:
173          Reader m_reader;
174          std::size_t m_maximum;
175          std::unique_ptr< char[] > m_buffer;
176          iterator_t m_current;
177          char* m_end;
178          const Source m_source;
179       };
180 
181    }  // namespace TAO_PEGTL_NAMESPACE
182 
183 }  // namespace tao
184 
185 #endif
186