Last active
December 31, 2015 04:59
-
-
Save dgodfrey206/7938186 to your computer and use it in GitHub Desktop.
Inserter/Extractor for a Line object
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 <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