blob: aa394851a384f9a7c8cf677d0a736423fa80b527 [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: 54633 $
11//
12// Description : implements parser - public interface for CLA parsing and accessing
13// ***************************************************************************
14
Jeff Thompson3d613fd2013-10-15 15:39:04 -070015#ifndef NDNBOOST_RT_CLA_PARSER_IPP_062904GER
16#define NDNBOOST_RT_CLA_PARSER_IPP_062904GER
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070017
18// Boost.Runtime.Parameter
19#include <ndnboost/test/utils/runtime/config.hpp>
20#include <ndnboost/test/utils/runtime/trace.hpp>
21#include <ndnboost/test/utils/runtime/argument.hpp>
22
23#include <ndnboost/test/utils/runtime/cla/argv_traverser.hpp>
24#include <ndnboost/test/utils/runtime/cla/parameter.hpp>
25#include <ndnboost/test/utils/runtime/cla/modifier.hpp>
26#include <ndnboost/test/utils/runtime/cla/validation.hpp>
27#include <ndnboost/test/utils/runtime/cla/parser.hpp>
28
29// Boost.Test
30#include <ndnboost/test/utils/basic_cstring/io.hpp>
31#include <ndnboost/test/utils/foreach.hpp>
32
33// Boost
34#include <ndnboost/lexical_cast.hpp>
35
36namespace ndnboost {
37
Jeff Thompson3d613fd2013-10-15 15:39:04 -070038namespace NDNBOOST_RT_PARAM_NAMESPACE {
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070039
40namespace cla {
41
42// ************************************************************************** //
43// ************** runtime::cla::parser ************** //
44// ************************************************************************** //
45
Jeff Thompson3d613fd2013-10-15 15:39:04 -070046NDNBOOST_RT_PARAM_INLINE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070047parser::parser( cstring program_name )
48{
49 assign_op( m_program_name, program_name, 0 );
50}
51
52//____________________________________________________________________________//
53
Jeff Thompson3d613fd2013-10-15 15:39:04 -070054NDNBOOST_RT_PARAM_INLINE parser::param_iterator
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070055parser::first_param() const
56{
57 return m_parameters.begin();
58}
59
60//____________________________________________________________________________//
61
Jeff Thompson3d613fd2013-10-15 15:39:04 -070062NDNBOOST_RT_PARAM_INLINE parser::param_iterator
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070063parser::last_param() const
64{
65 return m_parameters.end();
66}
67
68//____________________________________________________________________________//
69
Jeff Thompson3d613fd2013-10-15 15:39:04 -070070NDNBOOST_RT_PARAM_INLINE argument const&
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070071parser::valid_argument( cstring string_id ) const
72{
73 const_argument_ptr arg = (*this)[string_id];
74
Jeff Thompson3d613fd2013-10-15 15:39:04 -070075 NDNBOOST_RT_PARAM_VALIDATE_LOGIC( !!arg, "Actual argument for parameter " << string_id << " is not present" );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070076
77 return *arg;
78}
79
80//____________________________________________________________________________//
81
Jeff Thompson3d613fd2013-10-15 15:39:04 -070082NDNBOOST_RT_PARAM_INLINE parser&
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070083parser::operator<<( parameter_ptr new_param )
84{
Jeff Thompson3d613fd2013-10-15 15:39:04 -070085 NDNBOOST_TEST_FOREACH( parameter_ptr, old_param, m_parameters ) {
86 NDNBOOST_RT_PARAM_VALIDATE_LOGIC( !old_param->conflict_with( *new_param ),
87 NDNBOOST_RT_PARAM_LITERAL( "Definition of parameter " ) << new_param->id_2_report() <<
88 NDNBOOST_RT_PARAM_LITERAL( " conflicts with defintion of parameter " ) << old_param->id_2_report() );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070089 }
90
91 m_parameters.push_back( new_param );
92
93 return *this;
94}
95
96//____________________________________________________________________________//
97
Jeff Thompson3d613fd2013-10-15 15:39:04 -070098NDNBOOST_RT_PARAM_INLINE void
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070099parser::parse( int& argc, char_type** argv )
100{
101 if( m_program_name.empty() ) {
102 m_program_name.assign( argv[0] );
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700103 dstring::size_type pos = m_program_name.find_last_of( NDNBOOST_RT_PARAM_LITERAL( "/\\" ) );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700104
105 if( pos != static_cast<dstring::size_type>(cstring::npos) )
106 m_program_name.erase( 0, pos+1 );
107 }
108
109 m_traverser.init( argc, argv );
110
111 try {
112 while( !m_traverser.eoi() ) {
113 parameter_ptr found_param;
114
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700115 NDNBOOST_RT_PARAM_TRACE( "Total " << m_parameters.size() << " parameters registered" );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700116
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700117 NDNBOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
118 NDNBOOST_RT_PARAM_TRACE( "Try parameter " << curr_param->id_2_report() );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700119
120 if( curr_param->matching( m_traverser, !found_param ) ) {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700121 NDNBOOST_RT_PARAM_TRACE( "Match found" );
122 NDNBOOST_RT_CLA_VALIDATE_INPUT( !found_param, (m_traverser.rollback(),m_traverser), "Ambiguous input" );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700123
124 found_param = curr_param;
125 }
126
127 m_traverser.rollback();
128 }
129
130 if( !found_param ) {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700131 NDNBOOST_RT_PARAM_TRACE( "No match found" );
132 NDNBOOST_RT_CLA_VALIDATE_INPUT( m_traverser.handle_mismatch(), m_traverser,
133 NDNBOOST_RT_PARAM_LITERAL( "Unexpected input" ) );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700134
135 continue;
136 }
137
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700138 NDNBOOST_RT_PARAM_TRACE( "Parse argument value" );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700139 found_param->produce_argument( m_traverser );
140
141 m_traverser.commit();
142 }
143
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700144 NDNBOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700145 if( !curr_param->p_optional && !curr_param->actual_argument() ) {
146 curr_param->produce_argument( *this );
147
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700148 NDNBOOST_RT_PARAM_VALIDATE_LOGIC( curr_param->actual_argument(),
149 NDNBOOST_RT_PARAM_LITERAL( "Required argument for parameter " ) << curr_param->id_2_report()
150 << NDNBOOST_RT_PARAM_LITERAL( " is missing" ) );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700151 }
152 }
153 }
154 catch( bad_lexical_cast const& ) {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700155 NDNBOOST_RT_PARAM_REPORT_LOGIC_ERROR(
156 NDNBOOST_RT_PARAM_LITERAL( "String to value convertion error during input parsing" ) );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700157 }
158
159 m_traverser.remainder( argc, argv );
160}
161
162//____________________________________________________________________________//
163
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700164NDNBOOST_RT_PARAM_INLINE const_argument_ptr
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700165parser::operator[]( cstring string_id ) const
166{
167 parameter_ptr found_param;
168
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700169 NDNBOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700170 if( curr_param->responds_to( string_id ) ) {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700171 NDNBOOST_RT_PARAM_VALIDATE_LOGIC( !found_param,
172 NDNBOOST_RT_PARAM_LITERAL( "Ambiguous parameter string id: " ) << string_id );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700173
174 found_param = curr_param;
175 }
176 }
177
178 return found_param ? found_param->actual_argument() : argument_ptr();
179}
180
181//____________________________________________________________________________//
182
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700183NDNBOOST_RT_PARAM_INLINE cstring
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700184parser::get( cstring string_id ) const
185{
186 return get<cstring>( string_id );
187}
188
189//____________________________________________________________________________//
190
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700191NDNBOOST_RT_PARAM_INLINE void
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700192parser::usage( out_stream& ostr )
193{
194 if( m_program_name.empty() )
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700195 assign_op( m_program_name, NDNBOOST_RT_PARAM_CSTRING_LITERAL( "<program>" ), 0 );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700196
197 format_stream fs;
198
199 fs << m_program_name;
200
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700201 NDNBOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
202 fs << NDNBOOST_RT_PARAM_LITERAL( ' ' );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700203
204 if( curr_param->p_optional )
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700205 fs << NDNBOOST_RT_PARAM_LITERAL( '[' );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700206
207 curr_param->usage_info( fs );
208
209 if( curr_param->p_optional )
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700210 fs << NDNBOOST_RT_PARAM_LITERAL( ']' );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700211
212 if( curr_param->p_multiplicable ) {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700213 fs << NDNBOOST_RT_PARAM_CSTRING_LITERAL( " ... " );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700214
215 if( curr_param->p_optional )
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700216 fs << NDNBOOST_RT_PARAM_LITERAL( '[' );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700217
218 curr_param->usage_info( fs );
219
220 if( curr_param->p_optional )
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700221 fs << NDNBOOST_RT_PARAM_LITERAL( ']' );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700222 }
223 }
224
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700225 ostr << NDNBOOST_RT_PARAM_CSTRING_LITERAL( "Usage:\n" ) << fs.str() << std::endl;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700226}
227
228//____________________________________________________________________________//
229
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700230NDNBOOST_RT_PARAM_INLINE void
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700231parser::help( out_stream& ostr )
232{
233 usage( ostr );
234
235 bool need_where = true;
236
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700237 NDNBOOST_TEST_FOREACH( parameter_ptr const&, curr_param, m_parameters ) {
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700238 if( curr_param->p_description->empty() )
239 continue;
240
241 if( need_where ) {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700242 ostr << NDNBOOST_RT_PARAM_CSTRING_LITERAL( "where:\n" );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700243 need_where = false;
244 }
245
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700246 ostr << curr_param->id_2_report() << NDNBOOST_RT_PARAM_CSTRING_LITERAL( " - " ) << curr_param->p_description << std::endl;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700247 }
248}
249
250//____________________________________________________________________________//
251
252} // namespace cla
253
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700254} // namespace NDNBOOST_RT_PARAM_NAMESPACE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700255
256} // namespace ndnboost
257
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700258#endif // NDNBOOST_RT_CLA_PARSER_IPP_062904GER