regex_split.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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 regex_split.hpp
  14. * VERSION see <boost/version.hpp>
  15. * DESCRIPTION: Implements regex_split and associated functions.
  16. * Note this is an internal header file included
  17. * by regex.hpp, do not include on its own.
  18. */
  19. #ifndef BOOST_REGEX_SPLIT_HPP
  20. #define BOOST_REGEX_SPLIT_HPP
  21. namespace boost{
  22. #ifdef BOOST_REGEX_MSVC
  23. # pragma warning(push)
  24. #if BOOST_REGEX_MSVC < 1910
  25. #pragma warning(disable:4800)
  26. #endif
  27. #endif
  28. namespace BOOST_REGEX_DETAIL_NS{
  29. template <class charT>
  30. const basic_regex<charT>& get_default_expression(charT)
  31. {
  32. static const charT expression_text[4] = { '\\', 's', '+', '\00', };
  33. static const basic_regex<charT> e(expression_text);
  34. return e;
  35. }
  36. template <class OutputIterator, class charT, class Traits1, class Alloc1>
  37. class split_pred
  38. {
  39. typedef std::basic_string<charT, Traits1, Alloc1> string_type;
  40. typedef typename string_type::const_iterator iterator_type;
  41. iterator_type* p_last;
  42. OutputIterator* p_out;
  43. std::size_t* p_max;
  44. std::size_t initial_max;
  45. public:
  46. split_pred(iterator_type* a, OutputIterator* b, std::size_t* c)
  47. : p_last(a), p_out(b), p_max(c), initial_max(*c) {}
  48. bool operator()(const match_results<iterator_type>& what);
  49. };
  50. template <class OutputIterator, class charT, class Traits1, class Alloc1>
  51. bool split_pred<OutputIterator, charT, Traits1, Alloc1>::operator()
  52. (const match_results<iterator_type>& what)
  53. {
  54. *p_last = what[0].second;
  55. if(what.size() > 1)
  56. {
  57. // output sub-expressions only:
  58. for(unsigned i = 1; i < what.size(); ++i)
  59. {
  60. *(*p_out) = what.str(i);
  61. ++(*p_out);
  62. if(0 == --*p_max) return false;
  63. }
  64. return *p_max != 0;
  65. }
  66. else
  67. {
  68. // output $` only if it's not-null or not at the start of the input:
  69. const sub_match<iterator_type>& sub = what[-1];
  70. if((sub.first != sub.second) || (*p_max != initial_max))
  71. {
  72. *(*p_out) = sub.str();
  73. ++(*p_out);
  74. return --*p_max;
  75. }
  76. }
  77. //
  78. // initial null, do nothing:
  79. return true;
  80. }
  81. } // namespace BOOST_REGEX_DETAIL_NS
  82. template <class OutputIterator, class charT, class Traits1, class Alloc1, class Traits2>
  83. std::size_t regex_split(OutputIterator out,
  84. std::basic_string<charT, Traits1, Alloc1>& s,
  85. const basic_regex<charT, Traits2>& e,
  86. match_flag_type flags,
  87. std::size_t max_split)
  88. {
  89. typedef typename std::basic_string<charT, Traits1, Alloc1>::const_iterator ci_t;
  90. //typedef typename match_results<ci_t>::allocator_type match_allocator;
  91. ci_t last = s.begin();
  92. std::size_t init_size = max_split;
  93. BOOST_REGEX_DETAIL_NS::split_pred<OutputIterator, charT, Traits1, Alloc1> pred(&last, &out, &max_split);
  94. ci_t i, j;
  95. i = s.begin();
  96. j = s.end();
  97. regex_grep(pred, i, j, e, flags);
  98. //
  99. // if there is still input left, do a final push as long as max_split
  100. // is not exhausted, and we're not splitting sub-expressions rather
  101. // than whitespace:
  102. if(max_split && (last != s.end()) && (e.mark_count() == 0))
  103. {
  104. *out = std::basic_string<charT, Traits1, Alloc1>((ci_t)last, (ci_t)s.end());
  105. ++out;
  106. last = s.end();
  107. --max_split;
  108. }
  109. //
  110. // delete from the string everything that has been processed so far:
  111. s.erase(0, last - s.begin());
  112. //
  113. // return the number of new records pushed:
  114. return init_size - max_split;
  115. }
  116. template <class OutputIterator, class charT, class Traits1, class Alloc1, class Traits2>
  117. inline std::size_t regex_split(OutputIterator out,
  118. std::basic_string<charT, Traits1, Alloc1>& s,
  119. const basic_regex<charT, Traits2>& e,
  120. match_flag_type flags = match_default)
  121. {
  122. return regex_split(out, s, e, flags, UINT_MAX);
  123. }
  124. template <class OutputIterator, class charT, class Traits1, class Alloc1>
  125. inline std::size_t regex_split(OutputIterator out,
  126. std::basic_string<charT, Traits1, Alloc1>& s)
  127. {
  128. return regex_split(out, s, BOOST_REGEX_DETAIL_NS::get_default_expression(charT(0)), match_default, UINT_MAX);
  129. }
  130. #ifdef BOOST_REGEX_MSVC
  131. # pragma warning(pop)
  132. #endif
  133. } // namespace boost
  134. #endif