/*=============================================================================
  Spirit V1.7.0
  Copyright (c) 2003 Giovanni Bajo
  Copyright (c) 2003 Martin Wille
  http://spirit.sourceforge.net/

  Permission to copy, use, modify, sell and distribute this software
  is granted provided this copyright notice appears in all copies.
  This software is provided "as is" without express or implied
  warranty, and with no claim as to its suitability for any purpose.
 =============================================================================*/

#include <boost/spirit/iterator/multi_pass.hpp>
#include <iterator>
#include "impl/util.ipp"
#include "impl/sstream.hpp"
#include <boost/test/included/unit_test_framework.hpp>

using namespace std;
using namespace boost::spirit;

// Test for bug #720917 
// http://sf.net/tracker/index.php?func=detail&aid=720917&group_id=28447&atid=393386
//
// Check that it's possible to use multi_pass
// together with standard library as a normal iterator
//

// a functor to test out the functor_multi_pass
class my_functor
{
    public:
        typedef char result_type;
        my_functor()
            : c('A')
        {}

        char operator()()
        {
            if (c == 'M')
                return eof;
            else
                return c++;
        }

        static result_type eof;
    private:
        char c;
};

my_functor::result_type my_functor::eof = '\0';

////////////////////////////////////////////////
// four types of multi_pass iterators
typedef multi_pass<
    my_functor,
    multi_pass_policies::functor_input,
    multi_pass_policies::first_owner,
    multi_pass_policies::no_check,
    multi_pass_policies::std_deque
> functor_multi_pass_t;

typedef multi_pass<istream_iterator<char> > default_multi_pass_t;
typedef look_ahead<istream_iterator<char>, 6> fixed_multi_pass_t;

typedef multi_pass<
    istream_iterator<char>,
    multi_pass_policies::input_iterator,
    multi_pass_policies::first_owner,
    multi_pass_policies::buf_id_check,
    multi_pass_policies::std_deque
> first_owner_multi_pass_t;


////////////////////////////////////////////////
// the test cases
template <typename IterT>
void construct_string_from(void)
{
    sstream_t ss;
    ss << "test string";

    IterT mpend;
    istream_iterator<char> a(ss);
    IterT mp1(a);

    std::string dummy;
    dummy.assign(mp1, mpend);
}

template <>
void construct_string_from<functor_multi_pass_t>(void) 
{
    functor_multi_pass_t mpend;
    functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor());

    std::string dummy;
    dummy.assign(mp1, mpend);
}

////////////////////////////////////////////////
// Definition of the test suite
boost::unit_test_framework::test_suite*
init_unit_test_suite( int argc, char* argv[] )
{
    test::init(argc, argv);
    test::banner("sf_bug_720917");

    boost::unit_test_framework::test_suite* s =
        BOOST_TEST_SUITE("spirit::sf_bug_720917");

    s->add(BOOST_TEST_CASE(construct_string_from<default_multi_pass_t>));
    s->add(BOOST_TEST_CASE(construct_string_from<fixed_multi_pass_t>));
    s->add(BOOST_TEST_CASE(construct_string_from<first_owner_multi_pass_t>));
    s->add(BOOST_TEST_CASE(construct_string_from<functor_multi_pass_t>));

    return s;
}
