Skip to content

Commit

Permalink
Added custom boost::locale::numpunct
Browse files Browse the repository at this point in the history
  • Loading branch information
salvoilmiosi committed Jul 5, 2021
1 parent 5789ae2 commit ff22efc
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 36 deletions.
1 change: 1 addition & 0 deletions include/boost/locale.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,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
100 changes: 100 additions & 0 deletions include/boost/locale/numpunct.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//
// 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>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <locale>
#include <string>

namespace boost {
namespace locale {

template<typename CharType>
class BOOST_LOCALE_DECL 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_full() const {
return do_decimal_point_full();
}

string_type thousands_sep_full() const {
return do_thousands_sep_full();
}

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

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

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

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

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);
}
};

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/icu/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
#include "formatter.hpp"
#include <boost/locale/formatting.hpp>
#include <boost/locale/hold_ptr.hpp>
#include <boost/locale/numpunct.hpp>
#include "all_generator.hpp"
#include "cdata.hpp"
#include <algorithm>
#include "predefined_formatters.hpp"
#include "uconv.hpp"

namespace boost {
namespace locale {
Expand Down Expand Up @@ -354,6 +356,46 @@ class num_parse : public std::num_get<CharType>, protected num_base

};

template<typename CharType>
struct icu_numpunct : public numpunct<CharType> {
typedef std::basic_string<CharType> string_type;
public:
icu_numpunct(icu::Locale const &loc)
{
UErrorCode err = U_ZERO_ERROR;
icu::NumberFormat *fmt = icu::NumberFormat::createInstance(loc, UNUM_DECIMAL, err);
if (icu::DecimalFormat *dec = dynamic_cast<icu::DecimalFormat *>(fmt)) {
boost::locale::impl_icu::icu_std_converter<CharType> cnv("UTF-8");
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:
virtual string_type do_decimal_point_full() const {
return decimal_point_;
}
virtual string_type do_thousands_sep_full() const {
return thousands_sep_;
}
virtual std::string do_grouping() const {
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 @@ -362,6 +404,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.locale));
return tmp;
}

Expand Down
17 changes: 7 additions & 10 deletions src/posix/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <boost/locale/formatting.hpp>
#include <boost/locale/generator.hpp>
#include <boost/locale/encoding.hpp>
#include <boost/locale/numpunct.hpp>
#include <boost/shared_ptr.hpp>
#include <sstream>
#include <stdlib.h>
Expand Down Expand Up @@ -404,20 +405,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)
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 @@ -427,13 +424,13 @@ class num_punct_posix : public std::numpunct<CharType> {
{
s2=conv::to_utf<wchar_t>(s1,nl_langinfo_l(CODESET,lc));
}
virtual CharType do_decimal_point() const
virtual string_type do_decimal_point_full() const
{
return *decimal_point_.c_str();
return decimal_point_;
}
virtual CharType do_thousands_sep() const
virtual string_type do_thousands_sep_full() const
{
return *thousands_sep_.c_str();
return thousands_sep_;
}
virtual std::string do_grouping() const
{
Expand Down
37 changes: 11 additions & 26 deletions src/win32/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <boost/locale/formatting.hpp>
#include <boost/locale/generator.hpp>
#include <boost/locale/encoding.hpp>
#include <boost/locale/numpunct.hpp>
#include <boost/shared_ptr.hpp>
#include <sstream>
#include <stdlib.h>
Expand Down Expand Up @@ -119,11 +120,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)
numpunct<CharType>(refs)
{
numeric_info np = wcsnumformat_l(lc) ;
if(sizeof(CharType) == 1 && np.thousands_sep == L"\xA0")
Expand All @@ -132,10 +133,6 @@ class num_punct_win : public std::numpunct<CharType> {
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 @@ -147,28 +144,18 @@ class num_punct_win : public std::numpunct<CharType> {
{
s2=conv::from_utf(s1,"UTF-8");
}
virtual CharType do_decimal_point() const
virtual string_type do_decimal_point_full() const
{
return *decimal_point_.c_str();
return decimal_point_;
}
virtual CharType do_thousands_sep() const
virtual string_type do_thousands_sep_full() const
{
return *thousands_sep_.c_str();
return thousands_sep_;
}
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_;
Expand All @@ -179,7 +166,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 @@ -193,14 +180,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

0 comments on commit ff22efc

Please sign in to comment.