From ff22efca495458cf80be3a484dadd5b83883291e Mon Sep 17 00:00:00 2001 From: Salvo Miosi Date: Mon, 5 Jul 2021 20:15:19 +0200 Subject: [PATCH 1/3] Added custom boost::locale::numpunct --- include/boost/locale.hpp | 1 + include/boost/locale/numpunct.hpp | 100 ++++++++++++++++++++++++++++++ src/icu/numeric.cpp | 43 +++++++++++++ src/posix/numeric.cpp | 17 +++-- src/win32/numeric.cpp | 37 ++++------- 5 files changed, 162 insertions(+), 36 deletions(-) create mode 100644 include/boost/locale/numpunct.hpp diff --git a/include/boost/locale.hpp b/include/boost/locale.hpp index 989bba6c..0094827f 100644 --- a/include/boost/locale.hpp +++ b/include/boost/locale.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/include/boost/locale/numpunct.hpp b/include/boost/locale/numpunct.hpp new file mode 100644 index 00000000..076dba09 --- /dev/null +++ b/include/boost/locale/numpunct.hpp @@ -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 +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4275 4251 4231 4660) +#endif +#include +#include + +namespace boost { + namespace locale { + + template + class BOOST_LOCALE_DECL numpunct_base : public std::numpunct + { + typedef std::basic_string string_type; + public: + numpunct_base(size_t refs = 0) : std::numpunct(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 struct numpunct {}; + + template<> struct numpunct : numpunct_base { + numpunct (size_t refs = 0) : numpunct_base(refs) {} + }; + + template<> struct numpunct : numpunct_base { + numpunct (size_t refs = 0) : numpunct_base(refs) {} + }; + + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T + template<> struct numpunct : numpunct_base { + numpunct (size_t refs = 0) : numpunct_base(refs) {} + }; + #endif + #ifdef BOOST_LOCALE_ENABLE_CHAR32_T + template<> struct numpunct : numpunct_base { + numpunct (size_t refs = 0) : numpunct_base(refs) {} + }; + #endif + } +} + +#endif \ No newline at end of file diff --git a/src/icu/numeric.cpp b/src/icu/numeric.cpp index debecfb8..7316f176 100644 --- a/src/icu/numeric.cpp +++ b/src/icu/numeric.cpp @@ -13,10 +13,12 @@ #include "formatter.hpp" #include #include +#include #include "all_generator.hpp" #include "cdata.hpp" #include #include "predefined_formatters.hpp" +#include "uconv.hpp" namespace boost { namespace locale { @@ -354,6 +356,46 @@ class num_parse : public std::num_get, protected num_base }; +template +struct icu_numpunct : public numpunct { + typedef std::basic_string 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(fmt)) { + boost::locale::impl_icu::icu_std_converter 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(&grouping_size), 1); + int32_t grouping_size_2 = dec->getSecondaryGroupingSize(); + if (grouping_size_2 > 0 && grouping_size_2 != grouping_size) { + grouping_ += static_cast(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 std::locale install_formatting_facets(std::locale const &in,cdata const &cd) @@ -362,6 +404,7 @@ std::locale install_formatting_facets(std::locale const &in,cdata const &cd) if(!std::has_facet(in)) { tmp=std::locale(tmp,new icu_formatters_cache(cd.locale)); } + tmp=std::locale(tmp, new icu_numpunct(cd.locale)); return tmp; } diff --git a/src/posix/numeric.cpp b/src/posix/numeric.cpp index 2bef81e2..0735fdf7 100644 --- a/src/posix/numeric.cpp +++ b/src/posix/numeric.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -404,20 +405,16 @@ struct basic_numpunct { }; template -class num_punct_posix : public std::numpunct { +class num_punct_posix : public numpunct { public: typedef std::basic_string string_type; num_punct_posix(locale_t lc,size_t refs = 0) : - std::numpunct(refs) + numpunct(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*/) { @@ -427,13 +424,13 @@ class num_punct_posix : public std::numpunct { { s2=conv::to_utf(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 { diff --git a/src/win32/numeric.cpp b/src/win32/numeric.cpp index 00bc94fd..209715b9 100644 --- a/src/win32/numeric.cpp +++ b/src/win32/numeric.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -119,11 +120,11 @@ class time_put_win : public std::time_put { template -class num_punct_win : public std::numpunct { +class num_punct_win : public numpunct { public: typedef std::basic_string string_type; num_punct_win(winlocale const &lc,size_t refs = 0) : - std::numpunct(refs) + numpunct(refs) { numeric_info np = wcsnumformat_l(lc) ; if(sizeof(CharType) == 1 && np.thousands_sep == L"\xA0") @@ -132,10 +133,6 @@ class num_punct_win : public std::numpunct { 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) @@ -147,28 +144,18 @@ class num_punct_win : public std::numpunct { { 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_; @@ -179,7 +166,7 @@ template std::locale create_formatting_impl(std::locale const &in,winlocale const &lc) { if(lc.is_c()) { - std::locale tmp(in,new std::numpunct_byname("C")); + std::locale tmp(in, new numpunct()); tmp=std::locale(tmp,new std::time_put_byname("C")); tmp = std::locale(tmp,new num_format(lc)); return tmp; @@ -193,14 +180,12 @@ std::locale create_formatting_impl(std::locale const &in,winlocale const &lc) } template -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 *np = 0; if(lc.is_c()) - np = new std::numpunct_byname("C"); + tmp = std::locale(tmp, new numpunct()); else - np = new num_punct_win(lc); - std::locale tmp(in,np); + tmp = std::locale(tmp, new num_punct_win(lc)); tmp = std::locale(tmp,new util::base_num_parse()); return tmp; } From 856ebf291e00f30572b69e1d40d89a4a447ad022 Mon Sep 17 00:00:00 2001 From: Salvo Miosi Date: Fri, 23 Jul 2021 17:02:02 +0200 Subject: [PATCH 2/3] fix icu_numpunct constructor --- src/icu/numeric.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/icu/numeric.cpp b/src/icu/numeric.cpp index 7316f176..df08e4a0 100644 --- a/src/icu/numeric.cpp +++ b/src/icu/numeric.cpp @@ -360,12 +360,12 @@ template struct icu_numpunct : public numpunct { typedef std::basic_string string_type; public: - icu_numpunct(icu::Locale const &loc) + icu_numpunct(cdata const &d) { UErrorCode err = U_ZERO_ERROR; - icu::NumberFormat *fmt = icu::NumberFormat::createInstance(loc, UNUM_DECIMAL, err); + icu::NumberFormat *fmt = icu::NumberFormat::createInstance(d.locale, UNUM_DECIMAL, err); if (icu::DecimalFormat *dec = dynamic_cast(fmt)) { - boost::locale::impl_icu::icu_std_converter cnv("UTF-8"); + boost::locale::impl_icu::icu_std_converter 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)); @@ -404,7 +404,7 @@ std::locale install_formatting_facets(std::locale const &in,cdata const &cd) if(!std::has_facet(in)) { tmp=std::locale(tmp,new icu_formatters_cache(cd.locale)); } - tmp=std::locale(tmp, new icu_numpunct(cd.locale)); + tmp=std::locale(tmp, new icu_numpunct(cd)); return tmp; } From 6d6942cef1fb9cd3b9f1eee65561178df86ff5b7 Mon Sep 17 00:00:00 2001 From: Salvo Miosi Date: Sun, 31 Jul 2022 21:14:29 +0200 Subject: [PATCH 3/3] fixes --- include/boost/locale/numpunct.hpp | 16 ++++++---------- src/boost/locale/icu/numeric.cpp | 6 +++--- src/boost/locale/posix/numeric.cpp | 14 ++------------ src/boost/locale/win32/numeric.cpp | 4 ++-- 4 files changed, 13 insertions(+), 27 deletions(-) diff --git a/include/boost/locale/numpunct.hpp b/include/boost/locale/numpunct.hpp index 7921f831..268def5a 100644 --- a/include/boost/locale/numpunct.hpp +++ b/include/boost/locale/numpunct.hpp @@ -9,10 +9,6 @@ #ifndef BOOST_LOCALE_NUMPUNCT_HPP_INCLUDED #define BOOST_LOCALE_NUMPUNCT_HPP_INCLUDED #include -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable : 4275 4251 4231 4660) -#endif #include #include @@ -20,7 +16,7 @@ namespace boost { namespace locale { template - class BOOST_LOCALE_DECL numpunct_base : public std::numpunct + class numpunct_base : public std::numpunct { typedef std::basic_string string_type; public: @@ -35,7 +31,7 @@ namespace boost { } protected: - virtual CharType do_decimal_point() const { + CharType do_decimal_point() const BOOST_OVERRIDE { string_type dec = do_decimal_point_str(); if (dec.size() > 1) { return '.'; @@ -49,7 +45,7 @@ namespace boost { return string_type(t, t + sizeof(t) - 1); } - virtual CharType do_thousands_sep() const { + CharType do_thousands_sep() const BOOST_OVERRIDE { string_type thous = do_thousands_sep_str(); if (thous.size() > 1) { return ','; @@ -63,18 +59,18 @@ namespace boost { return string_type(t, t + sizeof(t) - 1); } - virtual string_type do_truename() const { + 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 { + virtual string_type do_falsename() const BOOST_OVERRIDE { static const char t[] = "false"; return string_type(t, t + sizeof(t) - 1); } }; - template struct numpunct {}; + template struct numpunct; template<> struct numpunct : numpunct_base { numpunct (size_t refs = 0) : numpunct_base(refs) {} diff --git a/src/boost/locale/icu/numeric.cpp b/src/boost/locale/icu/numeric.cpp index 4ab7919d..5f5c5ada 100644 --- a/src/boost/locale/icu/numeric.cpp +++ b/src/boost/locale/icu/numeric.cpp @@ -381,13 +381,13 @@ struct icu_numpunct : public numpunct { } } protected: - virtual string_type do_decimal_point_str() const { + string_type do_decimal_point_str() const BOOST_OVERRIDE { return decimal_point_; } - virtual string_type do_thousands_sep_str() const { + string_type do_thousands_sep_str() const BOOST_OVERRIDE { return thousands_sep_; } - virtual std::string do_grouping() const { + std::string do_grouping() const BOOST_OVERRIDE { return grouping_; } diff --git a/src/boost/locale/posix/numeric.cpp b/src/boost/locale/posix/numeric.cpp index a205df7a..510ffbcd 100644 --- a/src/boost/locale/posix/numeric.cpp +++ b/src/boost/locale/posix/numeric.cpp @@ -423,11 +423,11 @@ class num_punct_posix : public numpunct { { s2=conv::to_utf(s1,nl_langinfo_l(CODESET,lc)); } - virtual string_type do_decimal_point_str() const + string_type do_decimal_point_str() const BOOST_OVERRIDE { return decimal_point_; } - virtual string_type do_thousands_sep_str() const + string_type do_thousands_sep_str() const BOOST_OVERRIDE { return thousands_sep_; } @@ -435,16 +435,6 @@ class num_punct_posix : public numpunct { { return grouping_; } - string_type do_truename() const BOOST_OVERRIDE - { - static const char t[]="true"; - return string_type(t,t+sizeof(t)-1); - } - string_type do_falsename() const BOOST_OVERRIDE - { - static const char t[]="false"; - return string_type(t,t+sizeof(t)-1); - } private: string_type decimal_point_; string_type thousands_sep_; diff --git a/src/boost/locale/win32/numeric.cpp b/src/boost/locale/win32/numeric.cpp index 6789d13c..309f67ab 100644 --- a/src/boost/locale/win32/numeric.cpp +++ b/src/boost/locale/win32/numeric.cpp @@ -141,11 +141,11 @@ BOOST_LOCALE_END_CONST_CONDITION { s2=conv::from_utf(s1,"UTF-8"); } - virtual string_type do_decimal_point_str() const + string_type do_decimal_point_str() const BOOST_OVERRIDE { return decimal_point_; } - virtual string_type do_thousands_sep_str() const + string_type do_thousands_sep_str() const BOOST_OVERRIDE { return thousands_sep_; }