Skip to content

Commit 77d1e5c

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

7 files changed

Lines changed: 143 additions & 32 deletions

File tree

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: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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+
template<typename CharType>
22+
class numpunct;
23+
24+
template<typename CharType>
25+
class BOOST_LOCALE_DECL numpunct : public std::locale::facet
26+
{
27+
typedef std::basic_string<CharType> string_type;
28+
public:
29+
static inline std::locale::id id;
30+
31+
numpunct (size_t refs = 0) : std::locale::facet(refs) {}
32+
33+
string_type decimal_point() const {
34+
return do_decimal_point();
35+
}
36+
37+
string_type thousands_sep() const {
38+
return do_thousands_sep();
39+
}
40+
41+
string_type grouping() const {
42+
return do_grouping();
43+
}
44+
45+
string_type truename() const {
46+
return do_truename();
47+
}
48+
49+
string_type falsename() const {
50+
return do_falsename();
51+
}
52+
53+
protected:
54+
virtual string_type do_decimal_point() const {
55+
static const char t[] = ".";
56+
return string_type(t, t + sizeof(t) - 1);
57+
}
58+
virtual string_type do_thousands_sep() const {
59+
static const char t[] = ",";
60+
return string_type(t, t + sizeof(t) - 1);
61+
}
62+
virtual std::string do_grouping() const {
63+
return "";
64+
}
65+
virtual string_type do_truename() const {
66+
static const char t[] = "true";
67+
return string_type(t, t + sizeof(t) - 1);
68+
}
69+
virtual string_type do_falsename() const {
70+
static const char t[] = "false";
71+
return string_type(t, t + sizeof(t) - 1);
72+
}
73+
};
74+
}
75+
}
76+
77+
#endif

src/icu/numeric.cpp

Lines changed: 30 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,33 @@ 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+
boost::locale::impl_icu::icu_std_converter<CharType> cnv("UTF-8");
366+
UErrorCode err;
367+
icu::DecimalFormatSymbols syms(loc, err);
368+
decimal_point_ = cnv.std(syms.getSymbol(icu::DecimalFormatSymbols::kDecimalSeparatorSymbol));
369+
thousands_sep_ = cnv.std(syms.getSymbol(icu::DecimalFormatSymbols::kGroupingSeparatorSymbol));
370+
}
371+
protected:
372+
virtual string_type do_decimal_point() const
373+
{
374+
return decimal_point_;
375+
}
376+
virtual string_type do_thousands_sep() const
377+
{
378+
return thousands_sep_;
379+
}
380+
381+
private:
382+
string_type decimal_point_;
383+
string_type thousands_sep_;
384+
};
385+
357386

358387
template<typename CharType>
359388
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)
362391
if(!std::has_facet<icu_formatters_cache>(in)) {
363392
tmp=std::locale(tmp,new icu_formatters_cache(cd.locale));
364393
}
394+
tmp=std::locale(tmp, new icu_numpunct<CharType>(cd.locale));
365395
return tmp;
366396
}
367397

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: 10 additions & 24 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_;
@@ -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 std::numpunct_byname<CharType>("C"));
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
}

test_numpunct.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include <iostream>
2+
#include "boost/locale.hpp"
3+
4+
int main(int argc, char **argv) {
5+
const char *lang = "";
6+
if (argc > 1) {
7+
lang = argv[1];
8+
}
9+
boost::locale::generator gen;
10+
std::locale loc = gen(lang);
11+
12+
auto &facet = std::use_facet<boost::locale::numpunct<char>>(loc);
13+
std::cout << facet.decimal_point() << ' ' << facet.thousands_sep() << '\n';
14+
}

0 commit comments

Comments
 (0)