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

    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)
 =============================================================================*/

#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;
#ifdef __BORLANDC__ //  Should have used boost::spirit::assign_actor but
                    //  Borland has a linker error BC it couldn't find
                    //  the string::replace code.
        copy(mp1, mpend, back_insert_iterator<std::string>(dummy));
#else
    dummy.assign(mp1, mpend);
#endif
}

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;
#ifdef __BORLANDC__ //  Should have used boost::spirit::assign_actor but
                    //  Borland has a linker error BC it couldn't find
                    //  the string::replace code.
        copy(mp1, mpend, back_insert_iterator<std::string>(dummy));
#else
    dummy.assign(mp1, mpend);
#endif
}

////////////////////////////////////////////////
// Definition of the test suite
//boost::unit_test_framework::test_suite*
int main(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>));

    construct_string_from<default_multi_pass_t>();
    construct_string_from<fixed_multi_pass_t>();
    construct_string_from<first_owner_multi_pass_t>();
    construct_string_from<functor_multi_pass_t>();

    return 0;
}
