diff --git a/include/boost/locale.hpp b/include/boost/locale.hpp index 1840bf51..b56f39a0 100644 --- a/include/boost/locale.hpp +++ b/include/boost/locale.hpp @@ -15,6 +15,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..268def5a --- /dev/null +++ b/include/boost/locale/numpunct.hpp @@ -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 +#include +#include + +namespace boost { + namespace locale { + + template + class 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_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 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/boost/locale/icu/numeric.cpp b/src/boost/locale/icu/numeric.cpp index e8d11ac1..3716173e 100644 --- a/src/boost/locale/icu/numeric.cpp +++ b/src/boost/locale/icu/numeric.cpp @@ -7,10 +7,12 @@ #define BOOST_LOCALE_SOURCE #include #include +#include #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 #include #include @@ -345,6 +347,46 @@ BOOST_LOCALE_END_CONST_CONDITION }; +template +struct icu_numpunct : public numpunct { + typedef std::basic_string 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(fmt)) { + 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)); + 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: + 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 std::locale install_formatting_facets(std::locale const &in,cdata const &cd) @@ -353,6 +395,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)); return tmp; } diff --git a/src/boost/locale/posix/numeric.cpp b/src/boost/locale/posix/numeric.cpp index 868d9f91..b8f78cb1 100644 --- a/src/boost/locale/posix/numeric.cpp +++ b/src/boost/locale/posix/numeric.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -394,20 +395,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) + num_punct_posix(locale_t lc,size_t refs = 0) : + 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*/) { @@ -417,28 +414,18 @@ class num_punct_posix : public std::numpunct { { s2=conv::to_utf(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_; diff --git a/src/boost/locale/win32/numeric.cpp b/src/boost/locale/win32/numeric.cpp index c6c73e53..4c4c6c58 100644 --- a/src/boost/locale/win32/numeric.cpp +++ b/src/boost/locale/win32/numeric.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -105,11 +106,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) + num_punct_win(winlocale const &lc,size_t refs = 0) : + numpunct(refs) { numeric_info np = wcsnumformat_l(lc) ; @@ -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) @@ -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_; @@ -168,7 +155,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; @@ -182,14 +169,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; }