Skip to content

Instantly share code, notes, and snippets.

@dgodfrey206
Created May 13, 2014 22:20
Show Gist options
  • Save dgodfrey206/3bbe83852bedc6555b2a to your computer and use it in GitHub Desktop.
Save dgodfrey206/3bbe83852bedc6555b2a to your computer and use it in GitHub Desktop.
Word extractor part 2
#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