1 //  (C) Copyright Gennadiy Rozental 2001.
2 //  Distributed under the Boost Software License, Version 1.0.
3 //  (See accompanying file LICENSE_1_0.txt or copy at
4 //  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$
11 //
12 //  Description : argument factories for different kinds of parameters
13 // ***************************************************************************
14 
15 #ifndef BOOST_TEST_UTILS_RUNTIME_ARGUMENT_FACTORY_HPP
16 #define BOOST_TEST_UTILS_RUNTIME_ARGUMENT_FACTORY_HPP
17 
18 // Boost.Test Runtime parameters
19 #include <boost/test/utils/runtime/errors.hpp>
20 #include <boost/test/utils/runtime/argument.hpp>
21 #include <boost/test/utils/runtime/modifier.hpp>
22 
23 // Boost.Test
24 #include <boost/test/utils/basic_cstring/io.hpp>
25 #include <boost/test/utils/basic_cstring/compare.hpp>
26 #include <boost/test/utils/string_cast.hpp>
27 
28 // Boost
29 #include <boost/function/function2.hpp>
30 
31 // STL
32 #include <vector>
33 
34 #include <boost/test/detail/suppress_warnings.hpp>
35 
36 namespace boost {
37 namespace runtime {
38 
39 // ************************************************************************** //
40 // **************          runtime::value_interpreter          ************** //
41 // ************************************************************************** //
42 
43 template<typename ValueType, bool is_enum>
44 struct value_interpreter;
45 
46 //____________________________________________________________________________//
47 
48 template<typename ValueType>
49 struct value_interpreter<ValueType, false> {
50     template<typename Modifiers>
value_interpreterboost::runtime::value_interpreter51     explicit    value_interpreter( Modifiers const& ) {}
52 
interpretboost::runtime::value_interpreter53     ValueType interpret( cstring param_name, cstring source ) const
54     {
55         ValueType res;
56         if( !unit_test::utils::string_as<ValueType>( source, res ) )
57             BOOST_TEST_I_THROW( format_error( param_name ) << source <<
58                                 " can't be interpreted as value of parameter " << param_name << "." );
59         return res;
60     }
61 };
62 
63 //____________________________________________________________________________//
64 
65 template<>
66 struct value_interpreter<std::string, false> {
67     template<typename Modifiers>
value_interpreterboost::runtime::value_interpreter68     explicit    value_interpreter( Modifiers const& ) {}
69 
interpretboost::runtime::value_interpreter70     std::string interpret( cstring, cstring source ) const
71     {
72         return std::string( source.begin(), source.size() );
73     }
74 };
75 
76 //____________________________________________________________________________//
77 
78 template<>
79 struct value_interpreter<cstring, false> {
80     template<typename Modifiers>
value_interpreterboost::runtime::value_interpreter81     explicit    value_interpreter( Modifiers const& ) {}
82 
interpretboost::runtime::value_interpreter83     cstring interpret( cstring, cstring source ) const
84     {
85         return source;
86     }
87 };
88 
89 //____________________________________________________________________________//
90 
91 template<>
92 struct value_interpreter<bool, false> {
93     template<typename Modifiers>
value_interpreterboost::runtime::value_interpreter94     explicit    value_interpreter( Modifiers const& ) {}
95 
interpretboost::runtime::value_interpreter96     bool    interpret( cstring param_name, cstring source ) const
97     {
98         static cstring const s_YES( "YES" );
99         static cstring const s_Y( "Y" );
100         static cstring const s_NO( "NO" );
101         static cstring const s_N( "N" );
102         static cstring const s_TRUE( "TRUE" );
103         static cstring const s_FALSE( "FALSE" );
104         static cstring const s_one( "1" );
105         static cstring const s_zero( "0" );
106 
107         source.trim();
108 
109         if( source.is_empty() ||
110             case_ins_eq( source, s_YES ) ||
111             case_ins_eq( source, s_Y ) ||
112             case_ins_eq( source, s_one ) ||
113             case_ins_eq( source, s_TRUE ) )
114             return true;
115 
116         if( case_ins_eq( source, s_NO ) ||
117             case_ins_eq( source, s_N ) ||
118             case_ins_eq( source, s_zero ) ||
119             case_ins_eq( source, s_FALSE ) )
120             return false;
121 
122         BOOST_TEST_I_THROW( format_error( param_name ) << source << " can't be interpreted as bool value." );
123     }
124 };
125 
126 //____________________________________________________________________________//
127 
128 template<typename EnumType>
129 struct value_interpreter<EnumType, true> {
130     template<typename Modifiers>
value_interpreterboost::runtime::value_interpreter131     explicit        value_interpreter( Modifiers const& m )
132 #if defined(BOOST_TEST_CLA_NEW_API)
133     : m_name_to_value( m[enum_values<EnumType>::value] )
134     {
135     }
136 #else
137     {
138         std::vector<std::pair<cstring,EnumType> > const& values = m[enum_values<EnumType>::value];
139 
140         m_name_to_value.insert( values.begin(), values.end() );
141     }
142 #endif
143 
interpretboost::runtime::value_interpreter144     EnumType        interpret( cstring param_name, cstring source ) const
145     {
146         typename std::map<cstring,EnumType>::const_iterator found = m_name_to_value.find( source );
147 
148         BOOST_TEST_I_ASSRT( found != m_name_to_value.end(),
149                             format_error( param_name ) << source <<
150                             " is not a valid enumeration value name for parameter " << param_name << "." );
151 
152         return found->second;
153     }
154 
155 private:
156     // Data members
157     std::map<cstring,EnumType>  m_name_to_value;
158 };
159 
160 //____________________________________________________________________________//
161 
162 // ************************************************************************** //
163 // **************           runtime::argument_factory          ************** //
164 // ************************************************************************** //
165 
166 template<typename ValueType, bool is_enum, bool repeatable>
167 class argument_factory;
168 
169 //____________________________________________________________________________//
170 
171 template<typename ValueType, bool is_enum>
172 class argument_factory<ValueType, is_enum, false> {
173 public:
174     template<typename Modifiers>
argument_factory(Modifiers const & m)175     explicit    argument_factory( Modifiers const& m )
176     : m_interpreter( m )
177     , m_optional_value( nfp::opt_get( m, optional_value, ValueType() ) )
178     , m_default_value( nfp::opt_get( m, default_value, ValueType() ) )
179     {
180     }
181 
produce_argument(cstring source,cstring param_name,arguments_store & store) const182     void        produce_argument( cstring source, cstring param_name, arguments_store& store ) const
183     {
184         store.set( param_name, source.empty() ? m_optional_value : m_interpreter.interpret( param_name, source ) );
185     }
186 
produce_default(cstring param_name,arguments_store & store) const187     void        produce_default( cstring param_name, arguments_store& store ) const
188     {
189         store.set( param_name, m_default_value );
190     }
191 
192 private:
193     // Data members
194     typedef value_interpreter<ValueType, is_enum> interp_t;
195     interp_t    m_interpreter;
196     ValueType   m_optional_value;
197     ValueType   m_default_value;
198 };
199 
200 //____________________________________________________________________________//
201 
202 template<typename ValueType, bool is_enum>
203 class argument_factory<ValueType, is_enum, true> {
204 public:
205     template<typename Modifiers>
argument_factory(Modifiers const & m)206     explicit    argument_factory( Modifiers const& m )
207     : m_interpreter( m )
208     {
209     }
210 
produce_argument(cstring source,cstring param_name,arguments_store & store) const211     void        produce_argument( cstring source, cstring param_name, arguments_store& store ) const
212     {
213         ValueType value = m_interpreter.interpret( param_name, source );
214 
215         if( store.has( param_name ) ) {
216             std::vector<ValueType>& values = store.get<std::vector<ValueType> >( param_name );
217             values.push_back( value );
218         }
219         else {
220             std::vector<ValueType> values( 1, value );
221 
222             store.set( param_name, values );
223         }
224 
225     }
produce_default(cstring param_name,arguments_store & store) const226     void        produce_default( cstring param_name, arguments_store& store ) const
227     {
228         store.set( param_name, std::vector<ValueType>() );
229     }
230 
231 private:
232     // Data members
233     value_interpreter<ValueType, is_enum> m_interpreter;
234 };
235 
236 //____________________________________________________________________________//
237 
238 } // namespace runtime
239 } // namespace boost
240 
241 #include <boost/test/detail/enable_warnings.hpp>
242 
243 #endif // BOOST_TEST_UTILS_RUNTIME_ARGUMENT_FACTORY_HPP
244