1 // (C) Copyright Gennadiy Rozental 2005-2014.
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$
11 //
12 // Description : flexible configuration file iterator implementation
13 // ***************************************************************************
14
15 // Boost.Runtime.Parameter
16 #include <boost/test/utils/runtime/config.hpp>
17
18 #include <boost/test/utils/runtime/file/config_file_iterator.hpp>
19 #include <boost/test/utils/runtime/validation.hpp>
20
21 #ifndef UNDER_CE
22 #include <boost/test/utils/runtime/env/environment.hpp>
23 #endif
24
25
26 // Boost
27 #include <boost/scoped_array.hpp>
28 #include <boost/bind.hpp>
29 #include <boost/noncopyable.hpp>
30
31 // Boost.Test
32 #include <boost/test/utils/basic_cstring/compare.hpp>
33 #include <boost/test/utils/algorithm.hpp>
34 #include <boost/test/utils/iterator/token_iterator.hpp>
35 #include <boost/test/utils/assign_op.hpp>
36
37 // STL
38 #include <memory>
39 #include <map>
40 #include <list>
41 #include <vector>
42 #include <fstream>
43 #include <cctype>
44 #include <iostream>
45
46 namespace boost {
47
48 namespace BOOST_TEST_UTILS_RUNTIME_PARAM_NAMESPACE {
49
50 namespace file {
51
52 // ************************************************************************** //
53 // ************** symbol_to_value_map ************** //
54 // ************************************************************************** //
55
56 template<typename ValueType>
57 struct symbol_to_value_map : std::map<cstring, ValueType> {
58 template<typename ParamType>
addboost::BOOST_TEST_UTILS_RUNTIME_PARAM_NAMESPACE::file::symbol_to_value_map59 void add( cstring name, ParamType const& value )
60 {
61 using namespace unit_test;
62
63 m_name_store.push_back( dstring() );
64
65 assign_op( m_name_store.back(), name, 0 );
66 assign_op( (*this)[m_name_store.back()], value, 0 );
67 }
removeboost::BOOST_TEST_UTILS_RUNTIME_PARAM_NAMESPACE::file::symbol_to_value_map68 void remove( cstring name )
69 {
70 std::list<dstring>::iterator it = std::find( m_name_store.begin(), m_name_store.end(), name );
71
72 m_name_store.erase( it );
73
74 this->erase( name );
75 }
76
77 private:
78 std::list<dstring> m_name_store;
79 };
80
81 // ************************************************************************** //
82 // ************** symbol_table_t ************** //
83 // ************************************************************************** //
84
85 typedef symbol_to_value_map<dstring> symbol_table_t;
86
87 // ************************************************************************** //
88 // ************** command_handler_map ************** //
89 // ************************************************************************** //
90
91 typedef symbol_to_value_map<config_file_iterator::command_handler> command_handler_map;
92
93 // ************************************************************************** //
94 // ************** is_valid_identifier ************** //
95 // ************************************************************************** //
96
97 static bool
is_valid_identifier(cstring const & source)98 is_valid_identifier( cstring const& source )
99 {
100 if( source.is_empty() )
101 return false;
102
103 cstring::const_iterator it = source.begin();
104
105 if( !std::isalpha( *it ) )
106 return false;
107
108 while( ++it < source.end() ) {
109 if( !std::isalnum( *it ) && *it != BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( '_' ) && *it != BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( '-' ) )
110 return false;
111 }
112
113 return true;
114 }
115
116 // ************************************************************************** //
117 // ************** include_level ************** //
118 // ************************************************************************** //
119
120 struct include_level;
121 typedef std::auto_ptr<include_level> include_level_ptr;
122
123 struct include_level : noncopyable
124 {
125 // Constructor
126 explicit include_level( cstring file_name, cstring path_separators, include_level* parent = 0 );
127
128 // Data members
129 std::ifstream m_stream;
130 location m_curr_location;
131 include_level_ptr m_parent;
132 };
133
134 //____________________________________________________________________________//
135
include_level(cstring file_name,cstring path_separators,include_level * parent_)136 include_level::include_level( cstring file_name, cstring path_separators, include_level* parent_ )
137 : m_parent( parent_ )
138 {
139 if( file_name.is_empty() )
140 return;
141
142 assign_op( m_curr_location.first, file_name, 0 );
143 m_curr_location.second = 0;
144
145 m_stream.open( m_curr_location.first.c_str() );
146
147 if( !m_stream.is_open() && !!m_parent.get() ) {
148 cstring parent_path = m_parent->m_curr_location.first;
149 cstring::iterator it = unit_test::find_last_of( parent_path.begin(), parent_path.end(),
150 path_separators.begin(),
151 path_separators.end() );
152
153 if( it != parent_path.end() ) {
154 assign_op( m_curr_location.first, cstring( parent_path.begin(), it+1 ), 0 );
155 m_curr_location.first.append( file_name.begin(), file_name.end() );
156 m_stream.clear();
157 m_stream.open( m_curr_location.first.c_str() );
158 }
159 }
160
161 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( m_stream.is_open(), BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "can't open file " ) << file_name );
162 }
163
164 //____________________________________________________________________________//
165
166 // ************************************************************************** //
167 // ************** config_file_iterator::Impl ************** //
168 // ************************************************************************** //
169
170 struct config_file_iterator::Impl : noncopyable {
171 // Constructor
172 Impl();
173
174 bool get_next_line( cstring& next_line );
175
176 void process_command_line( cstring line );
177 void process_include( cstring line );
178 void process_define( cstring line );
179 void process_undef( cstring line );
180 void process_ifdef( cstring line );
181 void process_ifndef( cstring line );
182 void process_else( cstring line );
183 void process_endif( cstring line );
184
185 boost::optional<cstring>
186 get_macro_value( cstring macro_name, bool ignore_missing = true );
187 void substitute_macros( cstring& where );
188
is_active_lineboost::BOOST_TEST_UTILS_RUNTIME_PARAM_NAMESPACE::file::config_file_iterator::Impl189 bool is_active_line() { return m_inactive_ifdef_level == 0; }
190
match_frontboost::BOOST_TEST_UTILS_RUNTIME_PARAM_NAMESPACE::file::config_file_iterator::Impl191 static bool match_front( cstring str, cstring pattern )
192 {
193 return str.size() >= pattern.size() && str.substr( 0, pattern.size() ) == pattern;
194 }
match_backboost::BOOST_TEST_UTILS_RUNTIME_PARAM_NAMESPACE::file::config_file_iterator::Impl195 static bool match_back( cstring str, cstring pattern )
196 {
197 return str.size() >= pattern.size() && str.substr( str.size() - pattern.size() ) == pattern;
198 }
199
200 // Configurable parameters
201 dstring m_path_separators;
202 char_type m_line_delimeter;
203 dstring m_sl_comment_delimeter;
204 dstring m_command_delimeter;
205 dstring m_line_beak;
206 dstring m_macro_ref_begin;
207 dstring m_macro_ref_end;
208
209 dstring m_include_kw;
210 dstring m_define_kw;
211 dstring m_undef_kw;
212 dstring m_ifdef_kw;
213 dstring m_ifndef_kw;
214 dstring m_else_kw;
215 dstring m_endif_kw;
216
217 std::size_t m_buffer_size;
218
219 bool m_trim_trailing_spaces;
220 bool m_trim_leading_spaces;
221 bool m_skip_empty_lines;
222 bool m_detect_missing_macro;
223
224 // Data members
225 dstring m_post_subst_line;
226 scoped_array<char> m_buffer;
227 include_level_ptr m_curr_level;
228 symbol_table_t m_symbols_table;
229 std::vector<bool> m_conditional_states;
230 std::size_t m_inactive_ifdef_level;
231 command_handler_map m_command_handler_map;
232 };
233
234 //____________________________________________________________________________//
235
Impl()236 config_file_iterator::Impl::Impl()
237 : m_path_separators( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "/\\" ) )
238 , m_line_delimeter( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( '\n' ) )
239 , m_sl_comment_delimeter( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "#" ) )
240 , m_command_delimeter( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "$" ) )
241 , m_line_beak( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "\\" ) )
242 , m_macro_ref_begin( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "$" ) )
243 , m_macro_ref_end( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "$" ) )
244
245 , m_include_kw( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "include" ) )
246 , m_define_kw( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "define" ) )
247 , m_undef_kw( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "undef" ) )
248 , m_ifdef_kw( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "ifdef" ) )
249 , m_ifndef_kw( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "ifndef" ) )
250 , m_else_kw( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "else" ) )
251 , m_endif_kw( BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "endif" ) )
252
253 , m_buffer_size( 8192 )
254
255 , m_trim_trailing_spaces( true )
256 , m_trim_leading_spaces( false )
257 , m_skip_empty_lines( true )
258 , m_detect_missing_macro( true )
259
260 , m_inactive_ifdef_level( 0 )
261 {}
262
263 //____________________________________________________________________________//
264
265 bool
get_next_line(cstring & line)266 config_file_iterator::Impl::get_next_line( cstring& line )
267 {
268 bool broken_line = false;
269
270 line.clear();
271
272 while( !m_curr_level->m_stream.eof() || !!m_curr_level->m_parent.get() ) {
273 // 10. Switch to upper include level if current one is finished
274 // 20. Read/append next file line
275 // 30. Increment line number
276 // 40. Remove comments
277 // 50. Remove trailing and leading spaces
278 // 60. Skip empty string
279 // 70. Concatenate broken lines if needed. Put the result into line
280 // 80. If line is not completed, try to finish it by reading the next line
281 // 90. Process command line
282 // 100. Substitute macros references with their definitions
283 // 110. Next line found.
284
285 if( m_curr_level->m_stream.eof() ) { // 10 //
286 m_curr_level = m_curr_level->m_parent;
287 continue;
288 }
289
290 std::ifstream& input = m_curr_level->m_stream;
291 char_type* buffer_insert_pos = broken_line ? m_buffer.get() + line.size() : m_buffer.get();
292
293 input.getline( buffer_insert_pos, (std::streamsize)(m_buffer_size - line.size()), // 20 //
294 m_line_delimeter );
295
296 cstring next_line( buffer_insert_pos,
297 input.gcount() > 0
298 ? buffer_insert_pos + (input.eof() ? input.gcount() : (input.gcount()-1))
299 : buffer_insert_pos );
300
301
302 m_curr_level->m_curr_location.second++; // 30 //
303
304 cstring::size_type comment_pos = next_line.find( m_sl_comment_delimeter );
305 if( comment_pos != cstring::npos )
306 next_line.trim_right( next_line.begin()+comment_pos ); // 40 //
307
308 if( m_trim_trailing_spaces ) // 50 //
309 next_line.trim_right();
310 if( m_trim_leading_spaces && !broken_line )
311 next_line.trim_left();
312
313 if( next_line.is_empty() ) { // 60 //
314 if( m_skip_empty_lines )
315 continue;
316 else
317 next_line.assign( buffer_insert_pos, buffer_insert_pos );
318 }
319
320 line = broken_line ? cstring( line.begin(), next_line.end() ) : next_line; // 70 //
321
322 broken_line = match_back( line, m_line_beak );
323 if( broken_line ) { // 80 //
324 line.trim_right( 1 );
325 continue;
326 }
327
328 if( match_front( line, m_command_delimeter ) ) { // 90 //
329 process_command_line( line );
330 continue;
331 }
332
333 if( !is_active_line() )
334 continue;
335
336 substitute_macros( line ); // 100 //
337
338 return true; // 110 //
339 }
340
341 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( !broken_line, BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "broken line is not completed" ) );
342 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( m_conditional_states.size() == 0,
343 BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "matching endif command is missing" ) );
344
345 return false;
346 }
347
348 //____________________________________________________________________________//
349
350 boost::optional<cstring>
get_macro_value(cstring macro_name,bool ignore_missing)351 config_file_iterator::Impl::get_macro_value( cstring macro_name, bool ignore_missing )
352 {
353 symbol_table_t::const_iterator it = m_symbols_table.find( macro_name );
354
355 if( it == m_symbols_table.end() ) {
356 boost::optional<cstring> macro_value; // !! variable actually may have different type
357
358 #ifndef UNDER_CE
359 env::get( macro_name, macro_value );
360 #endif
361
362 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( macro_value || ignore_missing || !m_detect_missing_macro,
363 BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "Unknown macro \"" ) << macro_name << BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "\"" ) );
364
365 if( !macro_value ) {
366 if( !ignore_missing )
367 macro_value = cstring();
368 }
369 else
370 m_symbols_table.add( macro_name, *macro_value );
371
372 return macro_value;
373 }
374
375 return boost::optional<cstring>( cstring( it->second ) );
376 }
377
378 //____________________________________________________________________________//
379
380 void
process_command_line(cstring line)381 config_file_iterator::Impl::process_command_line( cstring line )
382 {
383 line.trim_left( m_command_delimeter.size() );
384
385 unit_test::string_token_iterator tit( line, unit_test::max_tokens = 2 );
386
387 command_handler_map::const_iterator it = m_command_handler_map.find( *tit );
388
389 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( it != m_command_handler_map.end(), BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "Invalid command " ) << *tit );
390
391 ++tit;
392
393 (it->second)( *tit );
394 }
395
396 //____________________________________________________________________________//
397
398 void
process_include(cstring line)399 config_file_iterator::Impl::process_include( cstring line )
400 {
401 using namespace unit_test;
402
403 if( !is_active_line() )
404 return;
405
406 string_token_iterator tit( line, kept_delimeters = dt_none );
407
408 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( tit != string_token_iterator(),
409 BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "include file name missing" ) );
410
411 cstring include_file_name = *tit;
412
413 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( ++tit == string_token_iterator(),
414 BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "unexpected tokens at the end of include command" ) );
415
416 substitute_macros( include_file_name );
417
418 m_curr_level.reset( new include_level( include_file_name, m_path_separators, m_curr_level.release() ) );
419 }
420
421 //____________________________________________________________________________//
422
423 void
process_define(cstring line)424 config_file_iterator::Impl::process_define( cstring line )
425 {
426 using namespace unit_test;
427
428 if( !is_active_line() )
429 return;
430
431 string_token_iterator tit( line, (kept_delimeters = dt_none, max_tokens = 2 ));
432
433 cstring macro_name = *tit;
434 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
435 BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "invalid macro name" ) );
436
437 cstring macro_value = *(++tit);
438 substitute_macros( macro_value );
439
440 m_symbols_table.add( macro_name, macro_value );
441 }
442
443 //____________________________________________________________________________//
444
445 void
process_undef(cstring line)446 config_file_iterator::Impl::process_undef( cstring line )
447 {
448 if( !is_active_line() )
449 return;
450
451 cstring macro_name = line;
452 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
453 BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "invalid macro name" ) );
454
455 m_symbols_table.remove( macro_name );
456 }
457
458 //____________________________________________________________________________//
459
460 void
process_ifdef(cstring line)461 config_file_iterator::Impl::process_ifdef( cstring line )
462 {
463 m_conditional_states.push_back( true );
464 if( !is_active_line() )
465 return;
466
467 cstring macro_name = line;
468 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
469 BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "invalid macro name" ) );
470
471 if( !get_macro_value( macro_name ) )
472 m_inactive_ifdef_level = m_conditional_states.size();
473 }
474
475 //____________________________________________________________________________//
476
477 void
process_ifndef(cstring line)478 config_file_iterator::Impl::process_ifndef( cstring line )
479 {
480 m_conditional_states.push_back( true );
481 if( !is_active_line() )
482 return;
483
484 cstring macro_name = line;
485 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
486 BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "invalid macro name" ) );
487
488 if( get_macro_value( macro_name ) )
489 m_inactive_ifdef_level = m_conditional_states.size();
490 }
491
492 //____________________________________________________________________________//
493
494 void
process_else(cstring line)495 config_file_iterator::Impl::process_else( cstring line )
496 {
497 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( m_conditional_states.size() > 0 && m_conditional_states.back(),
498 BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "else without matching if" ) );
499
500 m_inactive_ifdef_level = m_conditional_states.size() == m_inactive_ifdef_level ? 0 : m_conditional_states.size();
501
502 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( line.is_empty(), BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "unexpected tokens at the end of else command" ) );
503 }
504
505 //____________________________________________________________________________//
506
507 void
process_endif(cstring line)508 config_file_iterator::Impl::process_endif( cstring line )
509 {
510 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( m_conditional_states.size() > 0, BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "endif without matching if" ) );
511
512 if( m_conditional_states.size() == m_inactive_ifdef_level )
513 m_inactive_ifdef_level = 0;
514
515 m_conditional_states.pop_back();
516 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( line.is_empty(), BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "unexpected tokens at the end of endif command" ) );
517 }
518
519 //____________________________________________________________________________//
520
521 void
substitute_macros(cstring & where)522 config_file_iterator::Impl::substitute_macros( cstring& where )
523 {
524 m_post_subst_line.clear();
525 cstring::size_type pos;
526
527 while( (pos = where.find( m_macro_ref_begin )) != cstring::npos ) {
528 m_post_subst_line.append( where.begin(), pos );
529
530 where.trim_left( where.begin() + pos + m_macro_ref_begin.size() );
531
532 pos = where.find( m_macro_ref_end );
533
534 BOOST_TEST_UTILS_RUNTIME_PARAM_VALIDATE_LOGIC( pos != cstring::npos, BOOST_TEST_UTILS_RUNTIME_PARAM_LITERAL( "incomplete macro reference" ) );
535
536 cstring value = *get_macro_value( where.substr( 0, pos ), false );
537 m_post_subst_line.append( value.begin(), value.size() );
538
539 where.trim_left( where.begin() + pos + m_macro_ref_end.size() );
540 }
541
542 if( !m_post_subst_line.empty() ) {
543 m_post_subst_line.append( where.begin(), where.size() );
544 where = m_post_subst_line;
545 }
546 }
547
548 //____________________________________________________________________________//
549
550 // ************************************************************************** //
551 // ************** runtime::file::config_file_iterator ************** //
552 // ************************************************************************** //
553
554 void
construct()555 config_file_iterator::construct()
556 {
557 m_pimpl.reset( new Impl );
558 }
559
560 //____________________________________________________________________________//
561
562 void
load(cstring file_name)563 config_file_iterator::load( cstring file_name )
564 {
565 m_pimpl->m_curr_level.reset( new include_level( file_name, m_pimpl->m_path_separators ) );
566 m_pimpl->m_buffer.reset( new char[m_pimpl->m_buffer_size] );
567
568 register_command_handler( m_pimpl->m_include_kw, boost::bind( &Impl::process_include, m_pimpl.get(), _1 ) );
569 register_command_handler( m_pimpl->m_define_kw, boost::bind( &Impl::process_define, m_pimpl.get(), _1 ) );
570 register_command_handler( m_pimpl->m_undef_kw, boost::bind( &Impl::process_undef, m_pimpl.get(), _1 ) );
571 register_command_handler( m_pimpl->m_ifdef_kw, boost::bind( &Impl::process_ifdef, m_pimpl.get(), _1 ) );
572 register_command_handler( m_pimpl->m_ifndef_kw, boost::bind( &Impl::process_ifndef, m_pimpl.get(), _1 ) );
573 register_command_handler( m_pimpl->m_else_kw, boost::bind( &Impl::process_else, m_pimpl.get(), _1 ) );
574 register_command_handler( m_pimpl->m_endif_kw, boost::bind( &Impl::process_endif, m_pimpl.get(), _1 ) );
575
576 init();
577 }
578
579 //____________________________________________________________________________//
580
581 location const&
curr_location()582 config_file_iterator::curr_location()
583 {
584 return m_pimpl->m_curr_level->m_curr_location;
585 }
586
587 //____________________________________________________________________________//
588
589 void
register_command_handler(cstring command_kw,command_handler const & ch)590 config_file_iterator::register_command_handler( cstring command_kw, command_handler const& ch )
591 {
592 m_pimpl->m_command_handler_map.add( command_kw, ch );
593 }
594
595 //____________________________________________________________________________//
596
597 bool
get()598 config_file_iterator::get()
599 {
600 return m_pimpl->get_next_line( m_value );
601 }
602
603 //____________________________________________________________________________//
604
605 void
set_parameter(rtti::id_t id,cstring value)606 config_file_iterator::set_parameter( rtti::id_t id, cstring value )
607 {
608 BOOST_RTTI_SWITCH( id ) {
609 BOOST_RTTI_CASE( cfg_detail::path_separators_t )
610 assign_op( m_pimpl->m_path_separators , value, 0 );
611 BOOST_RTTI_CASE( cfg_detail::sl_comment_delimeter_t )
612 assign_op( m_pimpl->m_sl_comment_delimeter , value, 0 );
613 BOOST_RTTI_CASE( cfg_detail::command_delimeter_t )
614 assign_op( m_pimpl->m_command_delimeter , value, 0 );
615 BOOST_RTTI_CASE( cfg_detail::line_beak_t )
616 assign_op( m_pimpl->m_line_beak , value, 0 );
617 BOOST_RTTI_CASE( cfg_detail::macro_ref_begin_t )
618 assign_op( m_pimpl->m_macro_ref_begin , value, 0 );
619 BOOST_RTTI_CASE( cfg_detail::macro_ref_end_t )
620 assign_op( m_pimpl->m_macro_ref_end , value, 0 );
621 BOOST_RTTI_CASE( cfg_detail::include_kw_t )
622 assign_op( m_pimpl->m_include_kw , value, 0 );
623 BOOST_RTTI_CASE( cfg_detail::define_kw_t )
624 assign_op( m_pimpl->m_define_kw , value, 0 );
625 BOOST_RTTI_CASE( cfg_detail::undef_kw_t )
626 assign_op( m_pimpl->m_undef_kw , value, 0 );
627 BOOST_RTTI_CASE( cfg_detail::ifdef_kw_t )
628 assign_op( m_pimpl->m_ifdef_kw , value, 0 );
629 BOOST_RTTI_CASE( cfg_detail::ifndef_kw_t )
630 assign_op( m_pimpl->m_ifndef_kw , value, 0 );
631 BOOST_RTTI_CASE( cfg_detail::else_kw_t )
632 assign_op( m_pimpl->m_else_kw , value, 0 );
633 BOOST_RTTI_CASE( cfg_detail::endif_kw_t )
634 assign_op( m_pimpl->m_endif_kw , value, 0 );
635 }
636 }
637
638 //____________________________________________________________________________//
639
640 void
set_parameter(rtti::id_t id,bool value)641 config_file_iterator::set_parameter( rtti::id_t id, bool value )
642 {
643 BOOST_RTTI_SWITCH( id ) {
644 BOOST_RTTI_CASE( cfg_detail::trim_leading_spaces_t )
645 m_pimpl->m_trim_leading_spaces = value;
646 BOOST_RTTI_CASE( cfg_detail::trim_trailing_spaces_t )
647 m_pimpl->m_trim_trailing_spaces = value;
648 BOOST_RTTI_CASE( cfg_detail::skip_empty_lines_t )
649 m_pimpl->m_skip_empty_lines = value;
650 BOOST_RTTI_CASE( cfg_detail::detect_missing_macro_t )
651 m_pimpl->m_detect_missing_macro = value;
652 }
653 }
654
655 //____________________________________________________________________________//
656
657 void
set_parameter(rtti::id_t id,char_type value)658 config_file_iterator::set_parameter( rtti::id_t id, char_type value )
659 {
660 BOOST_RTTI_SWITCH( id ) {
661 BOOST_RTTI_CASE( cfg_detail::line_delimeter_t )
662 m_pimpl->m_line_delimeter = value;
663 }
664 }
665
666 //____________________________________________________________________________//
667
668 void
set_parameter(rtti::id_t id,std::size_t value)669 config_file_iterator::set_parameter( rtti::id_t id, std::size_t value )
670 {
671 BOOST_RTTI_SWITCH( id ) {
672 BOOST_RTTI_CASE( cfg_detail::buffer_size_t )
673 m_pimpl->m_buffer_size = value;
674 }
675 }
676
677 //____________________________________________________________________________//
678
679 } // namespace file
680
681 } // namespace BOOST_TEST_UTILS_RUNTIME_PARAM_NAMESPACE
682
683 } // namespace boost
684
685 // EOF
686