Skip to content

Instantly share code, notes, and snippets.

@dgodfrey206
Created November 2, 2013 22:07
Show Gist options
  • Save dgodfrey206/7284036 to your computer and use it in GitHub Desktop.
Save dgodfrey206/7284036 to your computer and use it in GitHub Desktop.
My implementation of a manipulator that saves a locale name to the stream. Still needs work.
#include <iostream>
#include <string>
#include <locale>
#include <vector>
static int index()
{
static int idx = std::ios_base::xalloc();
return idx;
}
template <class CharT>
static void cache(std::ios_base& os, const CharT* arg)
{
void*& p = os.pword(index());
std::basic_string<CharT>* oldLocaleName
= static_cast<std::basic_string<CharT>*>(p);
std::basic_string<CharT>* newLocaleName = new std::basic_string<CharT>(arg);
delete oldLocaleName;
p = newLocaleName;
}
template <class CharT>
std::basic_string<CharT> defaultLocaleName(std::ios_base& os)
{
char base[11] = "en_US.UTF8";
CharT* ptr = new CharT[11];
std::use_facet<std::ctype<CharT>>(os.getloc())
.widen(&base[0], base + 11, &ptr[0]);
return ptr;
}
template <class CharT>
static void cache(std::ios_base& os)
{
void*& p = os.pword(index());
std::basic_string<CharT>* newLocaleName;
newLocaleName = new std::basic_string<CharT>(defaultLocaleName<CharT>(os));
p = newLocaleName;
}
class my_locale { };
template <class Argument>
class manipulator
{
public:
typedef void (*function)(std::ios_base&, Argument);
manipulator(function f, const Argument& arg)
: arg(arg), f(f)
{ }
void call(std::ios_base& str, const Argument& arg) const
{
f(str, arg);
}
Argument arg;
private:
function f;
};
template <class CharT>
class localename_helper : public manipulator<const CharT*>
{
public:
localename_helper(const CharT* str)
: manipulator<const CharT*>(cache, str) { }
};
template <class Argument>
void do_manip(std::ios_base& str, manipulator<Argument> const& m)
{
m.call(str, m.arg);
}
template <class CharT, class Traits, class Argument>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, manipulator<Argument> const& m)
{
if (os.good())
do_manip(os, m);
return os;
}
template <class CharT>
localename_helper<CharT> localename(const CharT* str)
{
return localename_helper<CharT>(str);
}
template <class CharT, class Traits>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os, my_locale const&)
{
if (!os.pword(index()))
cache<CharT>(os);
return os << *static_cast<std::basic_string<CharT>*>(os.pword(index())) << std::endl;
}
int main()
{
my_locale ml;
std::cout << ml << ml << localename("ru_RU.UTF8") << ml;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment