match_results.hpp 17 KB

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