blob: 00bc94fd6d69fea66e4bacb01b922aa104057a7b [file] [log] [blame]
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#define BOOST_LOCALE_SOURCE
#include <locale>
#include <string>
#include <ios>
#include <boost/locale/formatting.hpp>
#include <boost/locale/generator.hpp>
#include <boost/locale/encoding.hpp>
#include <boost/shared_ptr.hpp>
#include <sstream>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <wctype.h>
#include <ctype.h>
#include "all_generator.hpp"
#include "api.hpp"
#include "../util/numeric.hpp"
namespace boost {
namespace locale {
namespace impl_win {
namespace {
std::ostreambuf_iterator<wchar_t> write_it(std::ostreambuf_iterator<wchar_t> out,std::wstring const &s)
{
for(size_t i=0;i<s.size();i++)
*out++ = s[i];
return out;
}
std::ostreambuf_iterator<char> write_it(std::ostreambuf_iterator<char> out,std::wstring const &s)
{
std::string tmp = conv::from_utf(s,"UTF-8");
for(size_t i=0;i<tmp.size();i++)
*out++ = tmp[i];
return out;
}
}
template<typename CharType>
class num_format : public util::base_num_format<CharType>
{
public:
typedef typename std::num_put<CharType>::iter_type iter_type;
typedef std::basic_string<CharType> string_type;
typedef CharType char_type;
num_format(winlocale const &lc,size_t refs = 0) :
util::base_num_format<CharType>(refs),
lc_(lc)
{
}
private:
virtual
iter_type do_format_currency(bool /*intl*/,iter_type out,std::ios_base &ios,char_type fill,long double val) const
{
if(lc_.is_c()) {
std::locale loc = ios.getloc();
int digits = std::use_facet<std::moneypunct<char_type> >(loc).frac_digits();
while(digits > 0) {
val*=10;
digits --;
}
std::ios_base::fmtflags f=ios.flags();
ios.flags(f | std::ios_base::showbase);
out = std::use_facet<std::money_put<char_type> >(loc).put(out,false,ios,fill,val);
ios.flags(f);
return out;
}
else {
std::wstring cur = wcsfmon_l(val,lc_);
return write_it(out,cur);
}
}
private:
winlocale lc_;
}; /// num_format
template<typename CharType>
class time_put_win : public std::time_put<CharType> {
public:
time_put_win(winlocale const &lc, size_t refs = 0) :
std::time_put<CharType>(refs),
lc_(lc)
{
}
virtual ~time_put_win()
{
}
typedef typename std::time_put<CharType>::iter_type iter_type;
typedef CharType char_type;
typedef std::basic_string<char_type> string_type;
virtual iter_type do_put( iter_type out,
std::ios_base &/*ios*/,
CharType /*fill*/,
std::tm const *tm,
char format,
char /*modifier*/) const
{
return write_it(out,wcsftime_l(format,tm,lc_));
}
private:
winlocale lc_;
};
template<typename CharType>
class num_punct_win : public std::numpunct<CharType> {
public:
typedef std::basic_string<CharType> string_type;
num_punct_win(winlocale const &lc,size_t refs = 0) :
std::numpunct<CharType>(refs)
{
numeric_info np = wcsnumformat_l(lc) ;
if(sizeof(CharType) == 1 && np.thousands_sep == L"\xA0")
np.thousands_sep=L" ";
to_str(np.thousands_sep,thousands_sep_);
to_str(np.decimal_point,decimal_point_);
grouping_ = np.grouping;
if(thousands_sep_.size() > 1)
grouping_ = std::string();
if(decimal_point_.size() > 1)
decimal_point_ = CharType('.');
}
void to_str(std::wstring &s1,std::wstring &s2)
{
s2.swap(s1);
}
void to_str(std::wstring &s1,std::string &s2)
{
s2=conv::from_utf(s1,"UTF-8");
}
virtual CharType do_decimal_point() const
{
return *decimal_point_.c_str();
}
virtual CharType do_thousands_sep() const
{
return *thousands_sep_.c_str();
}
virtual std::string do_grouping() const
{
return grouping_;
}
virtual string_type do_truename() const
{
static const char t[]="true";
return string_type(t,t+sizeof(t)-1);
}
virtual string_type do_falsename() const
{
static const char t[]="false";
return string_type(t,t+sizeof(t)-1);
}
private:
string_type decimal_point_;
string_type thousands_sep_;
std::string grouping_;
};
template<typename CharType>
std::locale create_formatting_impl(std::locale const &in,winlocale const &lc)
{
if(lc.is_c()) {
std::locale tmp(in,new std::numpunct_byname<CharType>("C"));
tmp=std::locale(tmp,new std::time_put_byname<CharType>("C"));
tmp = std::locale(tmp,new num_format<CharType>(lc));
return tmp;
}
else {
std::locale tmp(in,new num_punct_win<CharType>(lc));
tmp = std::locale(tmp,new time_put_win<CharType>(lc));
tmp = std::locale(tmp,new num_format<CharType>(lc));
return tmp;
}
}
template<typename CharType>
std::locale create_parsing_impl(std::locale const &in,winlocale const &lc)
{
std::numpunct<CharType> *np = 0;
if(lc.is_c())
np = new std::numpunct_byname<CharType>("C");
else
np = new num_punct_win<CharType>(lc);
std::locale tmp(in,np);
tmp = std::locale(tmp,new util::base_num_parse<CharType>());
return tmp;
}
std::locale create_formatting( std::locale const &in,
winlocale const &lc,
character_facet_type type)
{
switch(type) {
case char_facet:
return create_formatting_impl<char>(in,lc);
case wchar_t_facet:
return create_formatting_impl<wchar_t>(in,lc);
default:
return in;
}
}
std::locale create_parsing( std::locale const &in,
winlocale const &lc,
character_facet_type type)
{
switch(type) {
case char_facet:
return create_parsing_impl<char>(in,lc);
case wchar_t_facet:
return create_parsing_impl<wchar_t>(in,lc);
default:
return in;
}
}
} // impl_std
} // locale
} //boost
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4