match_results.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. /*
  2. *
  3. * Copyright (c) 1998-2009
  4. * John Maddock
  5. *
  6. * Use, modification and distribution are subject to the
  7. * Boost Software License, Version 1.0. (See accompanying file
  8. * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. *
  10. */
  11. /*
  12. * LOCATION: see http://www.boost.org for most recent version.
  13. * FILE match_results.cpp
  14. * VERSION see <boost/version.hpp>
  15. * DESCRIPTION: Declares template class match_results.
  16. */
  17. #ifndef BOOST_REGEX_V5_MATCH_RESULTS_HPP
  18. #define BOOST_REGEX_V5_MATCH_RESULTS_HPP
  19. #include <boost/regex/v5/match_flags.hpp>
  20. #include <boost/regex/v5/sub_match.hpp>
  21. #include <boost/regex/v5/basic_regex.hpp>
  22. #include <boost/regex/v5/regex_format.hpp>
  23. #ifndef BOOST_REGEX_AS_MODULE
  24. #include <string>
  25. #include <vector>
  26. #endif
  27. namespace boost{
  28. #ifdef BOOST_REGEX_MSVC
  29. #pragma warning(push)
  30. #pragma warning(disable : 4251 4459)
  31. #if BOOST_REGEX_MSVC < 1700
  32. # pragma warning(disable : 4231)
  33. #endif
  34. # if BOOST_REGEX_MSVC < 1600
  35. # pragma warning(disable : 4660)
  36. # endif
  37. #endif
  38. namespace BOOST_REGEX_DETAIL_NS{
  39. class named_subexpressions;
  40. }
  41. BOOST_REGEX_MODULE_EXPORT template <class BidiIterator, class Allocator>
  42. class match_results
  43. {
  44. private:
  45. typedef std::vector<sub_match<BidiIterator>, Allocator> vector_type;
  46. public:
  47. typedef sub_match<BidiIterator> value_type;
  48. typedef typename std::allocator_traits<Allocator>::value_type const & const_reference;
  49. typedef const_reference reference;
  50. typedef typename vector_type::const_iterator const_iterator;
  51. typedef const_iterator iterator;
  52. typedef typename std::iterator_traits<
  53. BidiIterator>::difference_type difference_type;
  54. typedef typename std::allocator_traits<Allocator>::size_type size_type;
  55. typedef Allocator allocator_type;
  56. typedef typename std::iterator_traits<
  57. BidiIterator>::value_type char_type;
  58. typedef std::basic_string<char_type> string_type;
  59. typedef BOOST_REGEX_DETAIL_NS::named_subexpressions named_sub_type;
  60. // construct/copy/destroy:
  61. explicit match_results(const Allocator& a = Allocator())
  62. : m_subs(a), m_base(), m_null(), m_last_closed_paren(0), m_is_singular(true) {}
  63. //
  64. // IMPORTANT: in the code below, the crazy looking checks around m_is_singular are
  65. // all required because it is illegal to copy a singular iterator.
  66. // See https://svn.boost.org/trac/boost/ticket/3632.
  67. //
  68. match_results(const match_results& m)
  69. : m_subs(m.m_subs), m_base(), m_null(), m_named_subs(m.m_named_subs), m_last_closed_paren(m.m_last_closed_paren), m_is_singular(m.m_is_singular)
  70. {
  71. if(!m_is_singular)
  72. {
  73. m_base = m.m_base;
  74. m_null = m.m_null;
  75. }
  76. }
  77. match_results& operator=(const match_results& m)
  78. {
  79. m_subs = m.m_subs;
  80. m_named_subs = m.m_named_subs;
  81. m_last_closed_paren = m.m_last_closed_paren;
  82. m_is_singular = m.m_is_singular;
  83. if(!m_is_singular)
  84. {
  85. m_base = m.m_base;
  86. m_null = m.m_null;
  87. }
  88. return *this;
  89. }
  90. ~match_results(){}
  91. // size:
  92. size_type size() const
  93. { return empty() ? 0 : m_subs.size() - 2; }
  94. size_type max_size() const
  95. { return m_subs.max_size(); }
  96. bool empty() const
  97. { return m_subs.size() < 2; }
  98. // element access:
  99. private:
  100. difference_type do_get_length(int sub = 0) const
  101. {
  102. if (m_is_singular)
  103. raise_logic_error();
  104. sub += 2;
  105. if ((sub < (int)m_subs.size()) && (sub > 0))
  106. return m_subs[sub].length();
  107. return 0;
  108. }
  109. public:
  110. template <class Integer>
  111. typename std::enable_if<std::is_integral<Integer>::value, difference_type>::type length(Integer sub) const
  112. {
  113. return do_get_length(static_cast<int>(sub));
  114. }
  115. difference_type length() const { return do_get_length(0); }
  116. difference_type length(const char_type* sub) const
  117. {
  118. if(m_is_singular)
  119. raise_logic_error();
  120. const char_type* sub_end = sub;
  121. while(*sub_end) ++sub_end;
  122. return length(named_subexpression_index(sub, sub_end));
  123. }
  124. template <class charT>
  125. difference_type length(const charT* sub) const
  126. {
  127. if(m_is_singular)
  128. raise_logic_error();
  129. const charT* sub_end = sub;
  130. while(*sub_end) ++sub_end;
  131. return length(named_subexpression_index(sub, sub_end));
  132. }
  133. template <class charT, class Traits, class A>
  134. difference_type length(const std::basic_string<charT, Traits, A>& sub) const
  135. {
  136. return length(sub.c_str());
  137. }
  138. difference_type position(size_type sub = 0) const
  139. {
  140. if(m_is_singular)
  141. raise_logic_error();
  142. sub += 2;
  143. if(sub < m_subs.size())
  144. {
  145. const sub_match<BidiIterator>& s = m_subs[sub];
  146. if(s.matched || (sub == 2))
  147. {
  148. return std::distance((BidiIterator)(m_base), (BidiIterator)(s.first));
  149. }
  150. }
  151. return ~static_cast<difference_type>(0);
  152. }
  153. difference_type position(const char_type* sub) const
  154. {
  155. const char_type* sub_end = sub;
  156. while(*sub_end) ++sub_end;
  157. return position(named_subexpression_index(sub, sub_end));
  158. }
  159. template <class charT>
  160. difference_type position(const charT* sub) const
  161. {
  162. const charT* sub_end = sub;
  163. while(*sub_end) ++sub_end;
  164. return position(named_subexpression_index(sub, sub_end));
  165. }
  166. template <class charT, class Traits, class A>
  167. difference_type position(const std::basic_string<charT, Traits, A>& sub) const
  168. {
  169. return position(sub.c_str());
  170. }
  171. private:
  172. string_type do_get_string(int sub = 0) const
  173. {
  174. if(m_is_singular)
  175. raise_logic_error();
  176. sub += 2;
  177. string_type result;
  178. if(sub < (int)m_subs.size() && (sub > 0))
  179. {
  180. const sub_match<BidiIterator>& s = m_subs[sub];
  181. if(s.matched)
  182. {
  183. result = s.str();
  184. }
  185. }
  186. return result;
  187. }
  188. public:
  189. template <class Integer>
  190. typename std::enable_if<std::is_integral<Integer>::value, string_type>::type str(Integer sub) const
  191. {
  192. return do_get_string(static_cast<int>(sub));
  193. }
  194. string_type str() const { return do_get_string(0); }
  195. string_type str(const char_type* sub) const
  196. {
  197. return (*this)[sub].str();
  198. }
  199. template <class Traits, class A>
  200. string_type str(const std::basic_string<char_type, Traits, A>& sub) const
  201. {
  202. return (*this)[sub].str();
  203. }
  204. template <class charT>
  205. string_type str(const charT* sub) const
  206. {
  207. return (*this)[sub].str();
  208. }
  209. template <class charT, class Traits, class A>
  210. string_type str(const std::basic_string<charT, Traits, A>& sub) const
  211. {
  212. return (*this)[sub].str();
  213. }
  214. private:
  215. const_reference get_at(int sub) const
  216. {
  217. if(m_is_singular && m_subs.empty())
  218. raise_logic_error();
  219. if (sub >= INT_MAX - 2 )
  220. return m_null;
  221. sub += 2;
  222. if(sub < (int)m_subs.size() && (sub >= 0))
  223. {
  224. return m_subs[sub];
  225. }
  226. return m_null;
  227. }
  228. public:
  229. template <class Integer>
  230. typename std::enable_if<std::is_integral<Integer>::value, const_reference>::type operator[](Integer sub) const
  231. {
  232. return get_at(static_cast<int>(sub));
  233. }
  234. //
  235. // Named sub-expressions:
  236. //
  237. const_reference named_subexpression(const char_type* i, const char_type* j) const
  238. {
  239. //
  240. // Scan for the leftmost *matched* subexpression with the specified named:
  241. //
  242. if(m_is_singular)
  243. raise_logic_error();
  244. BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type r = m_named_subs->equal_range(i, j);
  245. while((r.first != r.second) && ((*this)[r.first->index].matched == false))
  246. ++r.first;
  247. return r.first != r.second ? (*this)[r.first->index] : m_null;
  248. }
  249. template <class charT>
  250. const_reference named_subexpression(const charT* i, const charT* j) const
  251. {
  252. static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
  253. if(i == j)
  254. return m_null;
  255. std::vector<char_type> s;
  256. while(i != j)
  257. s.insert(s.end(), *i++);
  258. return named_subexpression(&*s.begin(), &*s.begin() + s.size());
  259. }
  260. int named_subexpression_index(const char_type* i, const char_type* j) const
  261. {
  262. //
  263. // Scan for the leftmost *matched* subexpression with the specified named.
  264. // If none found then return the leftmost expression with that name,
  265. // otherwise an invalid index:
  266. //
  267. if(m_is_singular)
  268. raise_logic_error();
  269. BOOST_REGEX_DETAIL_NS::named_subexpressions::range_type s, r;
  270. s = r = m_named_subs->equal_range(i, j);
  271. while((r.first != r.second) && ((*this)[r.first->index].matched == false))
  272. ++r.first;
  273. if(r.first == r.second)
  274. r = s;
  275. return r.first != r.second ? r.first->index : -20;
  276. }
  277. template <class charT>
  278. int named_subexpression_index(const charT* i, const charT* j) const
  279. {
  280. static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
  281. if(i == j)
  282. return -20;
  283. std::vector<char_type> s;
  284. while(i != j)
  285. s.insert(s.end(), *i++);
  286. return named_subexpression_index(&*s.begin(), &*s.begin() + s.size());
  287. }
  288. template <class Traits, class A>
  289. const_reference operator[](const std::basic_string<char_type, Traits, A>& s) const
  290. {
  291. return named_subexpression(s.c_str(), s.c_str() + s.size());
  292. }
  293. const_reference operator[](const char_type* p) const
  294. {
  295. const char_type* e = p;
  296. while(*e) ++e;
  297. return named_subexpression(p, e);
  298. }
  299. template <class charT>
  300. const_reference operator[](const charT* p) const
  301. {
  302. static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
  303. if(*p == 0)
  304. return m_null;
  305. std::vector<char_type> s;
  306. while(*p)
  307. s.insert(s.end(), *p++);
  308. return named_subexpression(&*s.begin(), &*s.begin() + s.size());
  309. }
  310. template <class charT, class Traits, class A>
  311. const_reference operator[](const std::basic_string<charT, Traits, A>& ns) const
  312. {
  313. static_assert(sizeof(charT) <= sizeof(char_type), "Failed internal logic");
  314. if(ns.empty())
  315. return m_null;
  316. std::vector<char_type> s;
  317. for(unsigned i = 0; i < ns.size(); ++i)
  318. s.insert(s.end(), ns[i]);
  319. return named_subexpression(&*s.begin(), &*s.begin() + s.size());
  320. }
  321. const_reference prefix() const
  322. {
  323. if(m_is_singular)
  324. raise_logic_error();
  325. return (*this)[-1];
  326. }
  327. const_reference suffix() const
  328. {
  329. if(m_is_singular)
  330. raise_logic_error();
  331. return (*this)[-2];
  332. }
  333. const_iterator begin() const
  334. {
  335. return (m_subs.size() > 2) ? (m_subs.begin() + 2) : m_subs.end();
  336. }
  337. const_iterator end() const
  338. {
  339. return m_subs.end();
  340. }
  341. // format:
  342. template <class OutputIterator, class Functor>
  343. OutputIterator format(OutputIterator out,
  344. Functor fmt,
  345. match_flag_type flags = format_default) const
  346. {
  347. if(m_is_singular)
  348. raise_logic_error();
  349. typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, OutputIterator>::type F;
  350. F func(fmt);
  351. return func(*this, out, flags);
  352. }
  353. template <class Functor>
  354. string_type format(Functor fmt, match_flag_type flags = format_default) const
  355. {
  356. if(m_is_singular)
  357. raise_logic_error();
  358. std::basic_string<char_type> result;
  359. BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> > i(result);
  360. typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> > >::type F;
  361. F func(fmt);
  362. func(*this, i, flags);
  363. return result;
  364. }
  365. // format with locale:
  366. template <class OutputIterator, class Functor, class RegexT>
  367. OutputIterator format(OutputIterator out,
  368. Functor fmt,
  369. match_flag_type flags,
  370. const RegexT& re) const
  371. {
  372. if(m_is_singular)
  373. raise_logic_error();
  374. typedef ::boost::regex_traits_wrapper<typename RegexT::traits_type> traits_type;
  375. typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, OutputIterator, traits_type>::type F;
  376. F func(fmt);
  377. return func(*this, out, flags, re.get_traits());
  378. }
  379. template <class RegexT, class Functor>
  380. string_type format(Functor fmt,
  381. match_flag_type flags,
  382. const RegexT& re) const
  383. {
  384. if(m_is_singular)
  385. raise_logic_error();
  386. typedef ::boost::regex_traits_wrapper<typename RegexT::traits_type> traits_type;
  387. std::basic_string<char_type> result;
  388. BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> > i(result);
  389. typedef typename BOOST_REGEX_DETAIL_NS::compute_functor_type<Functor, match_results<BidiIterator, Allocator>, BOOST_REGEX_DETAIL_NS::string_out_iterator<std::basic_string<char_type> >, traits_type >::type F;
  390. F func(fmt);
  391. func(*this, i, flags, re.get_traits());
  392. return result;
  393. }
  394. const_reference get_last_closed_paren()const
  395. {
  396. if(m_is_singular)
  397. raise_logic_error();
  398. return m_last_closed_paren == 0 ? m_null : (*this)[m_last_closed_paren];
  399. }
  400. allocator_type get_allocator() const
  401. {
  402. return m_subs.get_allocator();
  403. }
  404. void swap(match_results& that)
  405. {
  406. std::swap(m_subs, that.m_subs);
  407. std::swap(m_named_subs, that.m_named_subs);
  408. std::swap(m_last_closed_paren, that.m_last_closed_paren);
  409. if(m_is_singular)
  410. {
  411. if(!that.m_is_singular)
  412. {
  413. m_base = that.m_base;
  414. m_null = that.m_null;
  415. }
  416. }
  417. else if(that.m_is_singular)
  418. {
  419. that.m_base = m_base;
  420. that.m_null = m_null;
  421. }
  422. else
  423. {
  424. std::swap(m_base, that.m_base);
  425. std::swap(m_null, that.m_null);
  426. }
  427. std::swap(m_is_singular, that.m_is_singular);
  428. }
  429. bool operator==(const match_results& that)const
  430. {
  431. if(m_is_singular)
  432. {
  433. return that.m_is_singular;
  434. }
  435. else if(that.m_is_singular)
  436. {
  437. return false;
  438. }
  439. return (m_subs == that.m_subs) && (m_base == that.m_base) && (m_last_closed_paren == that.m_last_closed_paren);
  440. }
  441. bool operator!=(const match_results& that)const
  442. { return !(*this == that); }
  443. #ifdef BOOST_REGEX_MATCH_EXTRA
  444. typedef typename sub_match<BidiIterator>::capture_sequence_type capture_sequence_type;
  445. const capture_sequence_type& captures(int i)const
  446. {
  447. if(m_is_singular)
  448. raise_logic_error();
  449. return (*this)[i].captures();
  450. }
  451. #endif
  452. //
  453. // private access functions:
  454. void set_second(BidiIterator i)
  455. {
  456. BOOST_REGEX_ASSERT(m_subs.size() > 2);
  457. m_subs[2].second = i;
  458. m_subs[2].matched = true;
  459. m_subs[0].first = i;
  460. m_subs[0].matched = (m_subs[0].first != m_subs[0].second);
  461. m_null.first = i;
  462. m_null.second = i;
  463. m_null.matched = false;
  464. m_is_singular = false;
  465. }
  466. void set_second(BidiIterator i, size_type pos, bool m = true, bool escape_k = false)
  467. {
  468. if(pos)
  469. m_last_closed_paren = static_cast<int>(pos);
  470. pos += 2;
  471. BOOST_REGEX_ASSERT(m_subs.size() > pos);
  472. m_subs[pos].second = i;
  473. m_subs[pos].matched = m;
  474. if((pos == 2) && !escape_k)
  475. {
  476. m_subs[0].first = i;
  477. m_subs[0].matched = (m_subs[0].first != m_subs[0].second);
  478. m_null.first = i;
  479. m_null.second = i;
  480. m_null.matched = false;
  481. m_is_singular = false;
  482. }
  483. }
  484. void set_size(size_type n, BidiIterator i, BidiIterator j)
  485. {
  486. value_type v(j);
  487. size_type len = m_subs.size();
  488. if(len > n + 2)
  489. {
  490. m_subs.erase(m_subs.begin()+n+2, m_subs.end());
  491. std::fill(m_subs.begin(), m_subs.end(), v);
  492. }
  493. else
  494. {
  495. std::fill(m_subs.begin(), m_subs.end(), v);
  496. if(n+2 != len)
  497. m_subs.insert(m_subs.end(), n+2-len, v);
  498. }
  499. m_subs[1].first = i;
  500. m_last_closed_paren = 0;
  501. }
  502. void set_base(BidiIterator pos)
  503. {
  504. m_base = pos;
  505. }
  506. BidiIterator base()const
  507. {
  508. return m_base;
  509. }
  510. void set_first(BidiIterator i)
  511. {
  512. BOOST_REGEX_ASSERT(m_subs.size() > 2);
  513. // set up prefix:
  514. m_subs[1].second = i;
  515. m_subs[1].matched = (m_subs[1].first != i);
  516. // set up $0:
  517. m_subs[2].first = i;
  518. // zero out everything else:
  519. for(size_type n = 3; n < m_subs.size(); ++n)
  520. {
  521. m_subs[n].first = m_subs[n].second = m_subs[0].second;
  522. m_subs[n].matched = false;
  523. }
  524. }
  525. void set_first(BidiIterator i, size_type pos, bool escape_k = false)
  526. {
  527. BOOST_REGEX_ASSERT(pos+2 < m_subs.size());
  528. if(pos || escape_k)
  529. {
  530. m_subs[pos+2].first = i;
  531. if(escape_k)
  532. {
  533. m_subs[1].second = i;
  534. m_subs[1].matched = (m_subs[1].first != m_subs[1].second);
  535. }
  536. }
  537. else
  538. set_first(i);
  539. }
  540. void maybe_assign(const match_results<BidiIterator, Allocator>& m);
  541. void set_named_subs(std::shared_ptr<named_sub_type> subs)
  542. {
  543. m_named_subs = std::move(subs);
  544. }
  545. private:
  546. //
  547. // Error handler called when an uninitialized match_results is accessed:
  548. //
  549. static void raise_logic_error()
  550. {
  551. std::logic_error e("Attempt to access an uninitialized boost::match_results<> class.");
  552. #ifndef BOOST_REGEX_STANDALONE
  553. boost::throw_exception(e);
  554. #else
  555. throw e;
  556. #endif
  557. }
  558. vector_type m_subs; // subexpressions
  559. BidiIterator m_base; // where the search started from
  560. sub_match<BidiIterator> m_null; // a null match
  561. std::shared_ptr<named_sub_type> m_named_subs; // Shared copy of named subs in the regex object
  562. int m_last_closed_paren; // Last ) to be seen - used for formatting
  563. bool m_is_singular; // True if our stored iterators are singular
  564. };
  565. template <class BidiIterator, class Allocator>
  566. void match_results<BidiIterator, Allocator>::maybe_assign(const match_results<BidiIterator, Allocator>& m)
  567. {
  568. if(m_is_singular)
  569. {
  570. *this = m;
  571. return;
  572. }
  573. const_iterator p1, p2;
  574. p1 = begin();
  575. p2 = m.begin();
  576. //
  577. // Distances are measured from the start of *this* match, unless this isn't
  578. // a valid match in which case we use the start of the whole sequence. Note that
  579. // no subsequent match-candidate can ever be to the left of the first match found.
  580. // This ensures that when we are using bidirectional iterators, that distances
  581. // measured are as short as possible, and therefore as efficient as possible
  582. // to compute. Finally note that we don't use the "matched" data member to test
  583. // whether a sub-expression is a valid match, because partial matches set this
  584. // to false for sub-expression 0.
  585. //
  586. BidiIterator l_end = this->suffix().second;
  587. BidiIterator l_base = (p1->first == l_end) ? this->prefix().first : (*this)[0].first;
  588. difference_type len1 = 0;
  589. difference_type len2 = 0;
  590. difference_type base1 = 0;
  591. difference_type base2 = 0;
  592. std::size_t i;
  593. for(i = 0; i < size(); ++i, ++p1, ++p2)
  594. {
  595. //
  596. // Leftmost takes priority over longest; handle special cases
  597. // where distances need not be computed first (an optimisation
  598. // for bidirectional iterators: ensure that we don't accidently
  599. // compute the length of the whole sequence, as this can be really
  600. // expensive).
  601. //
  602. if(p1->first == l_end)
  603. {
  604. if(p2->first != l_end)
  605. {
  606. // p2 must be better than p1, and no need to calculate
  607. // actual distances:
  608. base1 = 1;
  609. base2 = 0;
  610. break;
  611. }
  612. else
  613. {
  614. // *p1 and *p2 are either unmatched or match end-of sequence,
  615. // either way no need to calculate distances:
  616. if((p1->matched == false) && (p2->matched == true))
  617. break;
  618. if((p1->matched == true) && (p2->matched == false))
  619. return;
  620. continue;
  621. }
  622. }
  623. else if(p2->first == l_end)
  624. {
  625. // p1 better than p2, and no need to calculate distances:
  626. return;
  627. }
  628. base1 = std::distance(l_base, p1->first);
  629. base2 = std::distance(l_base, p2->first);
  630. BOOST_REGEX_ASSERT(base1 >= 0);
  631. BOOST_REGEX_ASSERT(base2 >= 0);
  632. if(base1 < base2) return;
  633. if(base2 < base1) break;
  634. len1 = std::distance((BidiIterator)p1->first, (BidiIterator)p1->second);
  635. len2 = std::distance((BidiIterator)p2->first, (BidiIterator)p2->second);
  636. BOOST_REGEX_ASSERT(len1 >= 0);
  637. BOOST_REGEX_ASSERT(len2 >= 0);
  638. if((len1 != len2) || ((p1->matched == false) && (p2->matched == true)))
  639. break;
  640. if((p1->matched == true) && (p2->matched == false))
  641. return;
  642. }
  643. if(i == size())
  644. return;
  645. if(base2 < base1)
  646. *this = m;
  647. else if((len2 > len1) || ((p1->matched == false) && (p2->matched == true)) )
  648. *this = m;
  649. }
  650. BOOST_REGEX_MODULE_EXPORT template <class BidiIterator, class Allocator>
  651. void swap(match_results<BidiIterator, Allocator>& a, match_results<BidiIterator, Allocator>& b)
  652. {
  653. a.swap(b);
  654. }
  655. BOOST_REGEX_MODULE_EXPORT template <class charT, class traits, class BidiIterator, class Allocator>
  656. std::basic_ostream<charT, traits>&
  657. operator << (std::basic_ostream<charT, traits>& os,
  658. const match_results<BidiIterator, Allocator>& s)
  659. {
  660. return (os << s.str());
  661. }
  662. #ifdef BOOST_REGEX_MSVC
  663. #pragma warning(pop)
  664. #endif
  665. } // namespace boost
  666. #endif