Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds custom boost::locale::numpunct #65

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/boost/locale.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <boost/locale/encoding.hpp>
#include <boost/locale/format.hpp>
#include <boost/locale/formatting.hpp>
#include <boost/locale/numpunct.hpp>
#include <boost/locale/generator.hpp>
#include <boost/locale/gnu_gettext.hpp>
#include <boost/locale/info.hpp>
Expand Down
96 changes: 96 additions & 0 deletions include/boost/locale/numpunct.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//
// Copyright (c) 2021-2021 Salvo Miosi
//
// 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)
//

#ifndef BOOST_LOCALE_NUMPUNCT_HPP_INCLUDED
#define BOOST_LOCALE_NUMPUNCT_HPP_INCLUDED
#include <boost/locale/config.hpp>
#include <locale>
#include <string>

namespace boost {
namespace locale {

template<typename CharType>
class numpunct_base : public std::numpunct<CharType>
{
typedef std::basic_string<CharType> string_type;
public:
numpunct_base(size_t refs = 0) : std::numpunct<CharType>(refs) {}

string_type decimal_point_str() const {
return do_decimal_point_str();
}

string_type thousands_sep_str() const {
return do_thousands_sep_str();
}

protected:
CharType do_decimal_point() const BOOST_OVERRIDE {
string_type dec = do_decimal_point_str();
if (dec.size() > 1) {
return '.';
} else {
return dec[0];
}
}

virtual string_type do_decimal_point_str() const {
static const char t[] = ".";
return string_type(t, t + sizeof(t) - 1);
}

CharType do_thousands_sep() const BOOST_OVERRIDE {
string_type thous = do_thousands_sep_str();
if (thous.size() > 1) {
return ',';
} else {
return thous[0];
}
}

virtual string_type do_thousands_sep_str() const {
static const char t[] = ",";
return string_type(t, t + sizeof(t) - 1);
}

virtual string_type do_truename() const BOOST_OVERRIDE {
static const char t[] = "true";
return string_type(t, t + sizeof(t) - 1);
}

virtual string_type do_falsename() const BOOST_OVERRIDE {
static const char t[] = "false";
return string_type(t, t + sizeof(t) - 1);
}
};

template<typename CharType> struct numpunct;

template<> struct numpunct<char> : numpunct_base<char> {
numpunct (size_t refs = 0) : numpunct_base<char>(refs) {}
};

template<> struct numpunct<wchar_t> : numpunct_base<wchar_t> {
numpunct (size_t refs = 0) : numpunct_base<wchar_t>(refs) {}
};

#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
template<> struct numpunct<char16_t> : numpunct_base<char16_t> {
numpunct (size_t refs = 0) : numpunct_base<char16_t>(refs) {}
};
#endif
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
template<> struct numpunct<char32_t> : numpunct_base<char32_t> {
numpunct (size_t refs = 0) : numpunct_base<char32_t>(refs) {}
};
#endif
}
}

#endif
43 changes: 43 additions & 0 deletions src/boost/locale/icu/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
#define BOOST_LOCALE_SOURCE
#include <boost/locale/formatting.hpp>
#include <boost/locale/hold_ptr.hpp>
#include <boost/locale/numpunct.hpp>
#include "boost/locale/icu/all_generator.hpp"
#include "boost/locale/icu/cdata.hpp"
#include "boost/locale/icu/formatter.hpp"
#include "boost/locale/icu/predefined_formatters.hpp"
#include "uconv.hpp"
#include <algorithm>
#include <ios>
#include <limits>
Expand Down Expand Up @@ -345,6 +347,46 @@ BOOST_LOCALE_END_CONST_CONDITION

};

template<typename CharType>
struct icu_numpunct : public numpunct<CharType> {
typedef std::basic_string<CharType> string_type;
public:
icu_numpunct(cdata const &d)
{
UErrorCode err = U_ZERO_ERROR;
icu::NumberFormat *fmt = icu::NumberFormat::createInstance(d.locale, UNUM_DECIMAL, err);
if (icu::DecimalFormat *dec = dynamic_cast<icu::DecimalFormat *>(fmt)) {
boost::locale::impl_icu::icu_std_converter<CharType> cnv(d.encoding);
const icu::DecimalFormatSymbols *syms = dec->getDecimalFormatSymbols();
decimal_point_ = cnv.std(syms->getSymbol(icu::DecimalFormatSymbols::kDecimalSeparatorSymbol));
thousands_sep_ = cnv.std(syms->getSymbol(icu::DecimalFormatSymbols::kGroupingSeparatorSymbol));
if (dec->isGroupingUsed()) {
int32_t grouping_size = dec->getGroupingSize();
grouping_ = std::string(reinterpret_cast<char*>(&grouping_size), 1);
int32_t grouping_size_2 = dec->getSecondaryGroupingSize();
if (grouping_size_2 > 0 && grouping_size_2 != grouping_size) {
grouping_ += static_cast<char>(grouping_size_2);
}
}
}
}
protected:
string_type do_decimal_point_str() const BOOST_OVERRIDE {
return decimal_point_;
}
string_type do_thousands_sep_str() const BOOST_OVERRIDE {
return thousands_sep_;
}
std::string do_grouping() const BOOST_OVERRIDE {
return grouping_;
}

private:
string_type decimal_point_;
string_type thousands_sep_;
std::string grouping_;
};


template<typename CharType>
std::locale install_formatting_facets(std::locale const &in,cdata const &cd)
Expand All @@ -353,6 +395,7 @@ std::locale install_formatting_facets(std::locale const &in,cdata const &cd)
if(!std::has_facet<icu_formatters_cache>(in)) {
tmp=std::locale(tmp,new icu_formatters_cache(cd.locale));
}
tmp=std::locale(tmp, new icu_numpunct<CharType>(cd));
return tmp;
}

Expand Down
29 changes: 8 additions & 21 deletions src/boost/locale/posix/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <boost/locale/encoding.hpp>
#include <boost/locale/formatting.hpp>
#include <boost/locale/generator.hpp>
#include <boost/locale/numpunct.hpp>
#include <boost/predef/os.h>
#include <cctype>
#include <cerrno>
Expand Down Expand Up @@ -394,20 +395,16 @@ struct basic_numpunct {
};

template<typename CharType>
class num_punct_posix : public std::numpunct<CharType> {
class num_punct_posix : public numpunct<CharType> {
public:
typedef std::basic_string<CharType> string_type;
num_punct_posix(locale_t lc,size_t refs = 0):
std::numpunct<CharType>(refs)
num_punct_posix(locale_t lc,size_t refs = 0) :
numpunct<CharType>(refs)
{
basic_numpunct np(lc);
to_str(np.thousands_sep,thousands_sep_,lc);
to_str(np.decimal_point,decimal_point_,lc);
grouping_ = np.grouping;
if(thousands_sep_.size() > 1)
grouping_ = std::string();
if(decimal_point_.size() > 1)
decimal_point_ = CharType('.');
}
void to_str(std::string &s1,std::string &s2,locale_t /*lc*/)
{
Expand All @@ -417,28 +414,18 @@ class num_punct_posix : public std::numpunct<CharType> {
{
s2=conv::to_utf<wchar_t>(s1,nl_langinfo_l(CODESET,lc));
}
CharType do_decimal_point() const override
string_type do_decimal_point_str() const override
{
return *decimal_point_.c_str();
return decimal_point_;
}
CharType do_thousands_sep() const override
string_type do_thousands_sep_str() const override
{
return *thousands_sep_.c_str();
return thousands_sep_;
}
std::string do_grouping() const override
{
return grouping_;
}
string_type do_truename() const override
{
static const char t[]="true";
return string_type(t,t+sizeof(t)-1);
}
string_type do_falsename() const override
{
static const char t[]="false";
return string_type(t,t+sizeof(t)-1);
}
private:
string_type decimal_point_;
string_type thousands_sep_;
Expand Down
39 changes: 12 additions & 27 deletions src/boost/locale/win32/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <boost/locale/encoding.hpp>
#include <boost/locale/formatting.hpp>
#include <boost/locale/generator.hpp>
#include <boost/locale/numpunct.hpp>
#include <cctype>
#include <cstdlib>
#include <cstring>
Expand Down Expand Up @@ -105,11 +106,11 @@ class time_put_win : public std::time_put<CharType> {


template<typename CharType>
class num_punct_win : public std::numpunct<CharType> {
class num_punct_win : public numpunct<CharType> {
public:
typedef std::basic_string<CharType> string_type;
num_punct_win(winlocale const &lc,size_t refs = 0):
std::numpunct<CharType>(refs)
num_punct_win(winlocale const &lc,size_t refs = 0) :
numpunct<CharType>(refs)
{
numeric_info np = wcsnumformat_l(lc) ;

Expand All @@ -121,10 +122,6 @@ BOOST_LOCALE_END_CONST_CONDITION
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)
Expand All @@ -136,28 +133,18 @@ BOOST_LOCALE_END_CONST_CONDITION
{
s2=conv::from_utf(s1,"UTF-8");
}
CharType do_decimal_point() const override
string_type do_decimal_point_str() const BOOST_OVERRIDE
{
return *decimal_point_.c_str();
return decimal_point_;
}
CharType do_thousands_sep() const override
string_type do_thousands_sep_str() const BOOST_OVERRIDE
{
return *thousands_sep_.c_str();
return thousands_sep_;
}
std::string do_grouping() const override
{
return grouping_;
}
string_type do_truename() const override
{
static const char t[]="true";
return string_type(t,t+sizeof(t)-1);
}
string_type do_falsename() const override
{
static const char t[]="false";
return string_type(t,t+sizeof(t)-1);
}
private:
string_type decimal_point_;
string_type thousands_sep_;
Expand All @@ -168,7 +155,7 @@ 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"));
std::locale tmp(in, new numpunct<CharType>());
tmp=std::locale(tmp,new std::time_put_byname<CharType>("C"));
tmp = std::locale(tmp,new num_format<CharType>(lc));
return tmp;
Expand All @@ -182,14 +169,12 @@ std::locale create_formatting_impl(std::locale const &in,winlocale const &lc)
}

template<typename CharType>
std::locale create_parsing_impl(std::locale const &in,winlocale const &lc)
std::locale create_parsing_impl(std::locale tmp,winlocale const &lc)
{
std::numpunct<CharType> *np = 0;
if(lc.is_c())
np = new std::numpunct_byname<CharType>("C");
tmp = std::locale(tmp, new numpunct<CharType>());
else
np = new num_punct_win<CharType>(lc);
std::locale tmp(in,np);
tmp = std::locale(tmp, new num_punct_win<CharType>(lc));
tmp = std::locale(tmp,new util::base_num_parse<CharType>());
return tmp;
}
Expand Down