123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- ///////////////////////////////////////////////////////////////////////////////
- // state.hpp
- //
- // Copyright 2008 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_STATE_HPP_EAN_10_04_2005
- #define BOOST_XPRESSIVE_DETAIL_CORE_STATE_HPP_EAN_10_04_2005
- // MS compatible compilers support #pragma once
- #if defined(_MSC_VER)
- # pragma once
- #endif
- #include <boost/noncopyable.hpp>
- #include <boost/xpressive/detail/detail_fwd.hpp>
- #include <boost/xpressive/detail/core/access.hpp>
- #include <boost/xpressive/detail/core/action.hpp>
- #include <boost/xpressive/detail/core/sub_match_vector.hpp>
- #include <boost/xpressive/detail/utility/sequence_stack.hpp>
- #include <boost/xpressive/detail/core/regex_impl.hpp>
- #include <boost/xpressive/regex_constants.hpp>
- namespace boost { namespace xpressive { namespace detail
- {
- ///////////////////////////////////////////////////////////////////////////////
- // match_context
- //
- template<typename BidiIter>
- struct match_context
- {
- typedef typename iterator_value<BidiIter>::type char_type;
- match_context()
- : results_ptr_(0)
- , prev_context_(0)
- , next_ptr_(0)
- , traits_(0)
- {
- }
- // pointer to the current match results, passed to actions as a parameter.
- match_results<BidiIter> *results_ptr_;
- // The previous match context, if this match_context corresponds to a nested regex invocation
- match_context<BidiIter> *prev_context_;
- // If this is a nested match, the "next" sub-expression to execute after the nested match
- matchable<BidiIter> const *next_ptr_;
- // A pointer to the current traits object
- detail::traits<char_type> const *traits_;
- };
- ///////////////////////////////////////////////////////////////////////////////
- // attr_context
- //
- struct attr_context
- {
- // Slots for holding type-erased pointers to attributes
- void const **attr_slots_;
- // The previous attr context, if one exists
- attr_context *prev_attr_context_;
- };
- ///////////////////////////////////////////////////////////////////////////////
- // match_flags
- //
- struct match_flags
- {
- bool match_all_;
- bool match_prev_avail_;
- bool match_bol_;
- bool match_eol_;
- bool match_not_bow_;
- bool match_not_eow_;
- bool match_not_null_;
- bool match_continuous_;
- bool match_partial_;
- explicit match_flags(regex_constants::match_flag_type flags)
- : match_all_(false)
- , match_prev_avail_(0 != (flags & regex_constants::match_prev_avail))
- , match_bol_(match_prev_avail_ || 0 == (flags & regex_constants::match_not_bol))
- , match_eol_(0 == (flags & regex_constants::match_not_eol))
- , match_not_bow_(!match_prev_avail_ && 0 != (flags & regex_constants::match_not_bow))
- , match_not_eow_(0 != (flags & regex_constants::match_not_eow))
- , match_not_null_(0 != (flags & regex_constants::match_not_null))
- , match_continuous_(0 != (flags & regex_constants::match_continuous))
- , match_partial_(0 != (flags & regex_constants::match_partial))
- {
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // match_state
- //
- template<typename BidiIter>
- struct match_state
- : noncopyable
- {
- typedef BidiIter iterator;
- typedef core_access<BidiIter> access;
- typedef detail::match_context<BidiIter> match_context;
- typedef detail::results_extras<BidiIter> results_extras;
- typedef detail::regex_impl<BidiIter> regex_impl;
- typedef detail::matchable<BidiIter> matchable;
- typedef xpressive::match_results<BidiIter> match_results;
- typedef detail::sub_match_impl<BidiIter> sub_match_impl;
- typedef detail::actionable actionable;
- BidiIter cur_;
- sub_match_impl *sub_matches_;
- std::size_t mark_count_;
- BidiIter begin_;
- BidiIter end_;
- match_flags flags_;
- bool found_partial_match_;
- match_context context_;
- results_extras *extras_;
- actionable action_list_;
- actionable const **action_list_tail_;
- action_args_type *action_args_;
- attr_context attr_context_;
- BidiIter next_search_;
- ///////////////////////////////////////////////////////////////////////////////
- //
- match_state
- (
- BidiIter begin
- , BidiIter end
- , match_results &what
- , regex_impl const &impl
- , regex_constants::match_flag_type flags
- )
- : cur_(begin)
- , sub_matches_(0)
- , mark_count_(0)
- , begin_(begin)
- , end_(end)
- , flags_(flags)
- , found_partial_match_(false)
- , context_() // zero-initializes the fields of context_
- , extras_(&core_access<BidiIter>::get_extras(what))
- , action_list_()
- , action_list_tail_(&action_list_.next)
- , action_args_(&core_access<BidiIter>::get_action_args(what))
- , attr_context_() // zero-initializes the fields of attr_context_
- , next_search_(begin)
- {
- // reclaim any cached memory in the match_results struct
- this->extras_->sub_match_stack_.unwind();
- // initialize the context_ struct
- this->init_(impl, what);
- // move all the nested match_results structs into the match_results cache
- this->extras_->results_cache_.reclaim_all(access::get_nested_results(what));
- }
- ///////////////////////////////////////////////////////////////////////////////
- // reset
- void reset(match_results &what, regex_impl const &impl)
- {
- this->extras_ = &core_access<BidiIter>::get_extras(what);
- this->action_list_.next = 0;
- this->action_list_tail_ = &action_list_.next;
- this->action_args_ = &core_access<BidiIter>::get_action_args(what);
- this->attr_context_ = attr_context();
- this->context_.prev_context_ = 0;
- this->found_partial_match_ = false;
- this->extras_->sub_match_stack_.unwind();
- this->init_(impl, what);
- this->extras_->results_cache_.reclaim_all(access::get_nested_results(what));
- }
- ///////////////////////////////////////////////////////////////////////////////
- // push_context
- // called to prepare the state object for a regex match
- match_context push_context(regex_impl const &impl, matchable const &next, match_context &prev)
- {
- // save state
- match_context context = this->context_;
- // create a new nested match_results for this regex
- nested_results<BidiIter> &nested = access::get_nested_results(*context.results_ptr_);
- match_results &what = this->extras_->results_cache_.append_new(nested);
- // (re)initialize the match context
- this->init_(impl, what);
- // create a linked list of match_context structs
- this->context_.prev_context_ = &prev;
- this->context_.next_ptr_ = &next;
- // record the start of the zero-th sub-match
- this->sub_matches_[0].begin_ = this->cur_;
- return context;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // pop_context
- // called after a nested match failed to restore the context
- bool pop_context(regex_impl const &impl, bool success)
- {
- match_context &context = *this->context_.prev_context_;
- if(!success)
- {
- match_results &what = *context.results_ptr_;
- this->uninit_(impl, what);
- // send the match_results struct back to the cache
- nested_results<BidiIter> &nested = access::get_nested_results(what);
- this->extras_->results_cache_.reclaim_last(nested);
- }
- // restore the state
- this->context_ = context;
- match_results &results = *this->context_.results_ptr_;
- this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
- this->mark_count_ = results.size();
- return success;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // swap_context
- void swap_context(match_context &context)
- {
- std::swap(this->context_, context);
- match_results &results = *this->context_.results_ptr_;
- this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
- this->mark_count_ = results.size();
- }
- // beginning of buffer
- bool bos() const
- {
- return this->cur_ == this->begin_;
- }
- // end of buffer
- bool eos()
- {
- return this->cur_ == this->end_ && this->found_partial_match();
- }
- // is this the regex that is currently executing?
- bool is_active_regex(regex_impl const &impl) const
- {
- return impl.xpr_.get() == this->context_.results_ptr_->regex_id();
- }
- // fetch the n-th sub_match
- sub_match_impl &sub_match(int n)
- {
- return this->sub_matches_[n];
- }
- // called when a partial match has succeeded
- void set_partial_match()
- {
- sub_match_impl &sub0 = this->sub_match(0);
- sub0.first = sub0.begin_;
- sub0.second = this->end_;
- sub0.matched = false;
- }
- template<typename Traits>
- Traits const &get_traits() const
- {
- return static_cast<traits_holder<Traits> const *>(this->context_.traits_)->traits();
- }
- private:
- void init_(regex_impl const &impl, match_results &what)
- {
- regex_id_type const id = impl.xpr_.get();
- std::size_t const total_mark_count = impl.mark_count_ + impl.hidden_mark_count_ + 1;
- // initialize the context and the sub_match vector
- this->context_.results_ptr_ = &what;
- this->context_.traits_ = impl.traits_.get();
- this->mark_count_ = impl.mark_count_ + 1;
- this->sub_matches_ = this->extras_->sub_match_stack_.push_sequence(total_mark_count, sub_match_impl(begin_), detail::fill);
- this->sub_matches_ += impl.hidden_mark_count_;
- // initialize the match_results struct
- access::init_match_results(what, id, impl.traits_, this->sub_matches_, this->mark_count_, impl.named_marks_);
- }
- void uninit_(regex_impl const &impl, match_results &)
- {
- extras_->sub_match_stack_.unwind_to(this->sub_matches_ - impl.hidden_mark_count_);
- }
- bool found_partial_match()
- {
- this->found_partial_match_ = true;
- return true;
- }
- };
- ///////////////////////////////////////////////////////////////////////////////
- // memento
- //
- template<typename BidiIter>
- struct memento
- {
- sub_match_impl<BidiIter> *old_sub_matches_;
- std::size_t nested_results_count_;
- actionable const *action_list_head_;
- actionable const **action_list_tail_;
- attr_context attr_context_;
- };
- ///////////////////////////////////////////////////////////////////////////////
- // save_sub_matches
- //
- template<typename BidiIter>
- inline memento<BidiIter> save_sub_matches(match_state<BidiIter> &state)
- {
- memento<BidiIter> mem =
- {
- state.extras_->sub_match_stack_.push_sequence(state.mark_count_, sub_match_impl<BidiIter>(state.begin_))
- , state.context_.results_ptr_->nested_results().size()
- , state.action_list_.next
- , state.action_list_tail_
- , state.attr_context_
- };
- state.action_list_.next = 0;
- state.action_list_tail_ = &state.action_list_.next;
- std::copy(state.sub_matches_, state.sub_matches_ + state.mark_count_, mem.old_sub_matches_);
- return mem;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // restore_action_queue
- //
- template<typename BidiIter>
- inline void restore_action_queue(memento<BidiIter> const &mem, match_state<BidiIter> &state)
- {
- state.action_list_.next = mem.action_list_head_;
- state.action_list_tail_ = mem.action_list_tail_;
- *state.action_list_tail_ = 0;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // restore_sub_matches
- //
- template<typename BidiIter>
- inline void restore_sub_matches(memento<BidiIter> const &mem, match_state<BidiIter> &state)
- {
- typedef core_access<BidiIter> access;
- nested_results<BidiIter> &nested = access::get_nested_results(*state.context_.results_ptr_);
- std::size_t count = nested.size() - mem.nested_results_count_;
- state.extras_->results_cache_.reclaim_last_n(nested, count);
- std::copy(mem.old_sub_matches_, mem.old_sub_matches_ + state.mark_count_, state.sub_matches_);
- state.extras_->sub_match_stack_.unwind_to(mem.old_sub_matches_);
- state.attr_context_ = mem.attr_context_;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // reclaim_sub_matches
- //
- template<typename BidiIter>
- inline void reclaim_sub_matches(memento<BidiIter> const &mem, match_state<BidiIter> &state, bool success)
- {
- std::size_t count = state.context_.results_ptr_->nested_results().size() - mem.nested_results_count_;
- if(count == 0)
- {
- state.extras_->sub_match_stack_.unwind_to(mem.old_sub_matches_);
- }
- // else we have we must orphan this block of backrefs because we are using the stack
- // space above it.
- if(!success)
- {
- state.attr_context_ = mem.attr_context_;
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- // traits_cast
- //
- template<typename Traits, typename BidiIter>
- inline Traits const &traits_cast(match_state<BidiIter> const &state)
- {
- return state.template get_traits<Traits>();
- }
- }}} // namespace boost::xpressive::detail
- #endif
|