Last active
December 28, 2015 19:49
-
-
Save dgodfrey206/7553400 to your computer and use it in GitHub Desktop.
My try at the address_put facet from the book Standard C++ IOStreams and Locales
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 <string> | |
#include <locale> | |
#include <typeinfo> | |
#include <map> | |
template<class charT> | |
class address | |
{ | |
template<class CharT> | |
friend std::basic_ostream<CharT>& | |
operator<<(std::basic_ostream<CharT>&, const address<CharT>&); | |
template<class CharT> | |
friend std::basic_istream<CharT> | |
operator>>(std::basic_istream<CharT>&, address<CharT>&); | |
typedef std::basic_string<charT> string; | |
public: | |
address(string _name, string _address) | |
: name(_name), street_address(_address) | |
{ } | |
private: | |
string name, street_address; | |
}; | |
template<class charT, class Iter = std::ostreambuf_iterator<charT>> | |
class address_put : public std::locale::facet | |
{ | |
typedef std::basic_string<charT> string; | |
public: | |
explicit address_put(std::size_t refs = 0) : std::locale::facet(refs) | |
{ } | |
static std::locale::id id; | |
typedef Iter iter_type; | |
virtual void put(iter_type it, const string& name, | |
const string& street) const = 0; | |
protected: | |
virtual void do_put(iter_type it, const string& name, | |
const string& street) const = 0; | |
void put_address(iter_type it, const string& fullAddress) const | |
{ | |
for (auto c : fullAddress) | |
*it = c; | |
} | |
}; | |
template<class charT, class Iter> | |
std::locale::id address_put<charT, Iter>::id; | |
template<class charT, class Iter = std::ostreambuf_iterator<charT>> | |
class US_address_put : public address_put<charT, Iter> | |
{ | |
using address_put<charT, Iter>::put_address; | |
typedef std::basic_string<charT> string; | |
public: | |
US_address_put(std::size_t refs = 0) | |
: address_put<charT, Iter>(refs) | |
{ } | |
void put(Iter it, const string& name, | |
const string& street) const | |
{ do_put(it, name, street); } | |
protected: | |
void do_put(Iter it, const string& name, | |
const string& street) const | |
{ put_address(it, street + ", " + name); } | |
}; | |
template<class charT> | |
std::basic_ostream<charT>& operator<<(std::basic_ostream<charT>& os, | |
const address<charT>& ad) | |
{ | |
if (!os.good()) | |
return os; | |
std::locale loc = os.getloc(); | |
try | |
{ | |
auto& f = std::use_facet<address_put<char>>(loc); | |
f.put(os, ad.name, ad.street_address); | |
} catch (const std::bad_cast&) | |
{ | |
std::cerr << "Output stream has no locale address_put<char>."; | |
} | |
return os; | |
} | |
class locale_factory | |
{ | |
protected: | |
virtual std::locale make_locale(const std::string& localeName) | |
{ | |
return std::locale(localeName.c_str()); | |
} | |
}; | |
class address_locale_factory : public locale_factory | |
{ | |
private: | |
typedef std::ostreambuf_iterator<char> iter_type; | |
public: | |
address_locale_factory() | |
{ | |
facets["en_US.UTF8"] = new US_address_put<char, iter_type>(1); | |
facets["C"] = new US_address_put<char, iter_type>(1); | |
} | |
~address_locale_factory() | |
{ | |
delete facets["en_US.UTF8"]; | |
delete facets["C"]; | |
} | |
std::locale make_locale(const std::string& localeName) | |
{ | |
if (facets.find(localeName) == facets.end()) | |
return locale_factory::make_locale(localeName); | |
else | |
return std::locale(std::locale(localeName.c_str()), | |
(*facets.find(localeName)).second); | |
} | |
private: | |
std::map<std::string, address_put<char, iter_type>*> facets; | |
}; | |
void putAddress(std::ostream& os, const address<char>& ad, std::locale loc) | |
{ | |
std::locale oldLocale = os.imbue(loc); | |
os << ad; | |
os.imbue(oldLocale); | |
} | |
int main() | |
{ | |
std::locale localeWithAddressFacet | |
= std::locale(std::cout.getloc(), new US_address_put<char>); | |
std::cout.imbue(localeWithAddressFacet); | |
address<char> ad("David", "4120 Hutchinson Rv Pkwy"); | |
putAddress(std::cout, ad, address_locale_factory().make_locale("en_US.UTF8")); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment