state.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // state.hpp
  3. //
  4. // Copyright 2008 Eric Niebler. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_XPRESSIVE_DETAIL_CORE_STATE_HPP_EAN_10_04_2005
  8. #define BOOST_XPRESSIVE_DETAIL_CORE_STATE_HPP_EAN_10_04_2005
  9. // MS compatible compilers support #pragma once
  10. #if defined(_MSC_VER)
  11. # pragma once
  12. #endif
  13. #include <boost/noncopyable.hpp>
  14. #include <boost/xpressive/detail/detail_fwd.hpp>
  15. #include <boost/xpressive/detail/core/access.hpp>
  16. #include <boost/xpressive/detail/core/action.hpp>
  17. #include <boost/xpressive/detail/core/sub_match_vector.hpp>
  18. #include <boost/xpressive/detail/utility/sequence_stack.hpp>
  19. #include <boost/xpressive/detail/core/regex_impl.hpp>
  20. #include <boost/xpressive/regex_constants.hpp>
  21. namespace boost { namespace xpressive { namespace detail
  22. {
  23. ///////////////////////////////////////////////////////////////////////////////
  24. // match_context
  25. //
  26. template<typename BidiIter>
  27. struct match_context
  28. {
  29. typedef typename iterator_value<BidiIter>::type char_type;
  30. match_context()
  31. : results_ptr_(0)
  32. , prev_context_(0)
  33. , next_ptr_(0)
  34. , traits_(0)
  35. {
  36. }
  37. // pointer to the current match results, passed to actions as a parameter.
  38. match_results<BidiIter> *results_ptr_;
  39. // The previous match context, if this match_context corresponds to a nested regex invocation
  40. match_context<BidiIter> *prev_context_;
  41. // If this is a nested match, the "next" sub-expression to execute after the nested match
  42. matchable<BidiIter> const *next_ptr_;
  43. // A pointer to the current traits object
  44. detail::traits<char_type> const *traits_;
  45. };
  46. ///////////////////////////////////////////////////////////////////////////////
  47. // attr_context
  48. //
  49. struct attr_context
  50. {
  51. // Slots for holding type-erased pointers to attributes
  52. void const **attr_slots_;
  53. // The previous attr context, if one exists
  54. attr_context *prev_attr_context_;
  55. };
  56. ///////////////////////////////////////////////////////////////////////////////
  57. // match_flags
  58. //
  59. struct match_flags
  60. {
  61. bool match_all_;
  62. bool match_prev_avail_;
  63. bool match_bol_;
  64. bool match_eol_;
  65. bool match_not_bow_;
  66. bool match_not_eow_;
  67. bool match_not_null_;
  68. bool match_continuous_;
  69. bool match_partial_;
  70. explicit match_flags(regex_constants::match_flag_type flags)
  71. : match_all_(false)
  72. , match_prev_avail_(0 != (flags & regex_constants::match_prev_avail))
  73. , match_bol_(match_prev_avail_ || 0 == (flags & regex_constants::match_not_bol))
  74. , match_eol_(0 == (flags & regex_constants::match_not_eol))
  75. , match_not_bow_(!match_prev_avail_ && 0 != (flags & regex_constants::match_not_bow))
  76. , match_not_eow_(0 != (flags & regex_constants::match_not_eow))
  77. , match_not_null_(0 != (flags & regex_constants::match_not_null))
  78. , match_continuous_(0 != (flags & regex_constants::match_continuous))
  79. , match_partial_(0 != (flags & regex_constants::match_partial))
  80. {
  81. }
  82. };
  83. ///////////////////////////////////////////////////////////////////////////////
  84. // match_state
  85. //
  86. template<typename BidiIter>
  87. struct match_state
  88. : noncopyable
  89. {
  90. typedef BidiIter iterator;
  91. typedef core_access<BidiIter> access;
  92. typedef detail::match_context<BidiIter> match_context;
  93. typedef detail::results_extras<BidiIter> results_extras;
  94. typedef detail::regex_impl<BidiIter> regex_impl;
  95. typedef detail::matchable<BidiIter> matchable;
  96. typedef xpressive::match_results<BidiIter> match_results;
  97. typedef detail::sub_match_impl<BidiIter> sub_match_impl;
  98. typedef detail::actionable actionable;
  99. BidiIter cur_;
  100. sub_match_impl *sub_matches_;
  101. std::size_t mark_count_;
  102. BidiIter begin_;
  103. BidiIter end_;
  104. match_flags flags_;
  105. bool found_partial_match_;
  106. match_context context_;
  107. results_extras *extras_;
  108. actionable action_list_;
  109. actionable const **action_list_tail_;
  110. action_args_type *action_args_;
  111. attr_context attr_context_;
  112. BidiIter next_search_;
  113. ///////////////////////////////////////////////////////////////////////////////
  114. //
  115. match_state
  116. (
  117. BidiIter begin
  118. , BidiIter end
  119. , match_results &what
  120. , regex_impl const &impl
  121. , regex_constants::match_flag_type flags
  122. )
  123. : cur_(begin)
  124. , sub_matches_(0)
  125. , mark_count_(0)
  126. , begin_(begin)
  127. , end_(end)
  128. , flags_(flags)
  129. , found_partial_match_(false)
  130. , context_() // zero-initializes the fields of context_
  131. , extras_(&core_access<BidiIter>::get_extras(what))
  132. , action_list_()
  133. , action_list_tail_(&action_list_.next)
  134. , action_args_(&core_access<BidiIter>::get_action_args(what))
  135. , attr_context_() // zero-initializes the fields of attr_context_
  136. , next_search_(begin)
  137. {
  138. // reclaim any cached memory in the match_results struct
  139. this->extras_->sub_match_stack_.unwind();
  140. // initialize the context_ struct
  141. this->init_(impl, what);
  142. // move all the nested match_results structs into the match_results cache
  143. this->extras_->results_cache_.reclaim_all(access::get_nested_results(what));
  144. }
  145. ///////////////////////////////////////////////////////////////////////////////
  146. // reset
  147. void reset(match_results &what, regex_impl const &impl)
  148. {
  149. this->extras_ = &core_access<BidiIter>::get_extras(what);
  150. this->action_list_.next = 0;
  151. this->action_list_tail_ = &action_list_.next;
  152. this->action_args_ = &core_access<BidiIter>::get_action_args(what);
  153. this->attr_context_ = attr_context();
  154. this->context_.prev_context_ = 0;
  155. this->found_partial_match_ = false;
  156. this->extras_->sub_match_stack_.unwind();
  157. this->init_(impl, what);
  158. this->extras_->results_cache_.reclaim_all(access::get_nested_results(what));
  159. }
  160. ///////////////////////////////////////////////////////////////////////////////
  161. // push_context
  162. // called to prepare the state object for a regex match
  163. match_context push_context(regex_impl const &impl, matchable const &next, match_context &prev)
  164. {
  165. // save state
  166. match_context context = this->context_;
  167. // create a new nested match_results for this regex
  168. nested_results<BidiIter> &nested = access::get_nested_results(*context.results_ptr_);
  169. match_results &what = this->extras_->results_cache_.append_new(nested);
  170. // (re)initialize the match context
  171. this->init_(impl, what);
  172. // create a linked list of match_context structs
  173. this->context_.prev_context_ = &prev;
  174. this->context_.next_ptr_ = &next;
  175. // record the start of the zero-th sub-match
  176. this->sub_matches_[0].begin_ = this->cur_;
  177. return context;
  178. }
  179. ///////////////////////////////////////////////////////////////////////////////
  180. // pop_context
  181. // called after a nested match failed to restore the context
  182. bool pop_context(regex_impl const &impl, bool success)
  183. {
  184. match_context &context = *this->context_.prev_context_;
  185. if(!success)
  186. {
  187. match_results &what = *context.results_ptr_;
  188. this->uninit_(impl, what);
  189. // send the match_results struct back to the cache
  190. nested_results<BidiIter> &nested = access::get_nested_results(what);
  191. this->extras_->results_cache_.reclaim_last(nested);
  192. }
  193. // restore the state
  194. this->context_ = context;
  195. match_results &results = *this->context_.results_ptr_;
  196. this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
  197. this->mark_count_ = results.size();
  198. return success;
  199. }
  200. ///////////////////////////////////////////////////////////////////////////////
  201. // swap_context
  202. void swap_context(match_context &context)
  203. {
  204. std::swap(this->context_, context);
  205. match_results &results = *this->context_.results_ptr_;
  206. this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
  207. this->mark_count_ = results.size();
  208. }
  209. // beginning of buffer
  210. bool bos() const
  211. {
  212. return this->cur_ == this->begin_;
  213. }
  214. // end of buffer
  215. bool eos()
  216. {
  217. return this->cur_ == this->end_ && this->found_partial_match();
  218. }
  219. // is this the regex that is currently executing?
  220. bool is_active_regex(regex_impl const &impl) const
  221. {
  222. return impl.xpr_.get() == this->context_.results_ptr_->regex_id();
  223. }
  224. // fetch the n-th sub_match
  225. sub_match_impl &sub_match(int n)
  226. {
  227. return this->sub_matches_[n];
  228. }
  229. // called when a partial match has succeeded
  230. void set_partial_match()
  231. {
  232. sub_match_impl &sub0 = this->sub_match(0);
  233. sub0.first = sub0.begin_;
  234. sub0.second = this->end_;
  235. sub0.matched = false;
  236. }
  237. template<typename Traits>
  238. Traits const &get_traits() const
  239. {
  240. return static_cast<traits_holder<Traits> const *>(this->context_.traits_)->traits();
  241. }
  242. private:
  243. void init_(regex_impl const &impl, match_results &what)
  244. {
  245. regex_id_type const id = impl.xpr_.get();
  246. std::size_t const total_mark_count = impl.mark_count_ + impl.hidden_mark_count_ + 1;
  247. // initialize the context and the sub_match vector
  248. this->context_.results_ptr_ = &what;
  249. this->context_.traits_ = impl.traits_.get();
  250. this->mark_count_ = impl.mark_count_ + 1;
  251. this->sub_matches_ = this->extras_->sub_match_stack_.push_sequence(total_mark_count, sub_match_impl(begin_), detail::fill);
  252. this->sub_matches_ += impl.hidden_mark_count_;
  253. // initialize the match_results struct
  254. access::init_match_results(what, id, impl.traits_, this->sub_matches_, this->mark_count_, impl.named_marks_);
  255. }
  256. void uninit_(regex_impl const &impl, match_results &)
  257. {
  258. extras_->sub_match_stack_.unwind_to(this->sub_matches_ - impl.hidden_mark_count_);
  259. }
  260. bool found_partial_match()
  261. {
  262. this->found_partial_match_ = true;
  263. return true;
  264. }
  265. };
  266. ///////////////////////////////////////////////////////////////////////////////
  267. // memento
  268. //
  269. template<typename BidiIter>
  270. struct memento
  271. {
  272. sub_match_impl<BidiIter> *old_sub_matches_;
  273. std::size_t nested_results_count_;
  274. actionable const *action_list_head_;
  275. actionable const **action_list_tail_;
  276. attr_context attr_context_;
  277. };
  278. ///////////////////////////////////////////////////////////////////////////////
  279. // save_sub_matches
  280. //
  281. template<typename BidiIter>
  282. inline memento<BidiIter> save_sub_matches(match_state<BidiIter> &state)
  283. {
  284. memento<BidiIter> mem =
  285. {
  286. state.extras_->sub_match_stack_.push_sequence(state.mark_count_, sub_match_impl<BidiIter>(state.begin_))
  287. , state.context_.results_ptr_->nested_results().size()
  288. , state.action_list_.next
  289. , state.action_list_tail_
  290. , state.attr_context_
  291. };
  292. state.action_list_.next = 0;
  293. state.action_list_tail_ = &state.action_list_.next;
  294. std::copy(state.sub_matches_, state.sub_matches_ + state.mark_count_, mem.old_sub_matches_);
  295. return mem;
  296. }
  297. ///////////////////////////////////////////////////////////////////////////////
  298. // restore_action_queue
  299. //
  300. template<typename BidiIter>
  301. inline void restore_action_queue(memento<BidiIter> const &mem, match_state<BidiIter> &state)
  302. {
  303. state.action_list_.next = mem.action_list_head_;
  304. state.action_list_tail_ = mem.action_list_tail_;
  305. *state.action_list_tail_ = 0;
  306. }
  307. ///////////////////////////////////////////////////////////////////////////////
  308. // restore_sub_matches
  309. //
  310. template<typename BidiIter>
  311. inline void restore_sub_matches(memento<BidiIter> const &mem, match_state<BidiIter> &state)
  312. {
  313. typedef core_access<BidiIter> access;
  314. nested_results<BidiIter> &nested = access::get_nested_results(*state.context_.results_ptr_);
  315. std::size_t count = nested.size() - mem.nested_results_count_;
  316. state.extras_->results_cache_.reclaim_last_n(nested, count);
  317. std::copy(mem.old_sub_matches_, mem.old_sub_matches_ + state.mark_count_, state.sub_matches_);
  318. state.extras_->sub_match_stack_.unwind_to(mem.old_sub_matches_);
  319. state.attr_context_ = mem.attr_context_;
  320. }
  321. ///////////////////////////////////////////////////////////////////////////////
  322. // reclaim_sub_matches
  323. //
  324. template<typename BidiIter>
  325. inline void reclaim_sub_matches(memento<BidiIter> const &mem, match_state<BidiIter> &state, bool success)
  326. {
  327. std::size_t count = state.context_.results_ptr_->nested_results().size() - mem.nested_results_count_;
  328. if(count == 0)
  329. {
  330. state.extras_->sub_match_stack_.unwind_to(mem.old_sub_matches_);
  331. }
  332. // else we have we must orphan this block of backrefs because we are using the stack
  333. // space above it.
  334. if(!success)
  335. {
  336. state.attr_context_ = mem.attr_context_;
  337. }
  338. }
  339. ///////////////////////////////////////////////////////////////////////////////
  340. // traits_cast
  341. //
  342. template<typename Traits, typename BidiIter>
  343. inline Traits const &traits_cast(match_state<BidiIter> const &state)
  344. {
  345. return state.template get_traits<Traits>();
  346. }
  347. }}} // namespace boost::xpressive::detail
  348. #endif