blob: 4f6709bff2614216f25f46856cb07a6e0e03408c [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: 57992 $
11//
12// Description : generic typed_argument_factory implementation
13// ***************************************************************************
14
15#ifndef BOOST_RT_CLA_ARGUMENT_FACTORY_HPP_062604GER
16#define BOOST_RT_CLA_ARGUMENT_FACTORY_HPP_062604GER
17
18// Boost.Runtime.Parameter
19#include <ndnboost/test/utils/runtime/config.hpp>
20
21#include <ndnboost/test/utils/runtime/fwd.hpp>
22#include <ndnboost/test/utils/runtime/validation.hpp>
23#include <ndnboost/test/utils/runtime/argument.hpp>
24#include <ndnboost/test/utils/runtime/trace.hpp>
25#include <ndnboost/test/utils/runtime/interpret_argument_value.hpp>
26
27#include <ndnboost/test/utils/runtime/cla/fwd.hpp>
28#include <ndnboost/test/utils/runtime/cla/value_generator.hpp>
29#include <ndnboost/test/utils/runtime/cla/value_handler.hpp>
30#include <ndnboost/test/utils/runtime/cla/validation.hpp>
31#include <ndnboost/test/utils/runtime/cla/argv_traverser.hpp>
32#include <ndnboost/test/utils/runtime/cla/detail/argument_value_usage.hpp>
33
34#include <ndnboost/test/utils/runtime/cla/iface/argument_factory.hpp>
35
36// Boost.Test
37#include <ndnboost/test/utils/callback.hpp>
38
39// Boost
40#include <ndnboost/optional.hpp>
41
42namespace ndnboost {
43
44namespace BOOST_RT_PARAM_NAMESPACE {
45
46namespace cla {
47
48// ************************************************************************** //
49// ************** default_value_interpreter ************** //
50// ************************************************************************** //
51
52namespace rt_cla_detail {
53
54struct default_value_interpreter {
55 template<typename T>
56 void operator()( argv_traverser& tr, ndnboost::optional<T>& value )
57 {
58 if( interpret_argument_value( tr.token(), value, 0 ) )
59 tr.next_token();
60 }
61};
62
63} // namespace rt_cla_detail
64
65// ************************************************************************** //
66// ************** typed_argument_factory ************** //
67// ************************************************************************** //
68
69template<typename T>
70struct typed_argument_factory : public argument_factory {
71 // Constructor
72 typed_argument_factory()
73 : m_value_interpreter( rt_cla_detail::default_value_interpreter() )
74 {}
75 BOOST_RT_PARAM_UNNEEDED_VIRTUAL ~typed_argument_factory() {}
76
77 // properties modification
78 template<typename Modifier>
79 void accept_modifier( Modifier const& m )
80 {
81 optionally_assign( m_value_handler, m, handler );
82 optionally_assign( m_value_interpreter, m, interpreter );
83
84 if( m.has( default_value ) ) {
85 BOOST_RT_PARAM_VALIDATE_LOGIC( !m_value_generator,
86 BOOST_RT_PARAM_LITERAL( "multiple value generators for parameter" ) );
87
88 T const& dv_ref = m[default_value];
89 m_value_generator = rt_cla_detail::const_generator<T>( dv_ref );
90 }
91
92 if( m.has( default_refer_to ) ) {
93 BOOST_RT_PARAM_VALIDATE_LOGIC( !m_value_generator,
94 BOOST_RT_PARAM_LITERAL( "multiple value generators for parameter" ) );
95
96 cstring ref_id = m[default_refer_to];
97 m_value_generator = rt_cla_detail::ref_generator<T>( ref_id );
98 }
99
100 if( m.has( assign_to ) ) {
101 BOOST_RT_PARAM_VALIDATE_LOGIC( !m_value_handler,
102 BOOST_RT_PARAM_LITERAL( "multiple value handlers for parameter" ) );
103
104 m_value_handler = rt_cla_detail::assigner<T>( m[assign_to] );
105 }
106 }
107
108 // Argument factory implementation
109 virtual argument_ptr produce_using( parameter& p, argv_traverser& tr );
110 virtual argument_ptr produce_using( parameter& p, parser const& );
111 virtual void argument_usage_info( format_stream& fs );
112
113// !! private?
114 // Data members
115 unit_test::callback2<parameter const&,T&> m_value_handler;
116 unit_test::callback2<parser const&,ndnboost::optional<T>&> m_value_generator;
117 unit_test::callback2<argv_traverser&,ndnboost::optional<T>&> m_value_interpreter;
118};
119
120//____________________________________________________________________________//
121
122template<typename T>
123inline argument_ptr
124typed_argument_factory<T>::produce_using( parameter& p, argv_traverser& tr )
125{
126 ndnboost::optional<T> value;
127
128 try {
129 m_value_interpreter( tr, value );
130 }
131 catch( ... ) { // !! should we do that?
132 BOOST_RT_PARAM_TRACE( "Fail to parse argument value" );
133
134 if( !p.p_optional_value )
135 throw;
136 }
137
138 argument_ptr actual_arg = p.actual_argument();
139
140 BOOST_RT_CLA_VALIDATE_INPUT( !!value || p.p_optional_value, tr,
141 BOOST_RT_PARAM_LITERAL( "Argument value missing for parameter " ) << p.id_2_report() );
142
143 BOOST_RT_CLA_VALIDATE_INPUT( !actual_arg || p.p_multiplicable, tr,
144 BOOST_RT_PARAM_LITERAL( "Unexpected repetition of the parameter " ) << p.id_2_report() );
145
146 if( !!value && !!m_value_handler )
147 m_value_handler( p, *value );
148
149 if( !p.p_multiplicable )
150 actual_arg.reset( p.p_optional_value && (rtti::type_id<T>() != rtti::type_id<bool>())
151 ? static_cast<argument*>(new typed_argument<ndnboost::optional<T> >( p, value ))
152 : static_cast<argument*>(new typed_argument<T>( p, *value )) );
153 else {
154 typedef std::list<ndnboost::optional<T> > optional_list;
155
156 if( !actual_arg )
157 actual_arg.reset( p.p_optional_value
158 ? static_cast<argument*>(new typed_argument<optional_list>( p ))
159 : static_cast<argument*>(new typed_argument<std::list<T> >( p )) );
160
161 if( p.p_optional_value ) {
162 optional_list& values = arg_value<optional_list>( *actual_arg );
163
164 values.push_back( value );
165 }
166 else {
167 std::list<T>& values = arg_value<std::list<T> >( *actual_arg );
168
169 values.push_back( *value );
170 }
171 }
172
173 return actual_arg;
174}
175
176//____________________________________________________________________________//
177
178template<typename T>
179inline argument_ptr
180typed_argument_factory<T>::produce_using( parameter& p, parser const& pa )
181{
182 argument_ptr actual_arg;
183
184 if( !m_value_generator )
185 return actual_arg;
186
187 ndnboost::optional<T> value;
188 m_value_generator( pa, value );
189
190 if( !value )
191 return actual_arg;
192
193 if( !!m_value_handler )
194 m_value_handler( p, *value );
195
196 actual_arg.reset( new typed_argument<T>( p, *value ) );
197
198 return actual_arg;
199}
200
201//____________________________________________________________________________//
202
203template<typename T>
204inline void
205typed_argument_factory<T>::argument_usage_info( format_stream& fs )
206{
207 rt_cla_detail::argument_value_usage( fs, 0, reinterpret_cast<T*>(0) );
208}
209
210//____________________________________________________________________________//
211
212} // namespace ndnboost
213
214} // namespace BOOST_RT_PARAM_NAMESPACE
215
216} // namespace cla
217
218#endif // BOOST_RT_CLA_ARGUMENT_FACTORY_HPP_062604GER