1 // Copyright (c) 2014-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_MEMORY_INPUT_HPP
5 #define TAO_PEGTL_MEMORY_INPUT_HPP
6 
7 #include <cstddef>
8 #include <cstring>
9 #include <string>
10 #include <type_traits>
11 #include <utility>
12 
13 #include "config.hpp"
14 #include "eol.hpp"
15 #include "position.hpp"
16 #include "tracking_mode.hpp"
17 
18 #include "internal/action_input.hpp"
19 #include "internal/bump_impl.hpp"
20 #include "internal/iterator.hpp"
21 #include "internal/marker.hpp"
22 
23 namespace tao
24 {
25    namespace TAO_PEGTL_NAMESPACE
26    {
27       namespace internal
28       {
29          template< tracking_mode, typename Eol, typename Source >
30          class memory_input_base;
31 
32          template< typename Eol, typename Source >
33          class memory_input_base< tracking_mode::IMMEDIATE, Eol, Source >
34          {
35          public:
36             using iterator_t = internal::iterator;
37 
38             template< typename T >
memory_input_base(const iterator_t & in_begin,const char * in_end,T && in_source)39             memory_input_base( const iterator_t& in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value )
40                : m_current( in_begin ),
41                  m_end( in_end ),
42                  m_source( std::forward< T >( in_source ) )
43             {
44             }
45 
46             template< typename T >
memory_input_base(const char * in_begin,const char * in_end,T && in_source)47             memory_input_base( const char* in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value )
48                : m_current( in_begin ),
49                  m_end( in_end ),
50                  m_source( std::forward< T >( in_source ) )
51             {
52             }
53 
54             memory_input_base( const memory_input_base& ) = delete;
55             memory_input_base( memory_input_base&& ) = delete;
56 
57             ~memory_input_base() = default;
58 
59             memory_input_base operator=( const memory_input_base& ) = delete;
60             memory_input_base operator=( memory_input_base&& ) = delete;
61 
current() const62             const char* current() const noexcept
63             {
64                return m_current.data;
65             }
66 
end(const std::size_t=0) const67             const char* end( const std::size_t /*unused*/ = 0 ) const noexcept
68             {
69                return m_end;
70             }
71 
byte() const72             std::size_t byte() const noexcept
73             {
74                return m_current.byte;
75             }
76 
line() const77             std::size_t line() const noexcept
78             {
79                return m_current.line;
80             }
81 
byte_in_line() const82             std::size_t byte_in_line() const noexcept
83             {
84                return m_current.byte_in_line;
85             }
86 
bump(const std::size_t in_count=1)87             void bump( const std::size_t in_count = 1 ) noexcept
88             {
89                internal::bump( m_current, in_count, Eol::ch );
90             }
91 
bump_in_this_line(const std::size_t in_count=1)92             void bump_in_this_line( const std::size_t in_count = 1 ) noexcept
93             {
94                internal::bump_in_this_line( m_current, in_count );
95             }
96 
bump_to_next_line(const std::size_t in_count=1)97             void bump_to_next_line( const std::size_t in_count = 1 ) noexcept
98             {
99                internal::bump_to_next_line( m_current, in_count );
100             }
101 
position(const iterator_t & it) const102             TAO_PEGTL_NAMESPACE::position position( const iterator_t& it ) const
103             {
104                return TAO_PEGTL_NAMESPACE::position( it, m_source );
105             }
106 
107          protected:
108             iterator_t m_current;
109             const char* const m_end;
110             const Source m_source;
111          };
112 
113          template< typename Eol, typename Source >
114          class memory_input_base< tracking_mode::LAZY, Eol, Source >
115          {
116          public:
117             using iterator_t = const char*;
118 
119             template< typename T >
memory_input_base(const internal::iterator & in_begin,const char * in_end,T && in_source)120             memory_input_base( const internal::iterator& in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value )
121                : m_begin( in_begin ),
122                  m_current( in_begin.data ),
123                  m_end( in_end ),
124                  m_source( std::forward< T >( in_source ) )
125             {
126             }
127 
128             template< typename T >
memory_input_base(const char * in_begin,const char * in_end,T && in_source)129             memory_input_base( const char* in_begin, const char* in_end, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value )
130                : m_begin( in_begin ),
131                  m_current( in_begin ),
132                  m_end( in_end ),
133                  m_source( std::forward< T >( in_source ) )
134             {
135             }
136 
137             memory_input_base( const memory_input_base& ) = delete;
138             memory_input_base( memory_input_base&& ) = delete;
139 
140             ~memory_input_base() = default;
141 
142             memory_input_base operator=( const memory_input_base& ) = delete;
143             memory_input_base operator=( memory_input_base&& ) = delete;
144 
current() const145             const char* current() const noexcept
146             {
147                return m_current;
148             }
149 
end(const std::size_t=0) const150             const char* end( const std::size_t /*unused*/ = 0 ) const noexcept
151             {
152                return m_end;
153             }
154 
byte() const155             std::size_t byte() const noexcept
156             {
157                return std::size_t( current() - m_begin.data );
158             }
159 
bump(const std::size_t in_count=1)160             void bump( const std::size_t in_count = 1 ) noexcept
161             {
162                m_current += in_count;
163             }
164 
bump_in_this_line(const std::size_t in_count=1)165             void bump_in_this_line( const std::size_t in_count = 1 ) noexcept
166             {
167                m_current += in_count;
168             }
169 
bump_to_next_line(const std::size_t in_count=1)170             void bump_to_next_line( const std::size_t in_count = 1 ) noexcept
171             {
172                m_current += in_count;
173             }
174 
position(const iterator_t it) const175             TAO_PEGTL_NAMESPACE::position position( const iterator_t it ) const
176             {
177                internal::iterator c( m_begin );
178                internal::bump( c, std::size_t( it - m_begin.data ), Eol::ch );
179                return TAO_PEGTL_NAMESPACE::position( c, m_source );
180             }
181 
182          protected:
183             const internal::iterator m_begin;
184             iterator_t m_current;
185             const char* const m_end;
186             const Source m_source;
187          };
188 
189       }  // namespace internal
190 
191       template< tracking_mode P = tracking_mode::IMMEDIATE, typename Eol = eol::lf_crlf, typename Source = std::string >
192       class memory_input
193          : public internal::memory_input_base< P, Eol, Source >
194       {
195       public:
196          static constexpr tracking_mode tracking_mode_v = P;
197 
198          using eol_t = Eol;
199          using source_t = Source;
200 
201          using typename internal::memory_input_base< P, Eol, Source >::iterator_t;
202 
203          using action_t = internal::action_input< memory_input >;
204 
205          using internal::memory_input_base< P, Eol, Source >::memory_input_base;
206 
207          template< typename T >
memory_input(const char * in_begin,const std::size_t in_size,T && in_source)208          memory_input( const char* in_begin, const std::size_t in_size, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value )
209             : memory_input( in_begin, in_begin + in_size, std::forward< T >( in_source ) )
210          {
211          }
212 
213          template< typename T >
memory_input(const std::string & in_string,T && in_source)214          memory_input( const std::string& in_string, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value )
215             : memory_input( in_string.data(), in_string.size(), std::forward< T >( in_source ) )
216          {
217          }
218 
219          template< typename T >
220          memory_input( std::string&&, T&& ) = delete;
221 
222          template< typename T >
memory_input(const char * in_begin,T && in_source)223          memory_input( const char* in_begin, T&& in_source ) noexcept( std::is_nothrow_constructible< Source, T&& >::value )
224             : memory_input( in_begin, std::strlen( in_begin ), std::forward< T >( in_source ) )
225          {
226          }
227 
228          template< typename T >
memory_input(const char * in_begin,const char * in_end,T && in_source,const std::size_t in_byte,const std::size_t in_line,const std::size_t in_byte_in_line)229          memory_input( const char* in_begin, const char* in_end, T&& in_source, const std::size_t in_byte, const std::size_t in_line, const std::size_t in_byte_in_line ) noexcept( std::is_nothrow_constructible< Source, T&& >::value )
230             : memory_input( { in_begin, in_byte, in_line, in_byte_in_line }, in_end, std::forward< T >( in_source ) )
231          {
232          }
233 
234          memory_input( const memory_input& ) = delete;
235          memory_input( memory_input&& ) = delete;
236 
237          ~memory_input() = default;
238 
239          memory_input operator=( const memory_input& ) = delete;
240          memory_input operator=( memory_input&& ) = delete;
241 
source() const242          const Source& source() const noexcept
243          {
244             return this->m_source;
245          }
246 
empty() const247          bool empty() const noexcept
248          {
249             return this->current() == this->end();
250          }
251 
size(const std::size_t=0) const252          std::size_t size( const std::size_t /*unused*/ = 0 ) const noexcept
253          {
254             return std::size_t( this->end() - this->current() );
255          }
256 
peek_char(const std::size_t offset=0) const257          char peek_char( const std::size_t offset = 0 ) const noexcept
258          {
259             return this->current()[ offset ];
260          }
261 
peek_byte(const std::size_t offset=0) const262          unsigned char peek_byte( const std::size_t offset = 0 ) const noexcept
263          {
264             return static_cast< unsigned char >( peek_char( offset ) );
265          }
266 
iterator()267          iterator_t& iterator() noexcept
268          {
269             return this->m_current;
270          }
271 
iterator() const272          const iterator_t& iterator() const noexcept
273          {
274             return this->m_current;
275          }
276 
277          using internal::memory_input_base< P, Eol, Source >::position;
278 
position() const279          TAO_PEGTL_NAMESPACE::position position() const
280          {
281             return position( iterator() );
282          }
283 
discard() const284          void discard() const noexcept
285          {
286          }
287 
require(const std::size_t) const288          void require( const std::size_t /*unused*/ ) const noexcept
289          {
290          }
291 
292          template< rewind_mode M >
mark()293          internal::marker< iterator_t, M > mark() noexcept
294          {
295             return internal::marker< iterator_t, M >( iterator() );
296          }
297       };
298 
299    }  // namespace TAO_PEGTL_NAMESPACE
300 
301 }  // namespace tao
302 
303 #endif
304