match_results.hpp 21 KB

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