Last active
August 29, 2015 13:58
-
-
Save dgodfrey206/9975127 to your computer and use it in GitHub Desktop.
Program that allows an arbitrary separator between each output sequence.
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> | |
namespace custom | |
{ | |
struct sep_impl | |
{ | |
sep_impl(std::string const& separator); | |
std::string separator; | |
}; | |
sep_impl sep(std::string const& str) | |
{ | |
return sep_impl(str); | |
} | |
std::ostream& nosep(std::ostream& os); | |
} | |
int separatorEnabled() | |
{ static int idx = std::ios_base::xalloc(); return idx; } | |
int getSeparator() { static int idx = std::ios_base::xalloc(); return idx; } | |
struct custom_separator : std::streambuf | |
{ | |
public: | |
custom_separator(std::ostream& _stream) : stream(_stream) | |
{ } | |
int_type overflow(int_type c) | |
{ | |
return stream.rdbuf()->sputc(c); | |
} | |
int sync() | |
{ | |
if (stream.iword(separatorEnabled())) | |
{ | |
void*& p = stream.pword(getSeparator()); | |
stream << *static_cast<std::string*>(p); | |
return 0; | |
} | |
return stream.rdbuf()->pubsync(); | |
} | |
private: | |
std::ostream& stream; | |
}; | |
void cleanup(std::ios_base::event evt, std::ios_base& str, int idx) | |
{ | |
if (str.iword(separatorEnabled()) && evt == std::ios_base::erase_event) | |
{ | |
void*& p = str.pword(idx); | |
delete static_cast<std::string*>(p); | |
str.iword(separatorEnabled()) = false; | |
} | |
} | |
std::ostream& set_separator(std::ostream& os, const custom::sep_impl& manip) | |
{ | |
if (!os.bad()) | |
{ | |
os.pword(getSeparator()) = new std::string(manip.separator); | |
os.register_callback(cleanup, getSeparator()); | |
} | |
return os; | |
} | |
std::ostream& operator<<(std::ostream& os, const custom::sep_impl& manip) | |
{ | |
std::ostream* p = os.tie(); | |
if (p && !p->iword(separatorEnabled()) | |
{ | |
set_separator(*p, manip); | |
p->iword(separatorEnabled()) = true; | |
} | |
return os << std::unitbuf; | |
} | |
namespace custom | |
{ | |
sep_impl::sep_impl(std::string const& _sep) : separator(_sep) { } | |
std::ostream& nosep(std::ostream& os) | |
{ | |
cleanup(std::ios_base::erase_event, *os.tie(), getSeparator()); | |
os.tie(nullptr); | |
return os << std::nounitbuf; | |
} | |
void install_separator(std::ostream& o1, std::ostream& o2) | |
{ | |
static custom_separator csep(o2); | |
o1.rdbuf(&csep); | |
o1.tie(&o2); | |
} | |
} | |
int main() | |
{ | |
std::ostream os(nullptr); | |
custom::install_separator(os, std::cout); | |
os << custom::sep(", ") << 4 << 2 << custom::nosep; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment