Skip to content

Commit 8ddfc7e

Browse files
committed
Added custom boost::locale::numpunct
1 parent 5789ae2 commit 8ddfc7e

File tree

5 files changed

+162
-36
lines changed

5 files changed

+162
-36
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: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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::numpunct<CharType>
24+
{
25+
typedef std::basic_string<CharType> string_type;
26+
public:
27+
numpunct_base(size_t refs = 0) : std::numpunct<CharType>(refs) {}
28+
29+
string_type decimal_point_full() const {
30+
return do_decimal_point_full();
31+
}
32+
33+
string_type thousands_sep_full() const {
34+
return do_thousands_sep_full();
35+
}
36+
37+
protected:
38+
virtual CharType do_decimal_point() const {
39+
string_type dec = do_decimal_point_full();
40+
if (dec.size() > 1) {
41+
return '.';
42+
} else {
43+
return dec[0];
44+
}
45+
}
46+
47+
virtual string_type do_decimal_point_full() const {
48+
static const char t[] = ".";
49+
return string_type(t, t + sizeof(t) - 1);
50+
}
51+
52+
virtual CharType do_thousands_sep() const {
53+
string_type thous = do_thousands_sep_full();
54+
if (thous.size() > 1) {
55+
return ',';
56+
} else {
57+
return thous[0];
58+
}
59+
}
60+
61+
virtual string_type do_thousands_sep_full() const {
62+
static const char t[] = ",";
63+
return string_type(t, t + sizeof(t) - 1);
64+
}
65+
66+
virtual string_type do_truename() const {
67+
static const char t[] = "true";
68+
return string_type(t, t + sizeof(t) - 1);
69+
}
70+
71+
virtual string_type do_falsename() const {
72+
static const char t[] = "false";
73+
return string_type(t, t + sizeof(t) - 1);
74+
}
75+
};
76+
77+
template<typename CharType> struct numpunct {};
78+
79+
template<> struct numpunct<char> : numpunct_base<char> {
80+
numpunct (size_t refs = 0) : numpunct_base<char>(refs) {}
81+
};
82+
83+
template<> struct numpunct<wchar_t> : numpunct_base<wchar_t> {
84+
numpunct (size_t refs = 0) : numpunct_base<wchar_t>(refs) {}
85+
};
86+
87+
#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
88+
template<> struct numpunct<char16_t> : numpunct_base<char16_t> {
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+
numpunct (size_t refs = 0) : numpunct_base<char32_t>(refs) {}
95+
};
96+
#endif
97+
}
98+
}
99+
100+
#endif

src/icu/numeric.cpp

Lines changed: 43 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,46 @@ 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 = U_ZERO_ERROR;
366+
icu::NumberFormat *fmt = icu::NumberFormat::createInstance(loc, UNUM_DECIMAL, err);
367+
if (icu::DecimalFormat *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+
int32_t grouping_size = dec->getGroupingSize();
374+
grouping_ = std::string(reinterpret_cast<char*>(&grouping_size), 1);
375+
int32_t grouping_size_2 = dec->getSecondaryGroupingSize();
376+
if (grouping_size_2 > 0 && grouping_size_2 != grouping_size) {
377+
grouping_ += static_cast<char>(grouping_size_2);
378+
}
379+
}
380+
}
381+
}
382+
protected:
383+
virtual string_type do_decimal_point_full() const {
384+
return decimal_point_;
385+
}
386+
virtual string_type do_thousands_sep_full() const {
387+
return thousands_sep_;
388+
}
389+
virtual std::string do_grouping() const {
390+
return grouping_;
391+
}
392+
393+
private:
394+
string_type decimal_point_;
395+
string_type thousands_sep_;
396+
std::string grouping_;
397+
};
398+
357399

358400
template<typename CharType>
359401
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)
362404
if(!std::has_facet<icu_formatters_cache>(in)) {
363405
tmp=std::locale(tmp,new icu_formatters_cache(cd.locale));
364406
}
407+
tmp=std::locale(tmp, new icu_numpunct<CharType>(cd.locale));
365408
return tmp;
366409
}
367410

src/posix/numeric.cpp

Lines changed: 7 additions & 10 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
{
@@ -427,13 +424,13 @@ class num_punct_posix : public std::numpunct<CharType> {
427424
{
428425
s2=conv::to_utf<wchar_t>(s1,nl_langinfo_l(CODESET,lc));
429426
}
430-
virtual CharType do_decimal_point() const
427+
virtual string_type do_decimal_point_full() const
431428
{
432-
return *decimal_point_.c_str();
429+
return decimal_point_;
433430
}
434-
virtual CharType do_thousands_sep() const
431+
virtual string_type do_thousands_sep_full() const
435432
{
436-
return *thousands_sep_.c_str();
433+
return thousands_sep_;
437434
}
438435
virtual std::string do_grouping() const
439436
{

src/win32/numeric.cpp

Lines changed: 11 additions & 26 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_full() 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_full() 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;
@@ -193,14 +180,12 @@ std::locale create_formatting_impl(std::locale const &in,winlocale const &lc)
193180
}
194181

195182
template<typename CharType>
196-
std::locale create_parsing_impl(std::locale const &in,winlocale const &lc)
183+
std::locale create_parsing_impl(std::locale tmp,winlocale const &lc)
197184
{
198-
std::numpunct<CharType> *np = 0;
199185
if(lc.is_c())
200-
np = new std::numpunct_byname<CharType>("C");
186+
tmp = std::locale(tmp, new numpunct<CharType>());
201187
else
202-
np = new num_punct_win<CharType>(lc);
203-
std::locale tmp(in,np);
188+
tmp = std::locale(tmp, new num_punct_win<CharType>(lc));
204189
tmp = std::locale(tmp,new util::base_num_parse<CharType>());
205190
return tmp;
206191
}

0 commit comments

Comments
 (0)