///////////////////////////////////////////////////////////////////////////////

// string_matcher.hpp

//

//  Copyright 2007 Eric Niebler. 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_XPRESSIVE_DETAIL_CORE_MATCHER_STRING_MATCHER_HPP_EAN_10_04_2005

#define BOOST_XPRESSIVE_DETAIL_CORE_MATCHER_STRING_MATCHER_HPP_EAN_10_04_2005



// MS compatible compilers support #pragma once

#if defined(_MSC_VER) && (_MSC_VER >= 1020)

# pragma once

#endif



#include <string>

#include <boost/mpl/bool.hpp>

#include <boost/xpressive/detail/detail_fwd.hpp>

#include <boost/xpressive/detail/core/quant_style.hpp>

#include <boost/xpressive/detail/core/state.hpp>

#include <boost/xpressive/detail/utility/algorithm.hpp>

#include <boost/xpressive/detail/utility/traits_utils.hpp>



namespace boost { namespace xpressive { namespace detail

{

    ///////////////////////////////////////////////////////////////////////////////

    // string_matcher

    //

    template<typename Traits, bool ICase>

    struct string_matcher

      : quant_style_fixed_unknown_width

    {

        typedef typename Traits::char_type char_type;

        typedef typename Traits::string_type string_type;

        typedef mpl::bool_<ICase> icase_type;

        string_type str_;

        char_type const *end_;



        string_matcher(string_type const &str, Traits const &traits)

          : str_(str)

          , end_()

        {

            typename range_iterator<string_type>::type cur = boost::begin(this->str_);

            typename range_iterator<string_type>::type end = boost::end(this->str_);

            for(; cur != end; ++cur)

            {

                *cur = detail::translate(*cur, traits, icase_type());

            }

            this->end_ = detail::data_end(str_);

        }



        string_matcher(string_matcher<Traits, ICase> const &that)

          : str_(that.str_)

          , end_(detail::data_end(str_))

        {

        }



        template<typename BidiIter, typename Next>

        bool match(match_state<BidiIter> &state, Next const &next) const

        {

            BidiIter const tmp = state.cur_;

            char_type const *begin = detail::data_begin(this->str_);

            for(; begin != this->end_; ++begin, ++state.cur_)

            {

                if(state.eos() ||

                    (detail::translate(*state.cur_, traits_cast<Traits>(state), icase_type()) != *begin))

                {

                    state.cur_ = tmp;

                    return false;

                }

            }



            if(next.match(state))

            {

                return true;

            }



            state.cur_ = tmp;

            return false;

        }



        detail::width get_width() const

        {

            return boost::size(this->str_);

        }

    };



}}}



#endif

