Imported existing code
This commit is contained in:
249
libraries/include/boost/test/utils/runtime/file/config_file.cpp
Normal file
249
libraries/include/boost/test/utils/runtime/file/config_file.cpp
Normal file
@@ -0,0 +1,249 @@
|
||||
// (C) Copyright Gennadiy Rozental 2005-2008.
|
||||
// Use, modification, and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/test for the library home page.
|
||||
//
|
||||
// File : $RCSfile$
|
||||
//
|
||||
// Version : $Revision: 49312 $
|
||||
//
|
||||
// Description : implements models configuration file, it's parameter and parameter namespaces
|
||||
// ***************************************************************************
|
||||
|
||||
// Boost.Runtime.Parameter
|
||||
#include <boost/test/utils/runtime/config.hpp>
|
||||
|
||||
#include <boost/test/utils/runtime/file/config_file.hpp>
|
||||
#include <boost/test/utils/runtime/validation.hpp>
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/utils/foreach.hpp>
|
||||
#include <boost/test/utils/basic_cstring/basic_cstring.hpp>
|
||||
#include <boost/test/utils/basic_cstring/io.hpp>
|
||||
#include <boost/test/utils/iterator/token_iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace BOOST_RT_PARAM_NAMESPACE {
|
||||
|
||||
namespace file {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** runtime::file::parameter ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
parameter::parameter( cstring name, cstring value, param_namespace const& parent )
|
||||
: m_parent( parent )
|
||||
{
|
||||
assign_op( p_name.value, name, 0 );
|
||||
assign_op( p_value.value, value, 0 );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
std::ostream&
|
||||
operator<<( std::ostream& os, parameter const& p )
|
||||
{
|
||||
p.m_parent.print_full_name( os );
|
||||
|
||||
return os << p.p_name << " = \"" << p.p_value << "\"";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** runtime::file::param_namespace ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
param_namespace::param_namespace( cstring name, param_namespace const* parent )
|
||||
: p_parent( parent )
|
||||
{
|
||||
assign_op( p_name.value, name );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
param_namespace::insert_param( cstring param_name, cstring param_value )
|
||||
{
|
||||
BOOST_TEST_FOREACH( parameter const&, p, m_parameters )
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( p.p_name != param_name,
|
||||
BOOST_RT_PARAM_LITERAL( "Duplicate parameter " ) << param_name );
|
||||
|
||||
m_parameters.push_back( parameter( param_name, param_value, *this ) );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
param_namespace&
|
||||
param_namespace::subnamespace( cstring namespace_name )
|
||||
{
|
||||
BOOST_TEST_FOREACH( param_namespace&, subns, m_subnamespaces )
|
||||
if( subns.p_name == namespace_name )
|
||||
return subns;
|
||||
|
||||
m_subnamespaces.push_back( param_namespace( namespace_name, this ) );
|
||||
|
||||
return m_subnamespaces.back();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
param_namespace::clear()
|
||||
{
|
||||
m_parameters.clear();
|
||||
m_subnamespaces.clear();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
param_namespace::print_full_name( std::ostream& os ) const
|
||||
{
|
||||
if( !p_parent )
|
||||
return;
|
||||
|
||||
p_parent.get()->print_full_name( os );
|
||||
|
||||
os << p_name << "::";
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
boost::optional<cstring>
|
||||
get_param_value( param_namespace const& where_from,
|
||||
cstring name_part1,
|
||||
cstring name_part2,
|
||||
cstring name_part3,
|
||||
cstring name_part4,
|
||||
cstring name_part5 )
|
||||
{
|
||||
if( name_part2.is_empty() ) {
|
||||
boost::optional<cstring> res;
|
||||
|
||||
BOOST_TEST_FOREACH( parameter const&, p, where_from ) {
|
||||
if( p.p_name == name_part1 ) {
|
||||
res = cstring( p.p_value );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
param_namespace const* sns = get_param_subns( where_from, name_part1 );
|
||||
|
||||
return sns ? get_param_value( *sns, name_part2, name_part3, name_part4, name_part5 )
|
||||
: boost::optional<cstring>();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
cstring
|
||||
get_requ_param_value( param_namespace const& where_from,
|
||||
cstring name_part1,
|
||||
cstring name_part2,
|
||||
cstring name_part3,
|
||||
cstring name_part4,
|
||||
cstring name_part5 )
|
||||
{
|
||||
boost::optional<cstring> v = get_param_value( where_from, name_part1, name_part2, name_part3, name_part4, name_part5 );
|
||||
|
||||
#define APPEND_PART( part ) (part.is_empty() ? "" : "::") << (part.is_empty() ? cstring() : part)
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( !!v, BOOST_RT_PARAM_LITERAL( "Required parameter " )
|
||||
<< name_part1
|
||||
<< APPEND_PART( name_part2 )
|
||||
<< APPEND_PART( name_part3 )
|
||||
<< APPEND_PART( name_part4 )
|
||||
<< APPEND_PART( name_part5 )
|
||||
<< BOOST_RT_PARAM_LITERAL( " value is missing" ) );
|
||||
#undef APPEND_PART
|
||||
|
||||
return *v;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
param_namespace const*
|
||||
get_param_subns( param_namespace const& where_from, cstring namespace_name )
|
||||
{
|
||||
param_namespace::sub_ns_const_iterator it = where_from.sub_ns_begin();
|
||||
param_namespace::sub_ns_const_iterator end = where_from.sub_ns_end();
|
||||
|
||||
while( it != end ) {
|
||||
if( it->p_name == namespace_name )
|
||||
return &*it;
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
param_namespace::load_impl( config_file_iterator cf_it,
|
||||
cstring value_marker, cstring value_delimeter, cstring namespace_delimeter )
|
||||
{
|
||||
using namespace unit_test;
|
||||
|
||||
while( cf_it != config_file_iterator() ) {
|
||||
string_token_iterator ti( *cf_it, (max_tokens = 2,kept_delimeters = dt_none, dropped_delimeters = value_delimeter) );
|
||||
|
||||
cstring param_name = *ti;
|
||||
cstring param_value = *(++ti);
|
||||
|
||||
param_value.trim( value_marker );
|
||||
|
||||
param_namespace* targ_ns = this;
|
||||
|
||||
while( !param_name.is_empty() ) {
|
||||
cstring::size_type pos = param_name.find( namespace_delimeter );
|
||||
cstring subname( param_name.begin(), pos == cstring::npos ? param_name.size() : pos );
|
||||
|
||||
if( subname.size() == param_name.size() ) {
|
||||
targ_ns->insert_param( param_name, param_value );
|
||||
break;
|
||||
}
|
||||
else {
|
||||
targ_ns = &targ_ns->subnamespace( subname );
|
||||
|
||||
param_name.trim_left( subname.size() + namespace_delimeter.size() );
|
||||
}
|
||||
}
|
||||
++cf_it;
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** runtime::file::config_file ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
config_file::config_file()
|
||||
: param_namespace( cstring() )
|
||||
{
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
config_file::config_file( cstring file_name )
|
||||
: param_namespace( cstring() )
|
||||
{
|
||||
load( file_name );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace file
|
||||
|
||||
} // namespace BOOST_RT_PARAM_NAMESPACE
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// EOF
|
||||
182
libraries/include/boost/test/utils/runtime/file/config_file.hpp
Normal file
182
libraries/include/boost/test/utils/runtime/file/config_file.hpp
Normal file
@@ -0,0 +1,182 @@
|
||||
// (C) Copyright Gennadiy Rozental 2005-2008.
|
||||
// Use, modification, and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/test for the library home page.
|
||||
//
|
||||
// File : $RCSfile$
|
||||
//
|
||||
// Version : $Revision: 49312 $
|
||||
//
|
||||
// Description : defines models configuration file, it's parameter and parameter namespaces
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_RT_FILE_CONFIG_FILE_HPP_010105GER
|
||||
#define BOOST_RT_FILE_CONFIG_FILE_HPP_010105GER
|
||||
|
||||
// Boost.Runtime.Parameter
|
||||
#include <boost/test/utils/runtime/config.hpp>
|
||||
|
||||
#include <boost/test/utils/runtime/file/config_file_iterator.hpp>
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/utils/class_properties.hpp>
|
||||
#include <boost/test/utils/named_params.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
// STL
|
||||
#include <list>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace BOOST_RT_PARAM_NAMESPACE {
|
||||
|
||||
namespace file {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** runtime::file::parameter ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
class param_namespace;
|
||||
|
||||
class parameter {
|
||||
public:
|
||||
// Constructor
|
||||
parameter( cstring name, cstring value, param_namespace const& parent );
|
||||
|
||||
BOOST_READONLY_PROPERTY( dstring, (parameter)) p_name;
|
||||
BOOST_READONLY_PROPERTY( dstring, (parameter)) p_value;
|
||||
|
||||
friend std::ostream& operator<<( std::ostream& os, parameter const& );
|
||||
|
||||
private:
|
||||
// Data members
|
||||
param_namespace const& m_parent;
|
||||
};
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** runtime::file::modifiers ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
namespace {
|
||||
nfp::typed_keyword<cstring, struct value_marker_t> value_marker;
|
||||
nfp::typed_keyword<cstring, struct value_delimeter_t> value_delimeter;
|
||||
nfp::typed_keyword<cstring, struct namespace_delimeter_t> namespace_delimeter;
|
||||
} // local namespace
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** runtime::file::param_namespace ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
class param_namespace {
|
||||
public:
|
||||
typedef std::list<parameter>::iterator iterator;
|
||||
typedef std::list<parameter>::const_iterator const_iterator;
|
||||
typedef std::list<param_namespace>::iterator sub_ns_iterator;
|
||||
typedef std::list<param_namespace>::const_iterator sub_ns_const_iterator;
|
||||
|
||||
// Public properties
|
||||
BOOST_READONLY_PROPERTY( dstring, (param_namespace)) p_name;
|
||||
unit_test::readonly_property<param_namespace const*> p_parent;
|
||||
|
||||
void load( config_file_iterator cf_it ) { load( cf_it, nfp::no_params ); }
|
||||
template<typename Modifier>
|
||||
void load( config_file_iterator cf_it, Modifier const& m )
|
||||
{
|
||||
cstring vm = m.has( value_marker ) ? m[value_marker] : BOOST_RT_PARAM_CSTRING_LITERAL( "\"" );
|
||||
cstring vd = m.has( value_delimeter ) ? m[value_delimeter] : BOOST_RT_PARAM_CSTRING_LITERAL( "= \t\n\r" );
|
||||
cstring nd = m.has( namespace_delimeter ) ? m[namespace_delimeter] : BOOST_RT_PARAM_CSTRING_LITERAL( "::" );
|
||||
|
||||
load_impl( cf_it, vm, vd, nd );
|
||||
}
|
||||
void load( cstring file_name )
|
||||
{
|
||||
load( file_name, nfp::no_params );
|
||||
}
|
||||
template<typename Modifier>
|
||||
void load( cstring file_name, Modifier const& m )
|
||||
{
|
||||
config_file_iterator cfi( file_name, m );
|
||||
|
||||
load( cfi, m );
|
||||
}
|
||||
|
||||
void insert_param( cstring param_name, cstring param_value );
|
||||
param_namespace& subnamespace( cstring namespace_name ); // find and insert if not present
|
||||
void clear();
|
||||
|
||||
iterator begin() { return m_parameters.begin(); }
|
||||
const_iterator begin() const { return m_parameters.begin(); }
|
||||
|
||||
iterator end() { return m_parameters.end(); }
|
||||
const_iterator end() const { return m_parameters.end(); }
|
||||
|
||||
sub_ns_iterator sub_ns_begin() { return m_subnamespaces.begin(); }
|
||||
sub_ns_const_iterator sub_ns_begin() const { return m_subnamespaces.begin(); }
|
||||
|
||||
sub_ns_iterator sub_ns_end() { return m_subnamespaces.end(); }
|
||||
sub_ns_const_iterator sub_ns_end() const { return m_subnamespaces.end(); }
|
||||
|
||||
void print_full_name( std::ostream& os ) const;
|
||||
|
||||
protected:
|
||||
explicit param_namespace( cstring name, param_namespace const* parent = 0 );
|
||||
|
||||
private:
|
||||
void load_impl( config_file_iterator cf_it,
|
||||
cstring value_marker_, cstring value_delimeter_, cstring namespace_delimeter_ );
|
||||
|
||||
// Data members
|
||||
std::list<parameter> m_parameters;
|
||||
std::list<param_namespace> m_subnamespaces;
|
||||
};
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
boost::optional<cstring>
|
||||
get_param_value( param_namespace const& where_from,
|
||||
cstring name_part1,
|
||||
cstring name_part2 = cstring(),
|
||||
cstring name_part3 = cstring(),
|
||||
cstring name_part4 = cstring(),
|
||||
cstring name_part5 = cstring() );
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
cstring
|
||||
get_requ_param_value( param_namespace const& where_from,
|
||||
cstring name_part1,
|
||||
cstring name_part2 = cstring(),
|
||||
cstring name_part3 = cstring(),
|
||||
cstring name_part4 = cstring(),
|
||||
cstring name_part5 = cstring() );
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
param_namespace const*
|
||||
get_param_subns( param_namespace const& where_from,
|
||||
cstring namespace_name );
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** runtime::file::config_file ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
class config_file : public param_namespace {
|
||||
public:
|
||||
// Constructor
|
||||
config_file();
|
||||
config_file( cstring file_name );
|
||||
};
|
||||
|
||||
} // namespace file
|
||||
|
||||
} // namespace BOOST_RT_PARAM_NAMESPACE
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_RT_FILE_CONFIG_FILE_HPP_010105GER
|
||||
@@ -0,0 +1,680 @@
|
||||
// (C) Copyright Gennadiy Rozental 2005-2008.
|
||||
// Use, modification, and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/test for the library home page.
|
||||
//
|
||||
// File : $RCSfile$
|
||||
//
|
||||
// Version : $Revision: 49312 $
|
||||
//
|
||||
// Description : flexible configuration file iterator implementation
|
||||
// ***************************************************************************
|
||||
|
||||
// Boost.Runtime.Parameter
|
||||
#include <boost/test/utils/runtime/config.hpp>
|
||||
|
||||
#include <boost/test/utils/runtime/file/config_file_iterator.hpp>
|
||||
#include <boost/test/utils/runtime/validation.hpp>
|
||||
|
||||
#include <boost/test/utils/runtime/env/environment.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/utils/basic_cstring/compare.hpp>
|
||||
#include <boost/test/utils/algorithm.hpp>
|
||||
#include <boost/test/utils/iterator/token_iterator.hpp>
|
||||
#include <boost/test/utils/assign_op.hpp>
|
||||
|
||||
// STL
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <cctype>
|
||||
#include <iostream>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace BOOST_RT_PARAM_NAMESPACE {
|
||||
|
||||
namespace file {
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** symbol_to_value_map ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
template<typename ValueType>
|
||||
struct symbol_to_value_map : std::map<cstring, ValueType> {
|
||||
template<typename ParamType>
|
||||
void add( cstring name, ParamType const& value )
|
||||
{
|
||||
using namespace unit_test;
|
||||
|
||||
m_name_store.push_back( dstring() );
|
||||
|
||||
assign_op( m_name_store.back(), name, 0 );
|
||||
assign_op( (*this)[m_name_store.back()], value, 0 );
|
||||
}
|
||||
void remove( cstring name )
|
||||
{
|
||||
std::list<dstring>::iterator it = std::find( m_name_store.begin(), m_name_store.end(), name );
|
||||
|
||||
m_name_store.erase( it );
|
||||
|
||||
erase( name );
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<dstring> m_name_store;
|
||||
};
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** symbol_table_t ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
typedef symbol_to_value_map<dstring> symbol_table_t;
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** command_handler_map ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
typedef symbol_to_value_map<config_file_iterator::command_handler> command_handler_map;
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** is_valid_identifier ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
static bool
|
||||
is_valid_identifier( cstring const& source )
|
||||
{
|
||||
if( source.is_empty() )
|
||||
return false;
|
||||
|
||||
cstring::const_iterator it = source.begin();
|
||||
|
||||
if( !std::isalpha( *it ) )
|
||||
return false;
|
||||
|
||||
while( ++it < source.end() ) {
|
||||
if( !std::isalnum( *it ) && *it != BOOST_RT_PARAM_LITERAL( '_' ) && *it != BOOST_RT_PARAM_LITERAL( '-' ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** include_level ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
struct include_level;
|
||||
typedef std::auto_ptr<include_level> include_level_ptr;
|
||||
|
||||
struct include_level : noncopyable
|
||||
{
|
||||
// Constructor
|
||||
explicit include_level( cstring file_name, cstring path_separators, include_level* parent = 0 );
|
||||
|
||||
// Data members
|
||||
std::ifstream m_stream;
|
||||
location m_curr_location;
|
||||
include_level_ptr m_parent;
|
||||
};
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
include_level::include_level( cstring file_name, cstring path_separators, include_level* parent_ )
|
||||
: m_parent( parent_ )
|
||||
{
|
||||
if( file_name.is_empty() )
|
||||
return;
|
||||
|
||||
assign_op( m_curr_location.first, file_name, 0 );
|
||||
m_curr_location.second = 0;
|
||||
|
||||
m_stream.open( m_curr_location.first.c_str() );
|
||||
|
||||
if( !m_stream.is_open() && !!m_parent.get() ) {
|
||||
cstring parent_path = m_parent->m_curr_location.first;
|
||||
cstring::iterator it = unit_test::find_last_of( parent_path.begin(), parent_path.end(),
|
||||
path_separators.begin(),
|
||||
path_separators.end() );
|
||||
|
||||
if( it != parent_path.end() ) {
|
||||
assign_op( m_curr_location.first, cstring( parent_path.begin(), it+1 ), 0 );
|
||||
m_curr_location.first.append( file_name.begin(), file_name.end() );
|
||||
m_stream.clear();
|
||||
m_stream.open( m_curr_location.first.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( m_stream.is_open(), BOOST_RT_PARAM_LITERAL( "couldn't open file " ) << file_name );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** config_file_iterator::Impl ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
struct config_file_iterator::Impl : noncopyable {
|
||||
// Constructor
|
||||
Impl();
|
||||
|
||||
bool get_next_line( cstring& next_line );
|
||||
|
||||
void process_command_line( cstring line );
|
||||
void process_include( cstring line );
|
||||
void process_define( cstring line );
|
||||
void process_undef( cstring line );
|
||||
void process_ifdef( cstring line );
|
||||
void process_ifndef( cstring line );
|
||||
void process_else( cstring line );
|
||||
void process_endif( cstring line );
|
||||
|
||||
boost::optional<cstring>
|
||||
get_macro_value( cstring macro_name, bool ignore_missing = true );
|
||||
void substitute_macros( cstring& where );
|
||||
|
||||
bool is_active_line() { return m_inactive_ifdef_level == 0; }
|
||||
|
||||
static bool match_front( cstring str, cstring pattern )
|
||||
{
|
||||
return str.size() >= pattern.size() && str.substr( 0, pattern.size() ) == pattern;
|
||||
}
|
||||
static bool match_back( cstring str, cstring pattern )
|
||||
{
|
||||
return str.size() >= pattern.size() && str.substr( str.size() - pattern.size() ) == pattern;
|
||||
}
|
||||
|
||||
// Configurable parameters
|
||||
dstring m_path_separators;
|
||||
char_type m_line_delimeter;
|
||||
dstring m_sl_comment_delimeter;
|
||||
dstring m_command_delimeter;
|
||||
dstring m_line_beak;
|
||||
dstring m_macro_ref_begin;
|
||||
dstring m_macro_ref_end;
|
||||
|
||||
dstring m_include_kw;
|
||||
dstring m_define_kw;
|
||||
dstring m_undef_kw;
|
||||
dstring m_ifdef_kw;
|
||||
dstring m_ifndef_kw;
|
||||
dstring m_else_kw;
|
||||
dstring m_endif_kw;
|
||||
|
||||
std::size_t m_buffer_size;
|
||||
|
||||
bool m_trim_trailing_spaces;
|
||||
bool m_trim_leading_spaces;
|
||||
bool m_skip_empty_lines;
|
||||
bool m_detect_missing_macro;
|
||||
|
||||
// Data members
|
||||
dstring m_post_subst_line;
|
||||
scoped_array<char> m_buffer;
|
||||
include_level_ptr m_curr_level;
|
||||
symbol_table_t m_symbols_table;
|
||||
std::vector<bool> m_conditional_states;
|
||||
std::size_t m_inactive_ifdef_level;
|
||||
command_handler_map m_command_handler_map;
|
||||
};
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
config_file_iterator::Impl::Impl()
|
||||
: m_path_separators( BOOST_RT_PARAM_LITERAL( "/\\" ) )
|
||||
, m_line_delimeter( BOOST_RT_PARAM_LITERAL( '\n' ) )
|
||||
, m_sl_comment_delimeter( BOOST_RT_PARAM_LITERAL( "#" ) )
|
||||
, m_command_delimeter( BOOST_RT_PARAM_LITERAL( "$" ) )
|
||||
, m_line_beak( BOOST_RT_PARAM_LITERAL( "\\" ) )
|
||||
, m_macro_ref_begin( BOOST_RT_PARAM_LITERAL( "$" ) )
|
||||
, m_macro_ref_end( BOOST_RT_PARAM_LITERAL( "$" ) )
|
||||
|
||||
, m_include_kw( BOOST_RT_PARAM_LITERAL( "include" ) )
|
||||
, m_define_kw( BOOST_RT_PARAM_LITERAL( "define" ) )
|
||||
, m_undef_kw( BOOST_RT_PARAM_LITERAL( "undef" ) )
|
||||
, m_ifdef_kw( BOOST_RT_PARAM_LITERAL( "ifdef" ) )
|
||||
, m_ifndef_kw( BOOST_RT_PARAM_LITERAL( "ifndef" ) )
|
||||
, m_else_kw( BOOST_RT_PARAM_LITERAL( "else" ) )
|
||||
, m_endif_kw( BOOST_RT_PARAM_LITERAL( "endif" ) )
|
||||
|
||||
, m_buffer_size( 8192 )
|
||||
|
||||
, m_trim_trailing_spaces( true )
|
||||
, m_trim_leading_spaces( false )
|
||||
, m_skip_empty_lines( true )
|
||||
, m_detect_missing_macro( true )
|
||||
|
||||
, m_inactive_ifdef_level( 0 )
|
||||
{}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
config_file_iterator::Impl::get_next_line( cstring& line )
|
||||
{
|
||||
bool broken_line = false;
|
||||
|
||||
line.clear();
|
||||
|
||||
while( !m_curr_level->m_stream.eof() || !!m_curr_level->m_parent.get() ) {
|
||||
// 10. Switch to upper include level if current one is finished
|
||||
// 20. Read/append next file line
|
||||
// 30. Increment line number
|
||||
// 40. Remove comments
|
||||
// 50. Remove trailing and leading spaces
|
||||
// 60. Skip empty string
|
||||
// 70. Concatenate broken lines if needed. Put the result into line
|
||||
// 80. If line is not completed, try to finish it by reading the next line
|
||||
// 90. Process command line
|
||||
// 100. Substitute macros references with their definitions
|
||||
// 110. Next line found.
|
||||
|
||||
if( m_curr_level->m_stream.eof() ) { // 10 //
|
||||
m_curr_level = m_curr_level->m_parent;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::ifstream& input = m_curr_level->m_stream;
|
||||
char_type* buffer_insert_pos = broken_line ? m_buffer.get() + line.size() : m_buffer.get();
|
||||
|
||||
input.getline( buffer_insert_pos, (std::streamsize)(m_buffer_size - line.size()), // 20 //
|
||||
m_line_delimeter );
|
||||
|
||||
cstring next_line( buffer_insert_pos,
|
||||
input.gcount() > 0
|
||||
? buffer_insert_pos + (input.eof() ? input.gcount() : (input.gcount()-1))
|
||||
: buffer_insert_pos );
|
||||
|
||||
|
||||
m_curr_level->m_curr_location.second++; // 30 //
|
||||
|
||||
cstring::size_type comment_pos = next_line.find( m_sl_comment_delimeter );
|
||||
if( comment_pos != cstring::npos )
|
||||
next_line.trim_right( next_line.begin()+comment_pos ); // 40 //
|
||||
|
||||
if( m_trim_trailing_spaces ) // 50 //
|
||||
next_line.trim_right();
|
||||
if( m_trim_leading_spaces && !broken_line )
|
||||
next_line.trim_left();
|
||||
|
||||
if( next_line.is_empty() ) { // 60 //
|
||||
if( m_skip_empty_lines )
|
||||
continue;
|
||||
else
|
||||
next_line.assign( buffer_insert_pos, buffer_insert_pos );
|
||||
}
|
||||
|
||||
line = broken_line ? cstring( line.begin(), next_line.end() ) : next_line; // 70 //
|
||||
|
||||
broken_line = match_back( line, m_line_beak );
|
||||
if( broken_line ) { // 80 //
|
||||
line.trim_right( 1 );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( match_front( line, m_command_delimeter ) ) { // 90 //
|
||||
process_command_line( line );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !is_active_line() )
|
||||
continue;
|
||||
|
||||
substitute_macros( line ); // 100 //
|
||||
|
||||
return true; // 110 //
|
||||
}
|
||||
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( !broken_line, BOOST_RT_PARAM_LITERAL( "broken line is not completed" ) );
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( m_conditional_states.size() == 0,
|
||||
BOOST_RT_PARAM_LITERAL( "matching endif command is missing" ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
boost::optional<cstring>
|
||||
config_file_iterator::Impl::get_macro_value( cstring macro_name, bool ignore_missing )
|
||||
{
|
||||
symbol_table_t::const_iterator it = m_symbols_table.find( macro_name );
|
||||
|
||||
if( it == m_symbols_table.end() ) {
|
||||
boost::optional<cstring> macro_value; // !! variable actually may have different type
|
||||
|
||||
env::get( macro_name, macro_value );
|
||||
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( macro_value || ignore_missing || !m_detect_missing_macro,
|
||||
BOOST_RT_PARAM_LITERAL( "Unknown macro \"" ) << macro_name << BOOST_RT_PARAM_LITERAL( "\"" ) );
|
||||
|
||||
if( !macro_value ) {
|
||||
if( !ignore_missing )
|
||||
macro_value = cstring();
|
||||
}
|
||||
else
|
||||
m_symbols_table.add( macro_name, *macro_value );
|
||||
|
||||
return macro_value;
|
||||
}
|
||||
|
||||
return boost::optional<cstring>( cstring( it->second ) );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::Impl::process_command_line( cstring line )
|
||||
{
|
||||
line.trim_left( m_command_delimeter.size() );
|
||||
|
||||
unit_test::string_token_iterator tit( line, unit_test::max_tokens = 2 );
|
||||
|
||||
command_handler_map::const_iterator it = m_command_handler_map.find( *tit );
|
||||
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( it != m_command_handler_map.end(), BOOST_RT_PARAM_LITERAL( "Invalid command " ) << *tit );
|
||||
|
||||
++tit;
|
||||
|
||||
(it->second)( *tit );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::Impl::process_include( cstring line )
|
||||
{
|
||||
using namespace unit_test;
|
||||
|
||||
if( !is_active_line() )
|
||||
return;
|
||||
|
||||
string_token_iterator tit( line, kept_delimeters = dt_none );
|
||||
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( tit != string_token_iterator(),
|
||||
BOOST_RT_PARAM_LITERAL( "include file name missing" ) );
|
||||
|
||||
cstring include_file_name = *tit;
|
||||
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( ++tit == string_token_iterator(),
|
||||
BOOST_RT_PARAM_LITERAL( "unexpected tokens at the end of include command" ) );
|
||||
|
||||
substitute_macros( include_file_name );
|
||||
|
||||
m_curr_level.reset( new include_level( include_file_name, m_path_separators, m_curr_level.release() ) );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::Impl::process_define( cstring line )
|
||||
{
|
||||
using namespace unit_test;
|
||||
|
||||
if( !is_active_line() )
|
||||
return;
|
||||
|
||||
string_token_iterator tit( line, (kept_delimeters = dt_none, max_tokens = 2 ));
|
||||
|
||||
cstring macro_name = *tit;
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
|
||||
BOOST_RT_PARAM_LITERAL( "invalid macro name" ) );
|
||||
|
||||
cstring macro_value = *(++tit);
|
||||
substitute_macros( macro_value );
|
||||
|
||||
m_symbols_table.add( macro_name, macro_value );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::Impl::process_undef( cstring line )
|
||||
{
|
||||
if( !is_active_line() )
|
||||
return;
|
||||
|
||||
cstring macro_name = line;
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
|
||||
BOOST_RT_PARAM_LITERAL( "invalid macro name" ) );
|
||||
|
||||
m_symbols_table.remove( macro_name );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::Impl::process_ifdef( cstring line )
|
||||
{
|
||||
m_conditional_states.push_back( true );
|
||||
if( !is_active_line() )
|
||||
return;
|
||||
|
||||
cstring macro_name = line;
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
|
||||
BOOST_RT_PARAM_LITERAL( "invalid macro name" ) );
|
||||
|
||||
if( !get_macro_value( macro_name ) )
|
||||
m_inactive_ifdef_level = m_conditional_states.size();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::Impl::process_ifndef( cstring line )
|
||||
{
|
||||
m_conditional_states.push_back( true );
|
||||
if( !is_active_line() )
|
||||
return;
|
||||
|
||||
cstring macro_name = line;
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( is_valid_identifier( macro_name ),
|
||||
BOOST_RT_PARAM_LITERAL( "invalid macro name" ) );
|
||||
|
||||
if( get_macro_value( macro_name ) )
|
||||
m_inactive_ifdef_level = m_conditional_states.size();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::Impl::process_else( cstring line )
|
||||
{
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( m_conditional_states.size() > 0 && m_conditional_states.back(),
|
||||
BOOST_RT_PARAM_LITERAL( "else without matching if" ) );
|
||||
|
||||
m_inactive_ifdef_level = m_conditional_states.size() == m_inactive_ifdef_level ? 0 : m_conditional_states.size();
|
||||
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( line.is_empty(), BOOST_RT_PARAM_LITERAL( "unexpected tokens at the end of else command" ) );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::Impl::process_endif( cstring line )
|
||||
{
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( m_conditional_states.size() > 0, BOOST_RT_PARAM_LITERAL( "endif without matching if" ) );
|
||||
|
||||
if( m_conditional_states.size() == m_inactive_ifdef_level )
|
||||
m_inactive_ifdef_level = 0;
|
||||
|
||||
m_conditional_states.pop_back();
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( line.is_empty(), BOOST_RT_PARAM_LITERAL( "unexpected tokens at the end of endif command" ) );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::Impl::substitute_macros( cstring& where )
|
||||
{
|
||||
m_post_subst_line.clear();
|
||||
cstring::size_type pos;
|
||||
|
||||
while( (pos = where.find( m_macro_ref_begin )) != cstring::npos ) {
|
||||
m_post_subst_line.append( where.begin(), pos );
|
||||
|
||||
where.trim_left( where.begin() + pos + m_macro_ref_begin.size() );
|
||||
|
||||
pos = where.find( m_macro_ref_end );
|
||||
|
||||
BOOST_RT_PARAM_VALIDATE_LOGIC( pos != cstring::npos, BOOST_RT_PARAM_LITERAL( "incomplete macro reference" ) );
|
||||
|
||||
cstring value = *get_macro_value( where.substr( 0, pos ), false );
|
||||
m_post_subst_line.append( value.begin(), value.size() );
|
||||
|
||||
where.trim_left( where.begin() + pos + m_macro_ref_end.size() );
|
||||
}
|
||||
|
||||
if( !m_post_subst_line.empty() ) {
|
||||
m_post_subst_line.append( where.begin(), where.size() );
|
||||
where = m_post_subst_line;
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** runtime::file::config_file_iterator ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
void
|
||||
config_file_iterator::construct()
|
||||
{
|
||||
m_pimpl.reset( new Impl );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::load( cstring file_name )
|
||||
{
|
||||
m_pimpl->m_curr_level.reset( new include_level( file_name, m_pimpl->m_path_separators ) );
|
||||
m_pimpl->m_buffer.reset( new char[m_pimpl->m_buffer_size] );
|
||||
|
||||
register_command_handler( m_pimpl->m_include_kw, bind( &Impl::process_include, m_pimpl.get(), _1 ) );
|
||||
register_command_handler( m_pimpl->m_define_kw, bind( &Impl::process_define, m_pimpl.get(), _1 ) );
|
||||
register_command_handler( m_pimpl->m_undef_kw, bind( &Impl::process_undef, m_pimpl.get(), _1 ) );
|
||||
register_command_handler( m_pimpl->m_ifdef_kw, bind( &Impl::process_ifdef, m_pimpl.get(), _1 ) );
|
||||
register_command_handler( m_pimpl->m_ifndef_kw, bind( &Impl::process_ifndef, m_pimpl.get(), _1 ) );
|
||||
register_command_handler( m_pimpl->m_else_kw, bind( &Impl::process_else, m_pimpl.get(), _1 ) );
|
||||
register_command_handler( m_pimpl->m_endif_kw, bind( &Impl::process_endif, m_pimpl.get(), _1 ) );
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
location const&
|
||||
config_file_iterator::curr_location()
|
||||
{
|
||||
return m_pimpl->m_curr_level->m_curr_location;
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::register_command_handler( cstring command_kw, command_handler const& ch )
|
||||
{
|
||||
m_pimpl->m_command_handler_map.add( command_kw, ch );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
bool
|
||||
config_file_iterator::get()
|
||||
{
|
||||
return m_pimpl->get_next_line( m_value );
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::set_parameter( rtti::id_t id, cstring value )
|
||||
{
|
||||
BOOST_RTTI_SWITCH( id ) {
|
||||
BOOST_RTTI_CASE( cfg_detail::path_separators_t )
|
||||
assign_op( m_pimpl->m_path_separators , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::sl_comment_delimeter_t )
|
||||
assign_op( m_pimpl->m_sl_comment_delimeter , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::command_delimeter_t )
|
||||
assign_op( m_pimpl->m_command_delimeter , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::line_beak_t )
|
||||
assign_op( m_pimpl->m_line_beak , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::macro_ref_begin_t )
|
||||
assign_op( m_pimpl->m_macro_ref_begin , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::macro_ref_end_t )
|
||||
assign_op( m_pimpl->m_macro_ref_end , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::include_kw_t )
|
||||
assign_op( m_pimpl->m_include_kw , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::define_kw_t )
|
||||
assign_op( m_pimpl->m_define_kw , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::undef_kw_t )
|
||||
assign_op( m_pimpl->m_undef_kw , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::ifdef_kw_t )
|
||||
assign_op( m_pimpl->m_ifdef_kw , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::ifndef_kw_t )
|
||||
assign_op( m_pimpl->m_ifndef_kw , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::else_kw_t )
|
||||
assign_op( m_pimpl->m_else_kw , value, 0 );
|
||||
BOOST_RTTI_CASE( cfg_detail::endif_kw_t )
|
||||
assign_op( m_pimpl->m_endif_kw , value, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::set_parameter( rtti::id_t id, bool value )
|
||||
{
|
||||
BOOST_RTTI_SWITCH( id ) {
|
||||
BOOST_RTTI_CASE( cfg_detail::trim_leading_spaces_t )
|
||||
m_pimpl->m_trim_leading_spaces = value;
|
||||
BOOST_RTTI_CASE( cfg_detail::trim_trailing_spaces_t )
|
||||
m_pimpl->m_trim_trailing_spaces = value;
|
||||
BOOST_RTTI_CASE( cfg_detail::skip_empty_lines_t )
|
||||
m_pimpl->m_skip_empty_lines = value;
|
||||
BOOST_RTTI_CASE( cfg_detail::detect_missing_macro_t )
|
||||
m_pimpl->m_detect_missing_macro = value;
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::set_parameter( rtti::id_t id, char_type value )
|
||||
{
|
||||
BOOST_RTTI_SWITCH( id ) {
|
||||
BOOST_RTTI_CASE( cfg_detail::line_delimeter_t )
|
||||
m_pimpl->m_line_delimeter = value;
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
void
|
||||
config_file_iterator::set_parameter( rtti::id_t id, std::size_t value )
|
||||
{
|
||||
BOOST_RTTI_SWITCH( id ) {
|
||||
BOOST_RTTI_CASE( cfg_detail::buffer_size_t )
|
||||
m_pimpl->m_buffer_size = value;
|
||||
}
|
||||
}
|
||||
|
||||
//____________________________________________________________________________//
|
||||
|
||||
} // namespace file
|
||||
|
||||
} // namespace BOOST_RT_PARAM_NAMESPACE
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// EOF
|
||||
@@ -0,0 +1,166 @@
|
||||
// (C) Copyright Gennadiy Rozental 2005-2008.
|
||||
// Use, modification, and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org/libs/test for the library home page.
|
||||
//
|
||||
// File : $RCSfile$
|
||||
//
|
||||
// Version : $Revision: 49312 $
|
||||
//
|
||||
// Description : flexible configuration file iterator definition
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef BOOST_RT_FILE_CONFIG_FILE_ITERATOR_HPP_062604GER
|
||||
#define BOOST_RT_FILE_CONFIG_FILE_ITERATOR_HPP_062604GER
|
||||
|
||||
// Boost.Runtime.Parameter
|
||||
#include <boost/test/utils/runtime/config.hpp>
|
||||
|
||||
#include <boost/test/utils/runtime/fwd.hpp>
|
||||
|
||||
// Boost.Test
|
||||
#include <boost/test/utils/iterator/input_iterator_facade.hpp>
|
||||
#include <boost/test/utils/callback.hpp>
|
||||
#include <boost/test/utils/named_params.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace BOOST_RT_PARAM_NAMESPACE {
|
||||
|
||||
namespace file {
|
||||
|
||||
// Public typedef
|
||||
typedef std::pair<dstring,long> location;
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** modifiers ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
namespace cfg_detail {
|
||||
struct path_separators_t;
|
||||
struct line_delimeter_t;
|
||||
struct sl_comment_delimeter_t;
|
||||
struct command_delimeter_t;
|
||||
struct line_beak_t;
|
||||
struct macro_ref_begin_t;
|
||||
struct macro_ref_end_t;
|
||||
struct include_kw_t;
|
||||
struct define_kw_t;
|
||||
struct undef_kw_t;
|
||||
struct ifdef_kw_t;
|
||||
struct ifndef_kw_t;
|
||||
struct else_kw_t;
|
||||
struct endif_kw_t;
|
||||
|
||||
struct buffer_size_t;
|
||||
|
||||
struct trim_leading_spaces_t;
|
||||
struct trim_trailing_spaces_t;
|
||||
struct skip_empty_lines_t;
|
||||
struct detect_missing_macro_t;
|
||||
} // namespace cfg_detail
|
||||
|
||||
namespace {
|
||||
|
||||
nfp::typed_keyword<cstring,cfg_detail::path_separators_t> path_separators;
|
||||
nfp::typed_keyword<char_type ,cfg_detail::line_delimeter_t> line_delimeter;
|
||||
nfp::typed_keyword<cstring,cfg_detail::sl_comment_delimeter_t> single_line_comment_delimeter;
|
||||
nfp::typed_keyword<cstring,cfg_detail::command_delimeter_t> command_delimeter;
|
||||
nfp::typed_keyword<cstring,cfg_detail::line_beak_t> line_beak;
|
||||
nfp::typed_keyword<cstring,cfg_detail::macro_ref_begin_t> macro_ref_begin;
|
||||
nfp::typed_keyword<cstring,cfg_detail::macro_ref_end_t> macro_ref_end;
|
||||
nfp::typed_keyword<cstring,cfg_detail::include_kw_t> include_kw;
|
||||
nfp::typed_keyword<cstring,cfg_detail::define_kw_t> define_kw;
|
||||
nfp::typed_keyword<cstring,cfg_detail::undef_kw_t> undef_kw;
|
||||
nfp::typed_keyword<cstring,cfg_detail::ifdef_kw_t> ifdef_kw;
|
||||
nfp::typed_keyword<cstring,cfg_detail::ifndef_kw_t> ifndef_kw;
|
||||
nfp::typed_keyword<cstring,cfg_detail::else_kw_t> else_kw;
|
||||
nfp::typed_keyword<cstring,cfg_detail::endif_kw_t> endif_kw;
|
||||
|
||||
nfp::typed_keyword<std::size_t,cfg_detail::buffer_size_t> buffer_size;
|
||||
|
||||
nfp::typed_keyword<bool,cfg_detail::trim_leading_spaces_t> trim_leading_spaces;
|
||||
nfp::typed_keyword<bool,cfg_detail::trim_trailing_spaces_t> trim_trailing_spaces;
|
||||
nfp::typed_keyword<bool,cfg_detail::skip_empty_lines_t> skip_empty_lines;
|
||||
nfp::typed_keyword<bool,cfg_detail::detect_missing_macro_t> detect_missing_macro;
|
||||
|
||||
} // local namespace
|
||||
|
||||
// ************************************************************************** //
|
||||
// ************** runtime::file::config_file_iterator ************** //
|
||||
// ************************************************************************** //
|
||||
|
||||
class config_file_iterator : public unit_test::input_iterator_facade<config_file_iterator,cstring,cstring> {
|
||||
typedef unit_test::input_iterator_facade<config_file_iterator,cstring,cstring> base;
|
||||
public:
|
||||
// Public typedefs
|
||||
typedef unit_test::callback1<cstring> command_handler;
|
||||
|
||||
// Constructors
|
||||
config_file_iterator() {}
|
||||
explicit config_file_iterator( cstring file_name )
|
||||
{
|
||||
construct();
|
||||
load( file_name );
|
||||
}
|
||||
template<typename Modifiers>
|
||||
config_file_iterator( cstring file_name, Modifiers const& m )
|
||||
{
|
||||
construct();
|
||||
m.apply_to( *this );
|
||||
load( file_name );
|
||||
}
|
||||
config_file_iterator( config_file_iterator const& rhs )
|
||||
: base( rhs )
|
||||
, m_pimpl( rhs.m_pimpl )
|
||||
{
|
||||
rhs.m_valid = false;
|
||||
}
|
||||
|
||||
void operator=( config_file_iterator const& rhs )
|
||||
{
|
||||
if( this == &rhs )
|
||||
return;
|
||||
|
||||
(base&)(*this) = rhs;
|
||||
m_pimpl = rhs.m_pimpl;
|
||||
rhs.m_valid = false;
|
||||
} // Assignment
|
||||
|
||||
|
||||
// Access methods
|
||||
location const& curr_location();
|
||||
void register_command_handler( cstring command_kw, command_handler const& );
|
||||
|
||||
// Parameters setters
|
||||
void set_parameter( rtti::id_t, cstring );
|
||||
void set_parameter( rtti::id_t, bool );
|
||||
void set_parameter( rtti::id_t, char_type );
|
||||
void set_parameter( rtti::id_t, std::size_t );
|
||||
|
||||
private:
|
||||
friend class unit_test::input_iterator_core_access;
|
||||
|
||||
void construct();
|
||||
void load( cstring file_name );
|
||||
|
||||
// increment implementation
|
||||
bool get();
|
||||
|
||||
// Data members
|
||||
struct Impl;
|
||||
shared_ptr<Impl> m_pimpl;
|
||||
};
|
||||
|
||||
} // namespace file
|
||||
|
||||
} // namespace BOOST_RT_PARAM_NAMESPACE
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_RT_FILE_CONFIG_FILE_ITERATOR_HPP_062604GER
|
||||
Reference in New Issue
Block a user