Ticket #7726: config_file.cpp

File config_file.cpp, 8.1 KB (added by p.brockamp@…, 10 years ago)

Test

Line 
1// (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 models configuration file, it's parameter and parameter namespaces
13// ***************************************************************************
14
15// Boost.Runtime.Parameter
16#include <boost/test/utils/runtime/config.hpp>
17
18#include <boost/test/utils/runtime/file/config_file.hpp>
19#include <boost/test/utils/runtime/validation.hpp>
20
21// Boost.Test
22#include <boost/test/utils/foreach.hpp>
23#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
24#include <boost/test/utils/basic_cstring/io.hpp>
25#include <boost/test/utils/iterator/token_iterator.hpp>
26
27namespace boost {
28
29namespace BOOST_RT_PARAM_NAMESPACE {
30
31namespace file {
32
33// ************************************************************************** //
34// ************** runtime::file::parameter ************** //
35// ************************************************************************** //
36
37parameter::parameter( cstring name, cstring value, param_namespace const& parent )
38: m_parent( parent )
39{
40 assign_op( p_name.value, name, 0 );
41 assign_op( p_value.value, value, 0 );
42}
43
44//____________________________________________________________________________//
45
46std::ostream&
47operator<<( std::ostream& os, parameter const& p )
48{
49 p.m_parent.print_full_name( os );
50
51 return os << p.p_name << " = \"" << p.p_value << "\"";
52}
53
54//____________________________________________________________________________//
55
56// ************************************************************************** //
57// ************** runtime::file::param_namespace ************** //
58// ************************************************************************** //
59
60param_namespace::param_namespace( cstring name, param_namespace const* parent )
61: p_parent( parent )
62{
63 assign_op( p_name.value, name, 0 );
64}
65
66//____________________________________________________________________________//
67
68void
69param_namespace::insert_param( cstring param_name, cstring param_value )
70{
71 BOOST_TEST_FOREACH( parameter const&, p, m_parameters )
72 BOOST_RT_PARAM_VALIDATE_LOGIC( p.p_name != param_name,
73 BOOST_RT_PARAM_LITERAL( "Duplicate parameter " ) << param_name );
74
75 m_parameters.push_back( parameter( param_name, param_value, *this ) );
76}
77
78//____________________________________________________________________________//
79
80param_namespace&
81param_namespace::subnamespace( cstring namespace_name )
82{
83 BOOST_TEST_FOREACH( param_namespace&, subns, m_subnamespaces )
84 if( subns.p_name == namespace_name )
85 return subns;
86
87 m_subnamespaces.push_back( param_namespace( namespace_name, this ) );
88
89 return m_subnamespaces.back();
90}
91
92//____________________________________________________________________________//
93
94void
95param_namespace::clear()
96{
97 m_parameters.clear();
98 m_subnamespaces.clear();
99}
100
101//____________________________________________________________________________//
102
103void
104param_namespace::print_full_name( std::ostream& os ) const
105{
106 if( !p_parent )
107 return;
108
109 p_parent.get()->print_full_name( os );
110
111 os << p_name << "::";
112}
113
114//____________________________________________________________________________//
115
116boost::optional<cstring>
117get_param_value( param_namespace const& where_from,
118 cstring name_part1,
119 cstring name_part2,
120 cstring name_part3,
121 cstring name_part4,
122 cstring name_part5 )
123{
124 if( name_part2.is_empty() ) {
125 boost::optional<cstring> res;
126
127 BOOST_TEST_FOREACH( parameter const&, p, where_from ) {
128 if( p.p_name == name_part1 ) {
129 res = cstring( p.p_value );
130 break;
131 }
132 }
133
134 return res;
135 }
136
137 param_namespace const* sns = get_param_subns( where_from, name_part1 );
138
139 return sns ? get_param_value( *sns, name_part2, name_part3, name_part4, name_part5 )
140 : boost::optional<cstring>();
141}
142
143//____________________________________________________________________________//
144
145cstring
146get_requ_param_value( param_namespace const& where_from,
147 cstring name_part1,
148 cstring name_part2,
149 cstring name_part3,
150 cstring name_part4,
151 cstring name_part5 )
152{
153 boost::optional<cstring> v = get_param_value( where_from, name_part1, name_part2, name_part3, name_part4, name_part5 );
154
155#define APPEND_PART( part ) (part.is_empty() ? "" : "::") << (part.is_empty() ? cstring() : part)
156 BOOST_RT_PARAM_VALIDATE_LOGIC( !!v, BOOST_RT_PARAM_LITERAL( "Required parameter " )
157 << name_part1
158 << APPEND_PART( name_part2 )
159 << APPEND_PART( name_part3 )
160 << APPEND_PART( name_part4 )
161 << APPEND_PART( name_part5 )
162 << BOOST_RT_PARAM_LITERAL( " value is missing" ) );
163#undef APPEND_PART
164
165 return *v;
166}
167
168//____________________________________________________________________________//
169
170param_namespace const*
171get_param_subns( param_namespace const& where_from, cstring namespace_name )
172{
173 param_namespace::sub_ns_const_iterator it = where_from.sub_ns_begin();
174 param_namespace::sub_ns_const_iterator end = where_from.sub_ns_end();
175
176 while( it != end ) {
177 if( it->p_name == namespace_name )
178 return &*it;
179
180 ++it;
181 }
182
183 return 0;
184}
185
186//____________________________________________________________________________//
187
188void
189param_namespace::load_impl( config_file_iterator cf_it,
190 cstring value_marker, cstring value_delimeter, cstring namespace_delimeter )
191{
192 using namespace unit_test;
193
194 while( cf_it != config_file_iterator() ) {
195 string_token_iterator ti( *cf_it, (max_tokens = 2,kept_delimeters = dt_none, dropped_delimeters = value_delimeter) );
196
197 cstring param_name = *ti;
198 cstring param_value = *(++ti);
199
200 param_value.trim( value_marker );
201
202 param_namespace* targ_ns = this;
203
204 while( !param_name.is_empty() ) {
205 cstring::size_type pos = param_name.find( namespace_delimeter );
206 cstring subname( param_name.begin(), pos == cstring::npos ? param_name.size() : pos );
207
208 if( subname.size() == param_name.size() ) {
209 targ_ns->insert_param( param_name, param_value );
210 break;
211 }
212 else {
213 targ_ns = &targ_ns->subnamespace( subname );
214
215 param_name.trim_left( subname.size() + namespace_delimeter.size() );
216 }
217 }
218 ++cf_it;
219 }
220}
221
222//____________________________________________________________________________//
223
224// ************************************************************************** //
225// ************** runtime::file::config_file ************** //
226// ************************************************************************** //
227
228config_file::config_file()
229: param_namespace( cstring() )
230{
231}
232
233//____________________________________________________________________________//
234
235config_file::config_file( cstring file_name )
236: param_namespace( cstring() )
237{
238 load( file_name );
239}
240
241//____________________________________________________________________________//
242
243} // namespace file
244
245} // namespace BOOST_RT_PARAM_NAMESPACE
246
247} // namespace boost
248
249// EOF