Skip to content

Instantly share code, notes, and snippets.

@dgodfrey206
Last active December 31, 2015 04:59
Show Gist options
  • Save dgodfrey206/7938186 to your computer and use it in GitHub Desktop.
Save dgodfrey206/7938186 to your computer and use it in GitHub Desktop.
Inserter/Extractor for a Line object
#include <iostream>
#include <utility>
#include <tuple>
#include <sstream>
#include <typeinfo>
#include <vector>
using namespace std;
class Point
{
public:
Point() = default;
Point(int x1, int y1)
: x(x1), y(y1)
{ }
Point(const Point& other)
: x(other.x), y(other.y)
{ }
Point& operator=(const std::pair<int, int>& p)
{
std::tie(x, y) = p;
return *this;
}
std::pair<int, int> get_point() const
{
return std::make_pair(x, y);
}
private:
int x, y;
template<class charT>
friend basic_istream<charT>& operator>>(basic_istream<charT>& is, Point& p)
{
return is >> p.x >> p.y;
}
template<class charT>
friend basic_ostream<charT>& operator<<(basic_ostream<charT>& os,
const std::pair<Point, Point>& p)
{
return os << "(" << p.first.x << ", " << p.first.y << "),"
<< "(" << p.second.x << ", " << p.second.y << ")";
}
};
class Line
{
public:
Line() = default;
Line(const Point& _p1, const Point& _p2)
: p1(_p1), p2(_p2)
{ }
private:
Point p1, p2;
template<class charT>
friend basic_istream<charT>& operator>>(basic_istream<charT>&, Line&);
template<class charT>
friend basic_ostream<charT>& operator<<(basic_ostream<charT>&, const Line&);
};
template<class charT, class iterator = istreambuf_iterator<charT>>
class line_get : public locale::facet
{
public:
typedef charT char_type;
typedef iterator iter_type;
public:
static locale::id id;
line_get(int refs = 0) : locale::facet(refs) { }
virtual void get(basic_istream<charT>& is, Point& p1, Point& p2) const
{
do_get(is, p1, p2);
}
protected:
virtual void do_get(basic_istream<charT>& is, Point& p1, Point& p2) const
{
is >> p1 >> p2;
}
};
template<class charT, class iterator = ostreambuf_iterator<charT>>
class line_put : public locale::facet
{
public:
typedef charT char_type;
typedef iterator iter_type;
public:
static locale::id id;
line_put(int refs = 0) : locale::facet(refs) { }
virtual void put(basic_ostream<charT>& os, const Point& p1,
const Point& p2) const
{
do_put(os, p1, p2);
}
protected:
virtual void do_put(basic_ostream<charT>& os, const Point& p1,
const Point& p2) const
{
os << std::make_pair(p1, p2);
}
};
template<class charT, class iter>
locale::id line_get<charT, iter>::id;
template<class charT, class iter>
locale::id line_put<charT, iter>::id;
template<class charT>
basic_istream<charT>& operator>>(basic_istream<charT>& is, Line& l)
{
typename basic_istream<charT>::sentry s(is);
if (s)
{
locale loc = is.getloc();
try
{
auto& f = use_facet<line_get<charT>>(loc);
f.get(is, l.p1, l.p2);
} catch (const bad_cast&) { }
}
return is;
}
template<class charT>
basic_ostream<charT>& operator<<(basic_ostream<charT>& os, const Line& l)
{
typename basic_ostream<charT>::sentry s(os);
if (s)
{
locale loc = os.getloc();
try
{
auto& f = use_facet<line_put<charT>>(loc);
f.put(os, l.p1, l.p2);
} catch (const bad_cast&) { }
}
return os;
}
class ignore_commas : public std::ctype<char>
{
public:
static mask* make_table()
{
static std::vector<mask> v(classic_table(), classic_table() + table_size);
int spaces[7] = {0x20, 0x0c, 0x0a, 0x0d, 0x09, 0x0b, ','};
for (int i : spaces)
v[i] |= space;
return &v[0];
}
ignore_commas(int refs = 0) : ctype(make_table(), false, refs) { }
};
template<class Line>
class line_extractor
{
public:
line_extractor(Line& l)
: line(l)
{ }
private:
Line& line;
template<class charT, class Facet = line_get<charT>>
void extract(basic_istream<charT>& is, Facet* f = new Facet) const
{
locale original = is.getloc();
is.imbue(locale(is.getloc(), new ignore_commas));
is.imbue(locale(is.getloc(), f));
is >> line;
is.imbue(original);
}
template<class charT>
friend basic_istream<charT>& operator>>(basic_istream<charT>& is,
const line_extractor& li)
{
li.extract(is);
return is;
}
};
template<class Line>
class line_inserter
{
public:
line_inserter(const Line& l)
: line(l)
{ }
private:
Line line;
template<class charT, class Facet = line_put<charT>>
void insert(basic_ostream<charT>& os, Facet* f = new Facet) const
{
locale original = os.getloc();
os.imbue(locale(original, f));
os << line << endl;
os.imbue(original);
}
template<class charT>
friend basic_ostream<charT>& operator<<(basic_ostream<charT>& os,
const line_inserter& li)
{
li.insert(os);
return os;
}
};
template<class Line>
line_extractor<Line> get_line(Line& line)
{
return line_extractor<Line>(line);
}
template<class Line>
line_inserter<Line> put_line(const Line& line)
{
return line_inserter<Line>(line);
}
int main()
{
Line l;
std::istringstream iss("4,2 5,9 6,2");
iss >> get_line(l);
cout << put_line(l);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment