// Copyright Vladimir Prus 2004.

// Distributed under 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)



#ifndef BOOST_PARSERS_HPP_VP_2004_05_06

#define BOOST_PARSERS_HPP_VP_2004_05_06



#include <boost/program_options/detail/convert.hpp>



namespace boost { namespace program_options {



    namespace detail {

        template<class charT, class Iterator>

        std::vector<std::basic_string<charT> > 

        make_vector(Iterator i, Iterator e)

        {

            std::vector<std::basic_string<charT> > result;

            // Some compilers don't have templated constructor for 

            // vector, so we can't create vector from (argv+1, argv+argc) range

            for(; i != e; ++i)

                result.push_back(*i);

            return result;            

        }

    }



    template<class charT>

    basic_command_line_parser<charT>::

    basic_command_line_parser(const std::vector<

                              std::basic_string<charT> >& args)

       : detail::cmdline(to_internal(args))

    {}





    template<class charT>

    basic_command_line_parser<charT>::

    basic_command_line_parser(int argc, charT* argv[])

    : detail::cmdline(

        // Explicit template arguments are required by gcc 3.3.1 

        // (at least mingw version), and do no harm on other compilers.

        to_internal(detail::make_vector<charT, charT**>(argv+1, argv+argc+!argc)))

    {}



    

    template<class charT>

    basic_command_line_parser<charT>& 

    basic_command_line_parser<charT>::options(const options_description& desc)

    {

       detail::cmdline::set_options_description(desc);

        m_desc = &desc;

        return *this;

    }



    template<class charT>

    basic_command_line_parser<charT>& 

    basic_command_line_parser<charT>::positional(

        const positional_options_description& desc)

    {

        detail::cmdline::set_positional_options(desc);

        return *this;

    }



    template<class charT>

    basic_command_line_parser<charT>& 

    basic_command_line_parser<charT>::style(int style)

    {

        detail::cmdline::style(style);

        return *this;

    }



    template<class charT>

    basic_command_line_parser<charT>& 

    basic_command_line_parser<charT>::extra_parser(ext_parser ext)

    {

        detail::cmdline::set_additional_parser(ext);

        return *this;

    }



    template<class charT>

    basic_command_line_parser<charT>& 

    basic_command_line_parser<charT>::allow_unregistered()

    {

        detail::cmdline::allow_unregistered();

        return *this;

    }



    template<class charT>

    basic_command_line_parser<charT>& 

    basic_command_line_parser<charT>::extra_style_parser(style_parser s)

    {

        detail::cmdline::extra_style_parser(s);

        return *this;

    }







    template<class charT>    

    basic_parsed_options<charT>

    basic_command_line_parser<charT>::run()

    {

        parsed_options result(m_desc);

        result.options = detail::cmdline::run();



        // Presense of parsed_options -> wparsed_options conversion

        // does the trick.

        return basic_parsed_options<charT>(result);

    }





    template<class charT>

    basic_parsed_options<charT>

    parse_command_line(int argc, charT* argv[],

                       const options_description& desc,

                       int style,

                       function1<std::pair<std::string, std::string>, 

                                 const std::string&> ext)

    {

        return basic_command_line_parser<charT>(argc, argv).options(desc).

            style(style).extra_parser(ext).run();

    }



    template<class charT>

    std::vector< std::basic_string<charT> > 

    collect_unrecognized(const std::vector< basic_option<charT> >& options,

                         enum collect_unrecognized_mode mode)

    {

        std::vector< std::basic_string<charT> >  result;

        for(unsigned i = 0; i < options.size(); ++i)

        {

            if (options[i].unregistered ||

                (mode == include_positional && options[i].position_key != -1))

            {

                copy(options[i].original_tokens.begin(),

                     options[i].original_tokens.end(),

                     back_inserter(result));

            }

        }

        return result;

    }





}}



#endif

