//  (C) Copyright Gennadiy Rozental 2005-2007.

//  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: 43798 $

//

//  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

