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