From 77d1e5c3dd2847cde4e7d9c8b99ec1033b46a929 Mon Sep 17 00:00:00 2001 From: Salvo Miosi Date: Sun, 4 Jul 2021 15:48:37 +0200 Subject: [PATCH] Adds custom boost::locale::numpunct --- include/boost/locale.hpp | 1 + include/boost/locale/numpunct.hpp | 77 +++++++++++++++++++++++++++++++ src/icu/numeric.cpp | 30 ++++++++++++ src/posix/numeric.cpp | 13 ++---- src/shared/ids.cpp | 6 +++ src/win32/numeric.cpp | 34 ++++---------- test_numpunct.cpp | 14 ++++++ 7 files changed, 143 insertions(+), 32 deletions(-) create mode 100644 include/boost/locale/numpunct.hpp create mode 100644 test_numpunct.cpp 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..cd154c71 --- /dev/null +++ b/include/boost/locale/numpunct.hpp @@ -0,0 +1,77 @@ +// +// 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 numpunct; + + template + class BOOST_LOCALE_DECL numpunct : public std::locale::facet + { + typedef std::basic_string string_type; + public: + static inline std::locale::id id; + + numpunct (size_t refs = 0) : std::locale::facet(refs) {} + + string_type decimal_point() const { + return do_decimal_point(); + } + + string_type thousands_sep() const { + return do_thousands_sep(); + } + + string_type grouping() const { + return do_grouping(); + } + + string_type truename() const { + return do_truename(); + } + + string_type falsename() const { + return do_falsename(); + } + + protected: + virtual string_type do_decimal_point() const { + static const char t[] = "."; + return string_type(t, t + sizeof(t) - 1); + } + virtual string_type do_thousands_sep() const { + static const char t[] = ","; + return string_type(t, t + sizeof(t) - 1); + } + virtual std::string do_grouping() const { + return ""; + } + 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); + } + }; + } +} + +#endif \ No newline at end of file diff --git a/src/icu/numeric.cpp b/src/icu/numeric.cpp index debecfb8..e47cd1a6 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,33 @@ 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) + { + boost::locale::impl_icu::icu_std_converter cnv("UTF-8"); + UErrorCode err; + icu::DecimalFormatSymbols syms(loc, err); + decimal_point_ = cnv.std(syms.getSymbol(icu::DecimalFormatSymbols::kDecimalSeparatorSymbol)); + thousands_sep_ = cnv.std(syms.getSymbol(icu::DecimalFormatSymbols::kGroupingSeparatorSymbol)); + } +protected: + virtual string_type do_decimal_point() const + { + return decimal_point_; + } + virtual string_type do_thousands_sep() const + { + return thousands_sep_; + } + +private: + string_type decimal_point_; + string_type thousands_sep_; +}; + template std::locale install_formatting_facets(std::locale const &in,cdata const &cd) @@ -362,6 +391,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..25eadc26 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*/) { @@ -429,11 +426,11 @@ class num_punct_posix : public std::numpunct { } virtual CharType do_decimal_point() const { - return *decimal_point_.c_str(); + return decimal_point_; } virtual CharType do_thousands_sep() const { - return *thousands_sep_.c_str(); + return thousands_sep_; } virtual std::string do_grouping() const { diff --git a/src/shared/ids.cpp b/src/shared/ids.cpp index 952fa85a..2821c07a 100644 --- a/src/shared/ids.cpp +++ b/src/shared/ids.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace boost { namespace locale { @@ -25,10 +26,14 @@ namespace boost { std::locale::id converter::id; std::locale::id base_message_format::id; + // std::locale::id numpunct::id; + // std::locale::id numpunct::id; + #ifdef BOOST_LOCALE_ENABLE_CHAR16_T std::locale::id converter::id; std::locale::id base_message_format::id; + // std::locale::id numpunct::id; #endif @@ -36,6 +41,7 @@ namespace boost { std::locale::id converter::id; std::locale::id base_message_format::id; + // std::locale::id numpunct::id; #endif diff --git a/src/win32/numeric.cpp b/src/win32/numeric.cpp index 00bc94fd..c5cd5c51 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() const { - return *decimal_point_.c_str(); + return decimal_point_; } - virtual CharType do_thousands_sep() const + virtual string_type do_thousands_sep() 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_; @@ -195,12 +182,11 @@ 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::numpunct *np = 0; + std::locale tmp(in); if(lc.is_c()) - np = new std::numpunct_byname("C"); + tmp = std::locale(tmp, new std::numpunct_byname("C")); 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; } diff --git a/test_numpunct.cpp b/test_numpunct.cpp new file mode 100644 index 00000000..03eb5c9b --- /dev/null +++ b/test_numpunct.cpp @@ -0,0 +1,14 @@ +#include +#include "boost/locale.hpp" + +int main(int argc, char **argv) { + const char *lang = ""; + if (argc > 1) { + lang = argv[1]; + } + boost::locale::generator gen; + std::locale loc = gen(lang); + + auto &facet = std::use_facet>(loc); + std::cout << facet.decimal_point() << ' ' << facet.thousands_sep() << '\n'; +} \ No newline at end of file