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