Created
May 13, 2014 22:20
-
-
Save dgodfrey206/3bbe83852bedc6555b2a to your computer and use it in GitHub Desktop.
Word extractor part 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <sstream> | |
#include <typeinfo> | |
namespace detail | |
{ | |
template<int... Is> | |
struct index { }; | |
template<int N, int... Is> | |
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { }; | |
template<int... Is> | |
struct gen_seq<0, Is...> : index<Is...> { }; | |
} | |
class word_get_base : public std::locale::facet | |
{ | |
protected: | |
using back_iterator = std::back_insert_iterator<std::string>; | |
using iter_type = std::istreambuf_iterator<char>; | |
virtual iter_type do_get( iter_type, iter_type, std::ios_base&, | |
std::ios_base::iostate&, back_iterator) const = 0; | |
public: | |
static std::locale::id id; | |
explicit word_get_base(int refs = 0) : std::locale::facet(refs) { } | |
iter_type get( iter_type it, iter_type end, std::ios_base& str, | |
std::ios_base::iostate& err, back_iterator out) const | |
{ | |
return do_get(it, end, str, err, out); | |
} | |
}; | |
std::locale::id word_get_base::id; | |
class word_get : public word_get_base | |
{ | |
public: | |
explicit word_get(int refs = 0) : word_get_base(refs) { } | |
iter_type do_get( iter_type it, iter_type end, std::ios_base& str, | |
std::ios_base::iostate& err, back_iterator out) const | |
{ | |
ctype = &std::use_facet<std::ctype<char>>(str.getloc()); | |
int count = 0; | |
for (char c = *it; it != end; ++count) | |
{ | |
if (ctype->is(ctype->space, c)) | |
{ | |
out = c; | |
break; | |
} | |
out = *it++; | |
} | |
if (it == end) | |
err |= std::ios_base::eofbit; | |
return it; | |
} | |
private: | |
mutable const std::ctype<char>* ctype; | |
}; | |
template<int> | |
class word_extractor_impl | |
{ | |
public: | |
word_extractor_impl(std::string& value) | |
: value_(value) | |
{ } | |
template<int N> | |
friend std::istream& | |
operator>>(std::istream& is, const word_extractor_impl<N>& manip); | |
private: | |
std::string& value_; | |
}; | |
template<int... Is> | |
std::ios_base::iostate | |
word_extractor(std::istream& is, std::string& str, detail::index<Is...>) | |
{ | |
std::string temp; | |
std::ios_base::iostate total = std::ios_base::goodbit; | |
std::istreambuf_iterator<char> end; | |
auto f = [&] { | |
std::ios_base::iostate result = std::ios_base::goodbit, | |
fail = std::ios_base::failbit | std::ios_base::badbit; | |
std::use_facet<word_get>(is.getloc()) | |
.get(is, end, is, result, std::back_inserter(temp)); | |
if (!(result & fail)) | |
{ | |
str += temp; | |
temp.clear(); | |
} | |
total |= result; | |
}; | |
auto l = { 0, (f(), Is)... }; | |
(void)l; | |
return total; | |
} | |
template<int N> | |
std::istream& | |
operator>>(std::istream& is, const word_extractor_impl<N>& manip) | |
{ | |
std::istream::sentry ok(is); | |
std::ios_base::iostate err = std::ios_base::goodbit; | |
if (ok) | |
{ | |
is.imbue(std::locale(is.getloc(), new word_get)); | |
try | |
{ | |
err |= word_extractor(is, manip.value_, detail::gen_seq<N>()); | |
} catch (std::bad_cast&) { | |
err |= std::ios_base::failbit; | |
} catch (...) { | |
err |= std::ios_base::badbit; | |
} | |
} | |
else | |
err |= std::ios_base::failbit; | |
is.setstate(err); | |
return is; | |
} | |
template<int N> | |
word_extractor_impl<N> word_extractor(std::string& str) | |
{ | |
return word_extractor_impl<N>(str); | |
} | |
int main() | |
{ | |
std::stringstream ss("1 Bob Marely 2"); | |
std::string str; | |
int a, b; | |
if (ss >> a >> word_extractor<2>(str) >> b); | |
{ | |
std::cout << str; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment