/* | |
* | |
* Copyright (c) 1998-2002 | |
* John Maddock | |
* | |
* Use, modification and distribution are subject to the | |
* Boost Software License, Version 1.0. (See accompanying file | |
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
* | |
*/ | |
/* | |
* LOCATION: see http://www.boost.org for most recent version. | |
* FILE regex_split.hpp | |
* VERSION see <boost/version.hpp> | |
* DESCRIPTION: Implements regex_split and associated functions. | |
* Note this is an internal header file included | |
* by regex.hpp, do not include on its own. | |
*/ | |
#ifndef BOOST_REGEX_SPLIT_HPP | |
#define BOOST_REGEX_SPLIT_HPP | |
namespace boost{ | |
#ifdef BOOST_MSVC | |
#pragma warning(push) | |
#pragma warning(disable: 4103) | |
#endif | |
#ifdef BOOST_HAS_ABI_HEADERS | |
# include BOOST_ABI_PREFIX | |
#endif | |
#ifdef BOOST_MSVC | |
#pragma warning(pop) | |
#endif | |
#ifdef BOOST_MSVC | |
# pragma warning(push) | |
# pragma warning(disable: 4800) | |
#endif | |
namespace re_detail{ | |
template <class charT> | |
const basic_regex<charT>& get_default_expression(charT) | |
{ | |
static const charT expression_text[4] = { '\\', 's', '+', '\00', }; | |
static const basic_regex<charT> e(expression_text); | |
return e; | |
} | |
template <class OutputIterator, class charT, class Traits1, class Alloc1> | |
class split_pred | |
{ | |
typedef std::basic_string<charT, Traits1, Alloc1> string_type; | |
typedef typename string_type::const_iterator iterator_type; | |
iterator_type* p_last; | |
OutputIterator* p_out; | |
std::size_t* p_max; | |
std::size_t initial_max; | |
public: | |
split_pred(iterator_type* a, OutputIterator* b, std::size_t* c) | |
: p_last(a), p_out(b), p_max(c), initial_max(*c) {} | |
bool operator()(const match_results<iterator_type>& what); | |
}; | |
template <class OutputIterator, class charT, class Traits1, class Alloc1> | |
bool split_pred<OutputIterator, charT, Traits1, Alloc1>::operator() | |
(const match_results<iterator_type>& what) | |
{ | |
*p_last = what[0].second; | |
if(what.size() > 1) | |
{ | |
// output sub-expressions only: | |
for(unsigned i = 1; i < what.size(); ++i) | |
{ | |
*(*p_out) = what.str(i); | |
++(*p_out); | |
if(0 == --*p_max) return false; | |
} | |
return *p_max != 0; | |
} | |
else | |
{ | |
// output $` only if it's not-null or not at the start of the input: | |
const sub_match<iterator_type>& sub = what[-1]; | |
if((sub.first != sub.second) || (*p_max != initial_max)) | |
{ | |
*(*p_out) = sub.str(); | |
++(*p_out); | |
return --*p_max; | |
} | |
} | |
// | |
// initial null, do nothing: | |
return true; | |
} | |
} // namespace re_detail | |
template <class OutputIterator, class charT, class Traits1, class Alloc1, class Traits2> | |
std::size_t 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) | |
{ | |
typedef typename std::basic_string<charT, Traits1, Alloc1>::const_iterator ci_t; | |
typedef typename match_results<ci_t>::allocator_type match_allocator; | |
ci_t last = s.begin(); | |
std::size_t init_size = max_split; | |
re_detail::split_pred<OutputIterator, charT, Traits1, Alloc1> pred(&last, &out, &max_split); | |
ci_t i, j; | |
i = s.begin(); | |
j = s.end(); | |
regex_grep(pred, i, j, e, flags); | |
// | |
// if there is still input left, do a final push as long as max_split | |
// is not exhausted, and we're not splitting sub-expressions rather | |
// than whitespace: | |
if(max_split && (last != s.end()) && (e.mark_count() == 1)) | |
{ | |
*out = std::basic_string<charT, Traits1, Alloc1>((ci_t)last, (ci_t)s.end()); | |
++out; | |
last = s.end(); | |
--max_split; | |
} | |
// | |
// delete from the string everything that has been processed so far: | |
s.erase(0, last - s.begin()); | |
// | |
// return the number of new records pushed: | |
return init_size - max_split; | |
} | |
template <class OutputIterator, class charT, class Traits1, class Alloc1, class Traits2> | |
inline std::size_t regex_split(OutputIterator out, | |
std::basic_string<charT, Traits1, Alloc1>& s, | |
const basic_regex<charT, Traits2>& e, | |
match_flag_type flags = match_default) | |
{ | |
return regex_split(out, s, e, flags, UINT_MAX); | |
} | |
template <class OutputIterator, class charT, class Traits1, class Alloc1> | |
inline std::size_t regex_split(OutputIterator out, | |
std::basic_string<charT, Traits1, Alloc1>& s) | |
{ | |
return regex_split(out, s, re_detail::get_default_expression(charT(0)), match_default, UINT_MAX); | |
} | |
#ifdef BOOST_MSVC | |
# pragma warning(pop) | |
#endif | |
#ifdef BOOST_MSVC | |
#pragma warning(push) | |
#pragma warning(disable: 4103) | |
#endif | |
#ifdef BOOST_HAS_ABI_HEADERS | |
# include BOOST_ABI_SUFFIX | |
#endif | |
#ifdef BOOST_MSVC | |
#pragma warning(pop) | |
#endif | |
} // namespace boost | |
#endif | |