Skip to content

Commit 3672482

Browse files
committed
Adds custom boost::locale::numpunct
1 parent 5789ae2 commit 3672482

File tree

6 files changed

+164
-33
lines changed

6 files changed

+164
-33
lines changed

include/boost/locale.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <boost/locale/encoding.hpp>
1717
#include <boost/locale/format.hpp>
1818
#include <boost/locale/formatting.hpp>
19+
#include <boost/locale/numpunct.hpp>
1920
#include <boost/locale/generator.hpp>
2021
#include <boost/locale/gnu_gettext.hpp>
2122
#include <boost/locale/info.hpp>

include/boost/locale/numpunct.hpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//
2+
// Copyright (c) 2021-2021 Salvo Miosi
3+
//
4+
// Distributed under the Boost Software License, Version 1.0. (See
5+
// accompanying file LICENSE_1_0.txt or copy at
6+
// http://www.boost.org/LICENSE_1_0.txt)
7+
//
8+
9+
#ifndef BOOST_LOCALE_NUMPUNCT_HPP_INCLUDED
10+
#define BOOST_LOCALE_NUMPUNCT_HPP_INCLUDED
11+
#include <boost/locale/config.hpp>
12+
#ifdef BOOST_MSVC
13+
# pragma warning(push)
14+
# pragma warning(disable : 4275 4251 4231 4660)
15+
#endif
16+
#include <locale>
17+
#include <string>
18+
19+
namespace boost {
20+
namespace locale {
21+
22+
template<typename CharType>
23+
class BOOST_LOCALE_DECL numpunct_base : public std::locale::facet
24+
{
25+
typedef std::basic_string<CharType> string_type;
26+
public:
27+
numpunct_base(size_t refs = 0) : std::locale::facet(refs) {}
28+
29+
string_type decimal_point() const {
30+
return do_decimal_point();
31+
}
32+
33+
string_type thousands_sep() const {
34+
return do_thousands_sep();
35+
}
36+
37+
std::string grouping() const {
38+
return do_grouping();
39+
}
40+
41+
string_type truename() const {
42+
return do_truename();
43+
}
44+
45+
string_type falsename() const {
46+
return do_falsename();
47+
}
48+
49+
protected:
50+
virtual string_type do_decimal_point() const {
51+
static const char t[] = ".";
52+
return string_type(t, t + sizeof(t) - 1);
53+
}
54+
virtual string_type do_thousands_sep() const {
55+
static const char t[] = ",";
56+
return string_type(t, t + sizeof(t) - 1);
57+
}
58+
virtual std::string do_grouping() const {
59+
return "";
60+
}
61+
virtual string_type do_truename() const {
62+
static const char t[] = "true";
63+
return string_type(t, t + sizeof(t) - 1);
64+
}
65+
virtual string_type do_falsename() const {
66+
static const char t[] = "false";
67+
return string_type(t, t + sizeof(t) - 1);
68+
}
69+
};
70+
71+
template<typename CharType> struct numpunct {};
72+
73+
template<> struct numpunct<char> : numpunct_base<char> {
74+
static std::locale::id id;
75+
76+
numpunct (size_t refs = 0) : numpunct_base<char>(refs) {}
77+
};
78+
79+
template<> struct numpunct<wchar_t> : numpunct_base<wchar_t> {
80+
static std::locale::id id;
81+
82+
numpunct (size_t refs = 0) : numpunct_base<wchar_t>(refs) {}
83+
};
84+
85+
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
86+
template<> struct numpunct<char16_t> : numpunct_base<char16_t> {
87+
static std::locale::id id;
88+
89+
numpunct (size_t refs = 0) : numpunct_base<char16_t>(refs) {}
90+
};
91+
#endif
92+
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
93+
template<> struct numpunct<char32_t> : numpunct_base<char32_t> {
94+
static std::locale::id id;
95+
96+
numpunct (size_t refs = 0) : numpunct_base<char32_t>(refs) {}
97+
};
98+
#endif
99+
}
100+
}
101+
102+
#endif

src/icu/numeric.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
#include "formatter.hpp"
1414
#include <boost/locale/formatting.hpp>
1515
#include <boost/locale/hold_ptr.hpp>
16+
#include <boost/locale/numpunct.hpp>
1617
#include "all_generator.hpp"
1718
#include "cdata.hpp"
1819
#include <algorithm>
1920
#include "predefined_formatters.hpp"
21+
#include "uconv.hpp"
2022

2123
namespace boost {
2224
namespace locale {
@@ -354,6 +356,42 @@ class num_parse : public std::num_get<CharType>, protected num_base
354356

355357
};
356358

359+
template<typename CharType>
360+
struct icu_numpunct : public numpunct<CharType> {
361+
typedef std::basic_string<CharType> string_type;
362+
public:
363+
icu_numpunct(icu::Locale const &loc)
364+
{
365+
UErrorCode err;
366+
icu::NumberFormat *fmt = icu::NumberFormat::createInstance(loc, UNUM_DECIMAL, err);
367+
if (auto *dec = dynamic_cast<icu::DecimalFormat *>(fmt)) {
368+
boost::locale::impl_icu::icu_std_converter<CharType> cnv("UTF-8");
369+
const icu::DecimalFormatSymbols *syms = dec->getDecimalFormatSymbols();
370+
decimal_point_ = cnv.std(syms->getSymbol(icu::DecimalFormatSymbols::kDecimalSeparatorSymbol));
371+
thousands_sep_ = cnv.std(syms->getSymbol(icu::DecimalFormatSymbols::kGroupingSeparatorSymbol));
372+
if (dec->isGroupingUsed()) {
373+
char grouping_size = dec->getGroupingSize();
374+
grouping_ = std::string(&grouping_size, 1);
375+
}
376+
}
377+
}
378+
protected:
379+
virtual string_type do_decimal_point() const {
380+
return decimal_point_;
381+
}
382+
virtual string_type do_thousands_sep() const {
383+
return thousands_sep_;
384+
}
385+
virtual std::string do_grouping() const {
386+
return grouping_;
387+
}
388+
389+
private:
390+
string_type decimal_point_;
391+
string_type thousands_sep_;
392+
std::string grouping_;
393+
};
394+
357395

358396
template<typename CharType>
359397
std::locale install_formatting_facets(std::locale const &in,cdata const &cd)
@@ -362,6 +400,7 @@ std::locale install_formatting_facets(std::locale const &in,cdata const &cd)
362400
if(!std::has_facet<icu_formatters_cache>(in)) {
363401
tmp=std::locale(tmp,new icu_formatters_cache(cd.locale));
364402
}
403+
tmp=std::locale(tmp, new icu_numpunct<CharType>(cd.locale));
365404
return tmp;
366405
}
367406

src/posix/numeric.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <boost/locale/formatting.hpp>
1616
#include <boost/locale/generator.hpp>
1717
#include <boost/locale/encoding.hpp>
18+
#include <boost/locale/numpunct.hpp>
1819
#include <boost/shared_ptr.hpp>
1920
#include <sstream>
2021
#include <stdlib.h>
@@ -404,20 +405,16 @@ struct basic_numpunct {
404405
};
405406

406407
template<typename CharType>
407-
class num_punct_posix : public std::numpunct<CharType> {
408+
class num_punct_posix : public numpunct<CharType> {
408409
public:
409410
typedef std::basic_string<CharType> string_type;
410411
num_punct_posix(locale_t lc,size_t refs = 0) :
411-
std::numpunct<CharType>(refs)
412+
numpunct<CharType>(refs)
412413
{
413414
basic_numpunct np(lc);
414415
to_str(np.thousands_sep,thousands_sep_,lc);
415416
to_str(np.decimal_point,decimal_point_,lc);
416417
grouping_ = np.grouping;
417-
if(thousands_sep_.size() > 1)
418-
grouping_ = std::string();
419-
if(decimal_point_.size() > 1)
420-
decimal_point_ = CharType('.');
421418
}
422419
void to_str(std::string &s1,std::string &s2,locale_t /*lc*/)
423420
{
@@ -429,11 +426,11 @@ class num_punct_posix : public std::numpunct<CharType> {
429426
}
430427
virtual CharType do_decimal_point() const
431428
{
432-
return *decimal_point_.c_str();
429+
return decimal_point_;
433430
}
434431
virtual CharType do_thousands_sep() const
435432
{
436-
return *thousands_sep_.c_str();
433+
return thousands_sep_;
437434
}
438435
virtual std::string do_grouping() const
439436
{

src/shared/ids.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <boost/locale/date_time_facet.hpp>
1313
#include <boost/locale/message.hpp>
1414
#include <boost/locale/info.hpp>
15+
#include <boost/locale/numpunct.hpp>
1516

1617
namespace boost {
1718
namespace locale {
@@ -25,17 +26,22 @@ namespace boost {
2526
std::locale::id converter<wchar_t>::id;
2627
std::locale::id base_message_format<wchar_t>::id;
2728

29+
std::locale::id numpunct<char>::id;
30+
std::locale::id numpunct<wchar_t>::id;
31+
2832
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
2933

3034
std::locale::id converter<char16_t>::id;
3135
std::locale::id base_message_format<char16_t>::id;
36+
std::locale::id numpunct<char16_t>::id;
3237

3338
#endif
3439

3540
#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
3641

3742
std::locale::id converter<char32_t>::id;
3843
std::locale::id base_message_format<char32_t>::id;
44+
std::locale::id numpunct<char32_t>::id;
3945

4046
#endif
4147

src/win32/numeric.cpp

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <boost/locale/formatting.hpp>
1313
#include <boost/locale/generator.hpp>
1414
#include <boost/locale/encoding.hpp>
15+
#include <boost/locale/numpunct.hpp>
1516
#include <boost/shared_ptr.hpp>
1617
#include <sstream>
1718
#include <stdlib.h>
@@ -119,11 +120,11 @@ class time_put_win : public std::time_put<CharType> {
119120

120121

121122
template<typename CharType>
122-
class num_punct_win : public std::numpunct<CharType> {
123+
class num_punct_win : public numpunct<CharType> {
123124
public:
124125
typedef std::basic_string<CharType> string_type;
125126
num_punct_win(winlocale const &lc,size_t refs = 0) :
126-
std::numpunct<CharType>(refs)
127+
numpunct<CharType>(refs)
127128
{
128129
numeric_info np = wcsnumformat_l(lc) ;
129130
if(sizeof(CharType) == 1 && np.thousands_sep == L"\xA0")
@@ -132,10 +133,6 @@ class num_punct_win : public std::numpunct<CharType> {
132133
to_str(np.thousands_sep,thousands_sep_);
133134
to_str(np.decimal_point,decimal_point_);
134135
grouping_ = np.grouping;
135-
if(thousands_sep_.size() > 1)
136-
grouping_ = std::string();
137-
if(decimal_point_.size() > 1)
138-
decimal_point_ = CharType('.');
139136
}
140137

141138
void to_str(std::wstring &s1,std::wstring &s2)
@@ -147,28 +144,18 @@ class num_punct_win : public std::numpunct<CharType> {
147144
{
148145
s2=conv::from_utf(s1,"UTF-8");
149146
}
150-
virtual CharType do_decimal_point() const
147+
virtual string_type do_decimal_point() const
151148
{
152-
return *decimal_point_.c_str();
149+
return decimal_point_;
153150
}
154-
virtual CharType do_thousands_sep() const
151+
virtual string_type do_thousands_sep() const
155152
{
156-
return *thousands_sep_.c_str();
153+
return thousands_sep_;
157154
}
158155
virtual std::string do_grouping() const
159156
{
160157
return grouping_;
161158
}
162-
virtual string_type do_truename() const
163-
{
164-
static const char t[]="true";
165-
return string_type(t,t+sizeof(t)-1);
166-
}
167-
virtual string_type do_falsename() const
168-
{
169-
static const char t[]="false";
170-
return string_type(t,t+sizeof(t)-1);
171-
}
172159
private:
173160
string_type decimal_point_;
174161
string_type thousands_sep_;
@@ -179,7 +166,7 @@ template<typename CharType>
179166
std::locale create_formatting_impl(std::locale const &in,winlocale const &lc)
180167
{
181168
if(lc.is_c()) {
182-
std::locale tmp(in,new std::numpunct_byname<CharType>("C"));
169+
std::locale tmp(in, new numpunct<CharType>());
183170
tmp=std::locale(tmp,new std::time_put_byname<CharType>("C"));
184171
tmp = std::locale(tmp,new num_format<CharType>(lc));
185172
return tmp;
@@ -195,12 +182,11 @@ std::locale create_formatting_impl(std::locale const &in,winlocale const &lc)
195182
template<typename CharType>
196183
std::locale create_parsing_impl(std::locale const &in,winlocale const &lc)
197184
{
198-
std::numpunct<CharType> *np = 0;
185+
std::locale tmp(in);
199186
if(lc.is_c())
200-
np = new std::numpunct_byname<CharType>("C");
187+
tmp = std::locale(tmp, new numpunct<CharType>());
201188
else
202-
np = new num_punct_win<CharType>(lc);
203-
std::locale tmp(in,np);
189+
tmp = std::locale(tmp, new num_punct_win<CharType>(lc));
204190
tmp = std::locale(tmp,new util::base_num_parse<CharType>());
205191
return tmp;
206192
}

0 commit comments

Comments
 (0)