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