Skip to content

Instantly share code, notes, and snippets.

@NicolBolas
Created December 30, 2016 17:06
Show Gist options
  • Save NicolBolas/f326fab93f237c2e1c2fb58b10442f18 to your computer and use it in GitHub Desktop.
Save NicolBolas/f326fab93f237c2e1c2fb58b10442f18 to your computer and use it in GitHub Desktop.
C++ regex-based string splitter
template<typename CharT, typename Traits = std::char_traits<CharT>>
class split_range_regex
{
public:
using value_type = std::basic_string_view<CharT, Traits>;
using traits_type = Traits;
using size_type = typename value_type::size_type;
using difference_type = typename value_type::difference_type;
using reference = value_type;
using const_reference = reference;
using pointer = const value_type *;
using const_pointer = pointer;
using regex_type = std::basic_regex<CharT>;
class iterator : public std::forward_iterator_tag
{
public:
iterator(value_type sv, const regex_type &re)
: it_(sv.begin(), sv.end(), re, -1)
{}
iterator() = default;
reference operator*() const {get_curr(); return curr_;}
pointer operator->() const {get_curr(); return &curr_;}
iterator &operator++() {++it_; return *this;}
iterator operator++(int)
{
auto temp = *this;
++it_;
return temp;
}
bool operator==(const iterator &rhs) { return it_ == rhs.it_; }
bool operator!=(const iterator &rhs) { return it_ != rhs.it_; }
private:
using token_iterator = std::regex_token_iterator<typename value_type::iterator, CharT>;
token_iterator it_;
mutable value_type curr_; //Here just because -> requires a value to get a pointer to.
void get_curr() const
{
auto match = *it_;
curr_ = value_type(&*match.first, match.length());
}
};
using const_iterator = iterator;
split_range_regex(value_type sv, const regex_type &re)
: first_(sv, re)
{}
split_range_regex() = delete;
iterator begin() const noexcept {return iterator(first_);}
const_iterator cbegin() const noexcept {return const_iterator(first_);}
iterator end() const noexcept {return iterator(past_last_);}
const_iterator cend() const noexcept {return const_iterator(past_last_);}
bool empty() const noexcept
{
return past_last_ == first_;
}
private:
iterator first_;
iterator past_last_;
};
template<typename CharT, typename Traits = std::char_traits<CharT>>
split_range_regex<CharT, Traits> split_string(std::basic_string_view<CharT, Traits> sv,
const typename split_range_regex<CharT, Traits>::regex_type &re)
{
return split_range_regex<CharT, Traits>(sv, re);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment