blob: da03cd9b72a092f5109cf0991e0b173476011fd4 [file] [log] [blame]
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001// (C) Copyright Gennadiy Rozental 2005-2008.
2// Use, modification, and distribution are subject to the
3// Boost Software License, Version 1.0. (See accompanying file
4// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6// See http://www.boost.org/libs/test for the library home page.
7//
8// File : $RCSfile$
9//
10// Version : $Revision: 49312 $
11//
12// Description : implements facility to hide input traversing details
13// ***************************************************************************
14
15#ifndef BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER
16#define BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER
17
18// Boost.Runtime.Parameter
19#include <ndnboost/test/utils/runtime/trace.hpp>
20
21#include <ndnboost/test/utils/runtime/cla/argv_traverser.hpp>
22
23// STL
24#include <memory>
25#include <cstring>
26
27#ifdef BOOST_NO_STDC_NAMESPACE
28namespace std { using ::memcpy; }
29#endif
30
31namespace ndnboost {
32
33namespace BOOST_RT_PARAM_NAMESPACE {
34
35namespace cla {
36
37// ************************************************************************** //
38// ************** runtime::cla::argv_traverser ************** //
39// ************************************************************************** //
40
41BOOST_RT_PARAM_INLINE
42argv_traverser::argv_traverser()
43: p_ignore_mismatch( false ), p_separator( BOOST_RT_PARAM_LITERAL( ' ' ) )
44{
45}
46
47//____________________________________________________________________________//
48
49BOOST_RT_PARAM_INLINE void
50argv_traverser::init( int argc, char_type** argv )
51{
52 for( int index = 1; index < argc; ++index ) {
53 m_buffer += argv[index];
54 if( index != argc-1 )
55 m_buffer += BOOST_RT_PARAM_LITERAL( ' ' );
56 }
57
58 m_remainder.reset( new char_type[m_buffer.size()+1] );
59 m_remainder_size = 0;
60 m_work_buffer = m_buffer;
61 m_commited_end = m_work_buffer.begin();
62
63 BOOST_RT_PARAM_TRACE( "Input buffer: " << m_buffer );
64
65 next_token();
66}
67
68//____________________________________________________________________________//
69
70BOOST_RT_PARAM_INLINE void
71argv_traverser::remainder( int& argc, char_type** argv )
72{
73 argc = 1;
74 std::size_t pos = 0;
75 while(pos < m_remainder_size ) {
76 argv[argc++] = m_remainder.get() + pos;
77
78 pos = std::find( m_remainder.get() + pos, m_remainder.get() + m_remainder_size,
79 BOOST_RT_PARAM_LITERAL( ' ' ) ) - m_remainder.get();
80 m_remainder[pos++] = BOOST_RT_PARAM_LITERAL( '\0' );
81 }
82}
83
84//____________________________________________________________________________//
85
86BOOST_RT_PARAM_INLINE cstring
87argv_traverser::token() const
88{
89 return m_token;
90}
91
92//____________________________________________________________________________//
93
94BOOST_RT_PARAM_INLINE void
95argv_traverser::next_token()
96{
97 if( m_work_buffer.is_empty() )
98 return;
99
100 m_work_buffer.trim_left( m_token.size() ); // skip remainder of current token
101
102 if( m_work_buffer.size() != m_buffer.size() ) // !! is there a better way to identify first token
103 m_work_buffer.trim_left( 1 ); // skip separator if not first token;
104
105 m_token.assign( m_work_buffer.begin(),
106 std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) );
107}
108
109//____________________________________________________________________________//
110
111BOOST_RT_PARAM_INLINE cstring
112argv_traverser::input() const
113{
114 return m_work_buffer;
115}
116
117//____________________________________________________________________________//
118
119BOOST_RT_PARAM_INLINE void
120argv_traverser::trim( std::size_t size )
121{
122 m_work_buffer.trim_left( size );
123
124 if( size <= m_token.size() )
125 m_token.trim_left( size );
126 else {
127 m_token.assign( m_work_buffer.begin(),
128 std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) );
129 }
130}
131
132//____________________________________________________________________________//
133
134BOOST_RT_PARAM_INLINE bool
135argv_traverser::match_front( cstring str )
136{
137 return m_work_buffer.size() < str.size() ? false : m_work_buffer.substr( 0, str.size() ) == str;
138}
139
140//____________________________________________________________________________//
141
142BOOST_RT_PARAM_INLINE bool
143argv_traverser::match_front( char_type c )
144{
145 return first_char( m_work_buffer ) == c;
146}
147
148//____________________________________________________________________________//
149
150BOOST_RT_PARAM_INLINE bool
151argv_traverser::eoi() const
152{
153 return m_work_buffer.is_empty();
154}
155
156//____________________________________________________________________________//
157
158BOOST_RT_PARAM_INLINE void
159argv_traverser::commit()
160{
161 m_commited_end = m_work_buffer.begin();
162}
163
164//____________________________________________________________________________//
165
166BOOST_RT_PARAM_INLINE void
167argv_traverser::rollback()
168{
169 m_work_buffer.assign( m_commited_end, m_work_buffer.end() );
170 m_token.assign( m_work_buffer.begin(),
171 std::find( m_work_buffer.begin(), m_work_buffer.end(), p_separator ) );
172
173}
174
175//____________________________________________________________________________//
176
177BOOST_RT_PARAM_INLINE std::size_t
178argv_traverser::input_pos() const
179{
180 return m_work_buffer.begin() - m_commited_end;
181}
182
183//____________________________________________________________________________//
184
185BOOST_RT_PARAM_INLINE bool
186argv_traverser::handle_mismatch()
187{
188 if( !p_ignore_mismatch )
189 return false;
190
191 std::memcpy( m_remainder.get() + m_remainder_size, token().begin(), token().size() );
192 m_remainder_size += token().size();
193 m_remainder[m_remainder_size++] = p_separator;
194
195 next_token();
196 commit();
197
198 return true;
199}
200
201//____________________________________________________________________________//
202
203} // namespace cla
204
205} // namespace BOOST_RT_PARAM_NAMESPACE
206
207} // namespace ndnboost
208
209#endif // BOOST_RT_CLA_ARGV_TRAVERSER_IPP_070604GER