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 
24 namespace 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 
44 namespace BOOST_REGEX_DETAIL_NS{
45 
46 template <class charT>
get_default_expression(charT)47 const 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 
54 template <class OutputIterator, class charT, class Traits1, class Alloc1>
55 class 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;
63 public:
split_pred(iterator_type * a,OutputIterator * b,std::size_t * c)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 
70 template <class OutputIterator, class charT, class Traits1, class Alloc1>
operator ()(const match_results<iterator_type> & what)71 bool 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 
104 template <class OutputIterator, class charT, class Traits1, class Alloc1, class Traits2>
regex_split(OutputIterator out,std::basic_string<charT,Traits1,Alloc1> & s,const basic_regex<charT,Traits2> & e,match_flag_type flags,std::size_t max_split)105 std::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 
139 template <class OutputIterator, class charT, class Traits1, class Alloc1, class Traits2>
regex_split(OutputIterator out,std::basic_string<charT,Traits1,Alloc1> & s,const basic_regex<charT,Traits2> & e,match_flag_type flags=match_default)140 inline 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 
148 template <class OutputIterator, class charT, class Traits1, class Alloc1>
regex_split(OutputIterator out,std::basic_string<charT,Traits1,Alloc1> & s)149 inline 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