match_results.hpp 22 KB

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