~ubuntu-branches/ubuntu/wily/bombono-dvd/wily

« back to all changes in this revision

Viewing changes to libs/boost-lib/boost/test/utils/runtime/file/config_file_iterator.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia
  • Date: 2010-11-04 11:46:25 UTC
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20101104114625-8xfdhvhpsm51i0nu
Tags: upstream-0.8.0
ImportĀ upstreamĀ versionĀ 0.8.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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: 54633 $
 
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/utility.hpp>
 
28
#include <boost/scoped_array.hpp>
 
29
#include <boost/bind.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_RT_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>
 
59
    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
    }
 
68
    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
        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
 
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_RT_PARAM_LITERAL( '_' ) && *it != BOOST_RT_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
 
 
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_RT_PARAM_VALIDATE_LOGIC( m_stream.is_open(), BOOST_RT_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
 
 
189
    bool                is_active_line() { return m_inactive_ifdef_level == 0; }
 
190
 
 
191
    static bool         match_front( cstring str, cstring pattern )
 
192
    {
 
193
        return str.size() >= pattern.size() && str.substr( 0, pattern.size() ) == pattern;
 
194
    }
 
195
    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
 
 
236
config_file_iterator::Impl::Impl()
 
237
: m_path_separators( BOOST_RT_PARAM_LITERAL( "/\\" ) )
 
238
, m_line_delimeter( BOOST_RT_PARAM_LITERAL( '\n' ) )
 
239
, m_sl_comment_delimeter( BOOST_RT_PARAM_LITERAL( "#" ) )
 
240
, m_command_delimeter( BOOST_RT_PARAM_LITERAL( "$" ) )
 
241
, m_line_beak( BOOST_RT_PARAM_LITERAL( "\\" ) )
 
242
, m_macro_ref_begin( BOOST_RT_PARAM_LITERAL( "$" ) )
 
243
, m_macro_ref_end( BOOST_RT_PARAM_LITERAL( "$" ) )
 
244
 
 
245
, m_include_kw( BOOST_RT_PARAM_LITERAL( "include" ) )
 
246
, m_define_kw( BOOST_RT_PARAM_LITERAL( "define" ) )
 
247
, m_undef_kw( BOOST_RT_PARAM_LITERAL( "undef" ) )
 
248
, m_ifdef_kw( BOOST_RT_PARAM_LITERAL( "ifdef" ) )
 
249
, m_ifndef_kw( BOOST_RT_PARAM_LITERAL( "ifndef" ) )
 
250
, m_else_kw( BOOST_RT_PARAM_LITERAL( "else" ) )
 
251
, m_endif_kw( BOOST_RT_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
 
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_RT_PARAM_VALIDATE_LOGIC( !broken_line, BOOST_RT_PARAM_LITERAL( "broken line is not completed" ) );
 
342
    BOOST_RT_PARAM_VALIDATE_LOGIC( m_conditional_states.size() == 0,
 
343
                                   BOOST_RT_PARAM_LITERAL( "matching endif command is missing" ) );
 
344
 
 
345
    return false;
 
346
}
 
347
 
 
348
//____________________________________________________________________________//
 
349
 
 
350
boost::optional<cstring>
 
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_RT_PARAM_VALIDATE_LOGIC( macro_value || ignore_missing || !m_detect_missing_macro, 
 
363
            BOOST_RT_PARAM_LITERAL( "Unknown macro \"" ) << macro_name << BOOST_RT_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
 
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_RT_PARAM_VALIDATE_LOGIC( it != m_command_handler_map.end(), BOOST_RT_PARAM_LITERAL( "Invalid command " ) << *tit );
 
390
 
 
391
    ++tit;
 
392
 
 
393
    (it->second)( *tit );
 
394
}
 
395
 
 
396
//____________________________________________________________________________//
 
397
 
 
398
void
 
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_RT_PARAM_VALIDATE_LOGIC( tit != string_token_iterator(),
 
409
                                   BOOST_RT_PARAM_LITERAL( "include file name missing" ) );
 
410
 
 
411
    cstring include_file_name = *tit;
 
412
 
 
413
    BOOST_RT_PARAM_VALIDATE_LOGIC( ++tit == string_token_iterator(),
 
414
                                   BOOST_RT_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
 
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_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
 
435
                                   BOOST_RT_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
 
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_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
 
453
                                   BOOST_RT_PARAM_LITERAL( "invalid macro name" ) );
 
454
 
 
455
    m_symbols_table.remove( macro_name );
 
456
}
 
457
 
 
458
//____________________________________________________________________________//
 
459
 
 
460
void
 
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_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
 
469
                                   BOOST_RT_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
 
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_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
 
486
                                   BOOST_RT_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
 
495
config_file_iterator::Impl::process_else( cstring line )
 
496
{
 
497
    BOOST_RT_PARAM_VALIDATE_LOGIC( m_conditional_states.size() > 0 && m_conditional_states.back(),
 
498
                                   BOOST_RT_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_RT_PARAM_VALIDATE_LOGIC( line.is_empty(), BOOST_RT_PARAM_LITERAL( "unexpected tokens at the end of else command" ) );
 
503
}
 
504
 
 
505
//____________________________________________________________________________//
 
506
 
 
507
void
 
508
config_file_iterator::Impl::process_endif( cstring line )
 
509
{
 
510
    BOOST_RT_PARAM_VALIDATE_LOGIC( m_conditional_states.size() > 0, BOOST_RT_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_RT_PARAM_VALIDATE_LOGIC( line.is_empty(), BOOST_RT_PARAM_LITERAL( "unexpected tokens at the end of endif command" ) );
 
517
}
 
518
 
 
519
//____________________________________________________________________________//
 
520
 
 
521
void
 
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_RT_PARAM_VALIDATE_LOGIC( pos != cstring::npos, BOOST_RT_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
 
555
config_file_iterator::construct()
 
556
{
 
557
    m_pimpl.reset( new Impl );
 
558
}
 
559
 
 
560
//____________________________________________________________________________//
 
561
 
 
562
void
 
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, bind( &Impl::process_include, m_pimpl.get(), _1 ) );
 
569
    register_command_handler( m_pimpl->m_define_kw, bind( &Impl::process_define, m_pimpl.get(), _1 ) );
 
570
    register_command_handler( m_pimpl->m_undef_kw, bind( &Impl::process_undef, m_pimpl.get(), _1 ) );
 
571
    register_command_handler( m_pimpl->m_ifdef_kw, bind( &Impl::process_ifdef, m_pimpl.get(), _1 ) );
 
572
    register_command_handler( m_pimpl->m_ifndef_kw, bind( &Impl::process_ifndef, m_pimpl.get(), _1 ) );
 
573
    register_command_handler( m_pimpl->m_else_kw, bind( &Impl::process_else, m_pimpl.get(), _1 ) );
 
574
    register_command_handler( m_pimpl->m_endif_kw, bind( &Impl::process_endif, m_pimpl.get(), _1 ) );
 
575
 
 
576
    init();
 
577
}
 
578
 
 
579
//____________________________________________________________________________//
 
580
 
 
581
location const&
 
582
config_file_iterator::curr_location()
 
583
{
 
584
    return m_pimpl->m_curr_level->m_curr_location;
 
585
}
 
586
 
 
587
//____________________________________________________________________________//
 
588
 
 
589
void
 
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
 
598
config_file_iterator::get()
 
599
{
 
600
    return m_pimpl->get_next_line( m_value );
 
601
}
 
602
 
 
603
//____________________________________________________________________________//
 
604
 
 
605
void
 
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
 
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
 
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
 
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_RT_PARAM_NAMESPACE
 
682
 
 
683
} // namespace boost
 
684
 
 
685
// EOF