regex_split.hpp 4.6 KB

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