Skip to content

Commit

Permalink
Adds custom boost::locale::numpunct
Browse files Browse the repository at this point in the history
  • Loading branch information
salvoilmiosi committed Jul 4, 2021
1 parent 5789ae2 commit 77d1e5c
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 32 deletions.
1 change: 1 addition & 0 deletions include/boost/locale.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <boost/locale/encoding.hpp>
#include <boost/locale/format.hpp>
#include <boost/locale/formatting.hpp>
#include <boost/locale/numpunct.hpp>
#include <boost/locale/generator.hpp>
#include <boost/locale/gnu_gettext.hpp>
#include <boost/locale/info.hpp>
Expand Down
77 changes: 77 additions & 0 deletions include/boost/locale/numpunct.hpp
Original file line number Diff line number Diff line change
@@ -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 <boost/locale/config.hpp>
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable : 4275 4251 4231 4660)
#endif
#include <locale>
#include <string>

namespace boost {
namespace locale {
template<typename CharType>
class numpunct;

template<typename CharType>
class BOOST_LOCALE_DECL numpunct : public std::locale::facet
{
typedef std::basic_string<CharType> 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
30 changes: 30 additions & 0 deletions src/icu/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
#include "formatter.hpp"
#include <boost/locale/formatting.hpp>
#include <boost/locale/hold_ptr.hpp>
#include <boost/locale/numpunct.hpp>
#include "all_generator.hpp"
#include "cdata.hpp"
#include <algorithm>
#include "predefined_formatters.hpp"
#include "uconv.hpp"

namespace boost {
namespace locale {
Expand Down Expand Up @@ -354,6 +356,33 @@ class num_parse : public std::num_get<CharType>, protected num_base

};

template<typename CharType>
struct icu_numpunct : public numpunct<CharType> {
typedef std::basic_string<CharType> string_type;
public:
icu_numpunct(icu::Locale const &loc)
{
boost::locale::impl_icu::icu_std_converter<CharType> 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<typename CharType>
std::locale install_formatting_facets(std::locale const &in,cdata const &cd)
Expand All @@ -362,6 +391,7 @@ std::locale install_formatting_facets(std::locale const &in,cdata const &cd)
if(!std::has_facet<icu_formatters_cache>(in)) {
tmp=std::locale(tmp,new icu_formatters_cache(cd.locale));
}
tmp=std::locale(tmp, new icu_numpunct<CharType>(cd.locale));
return tmp;
}

Expand Down
13 changes: 5 additions & 8 deletions src/posix/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <boost/locale/formatting.hpp>
#include <boost/locale/generator.hpp>
#include <boost/locale/encoding.hpp>
#include <boost/locale/numpunct.hpp>
#include <boost/shared_ptr.hpp>
#include <sstream>
#include <stdlib.h>
Expand Down Expand Up @@ -404,20 +405,16 @@ struct basic_numpunct {
};

template<typename CharType>
class num_punct_posix : public std::numpunct<CharType> {
class num_punct_posix : public numpunct<CharType> {
public:
typedef std::basic_string<CharType> string_type;
num_punct_posix(locale_t lc,size_t refs = 0) :
std::numpunct<CharType>(refs)
numpunct<CharType>(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*/)
{
Expand All @@ -429,11 +426,11 @@ class num_punct_posix : public std::numpunct<CharType> {
}
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
{
Expand Down
6 changes: 6 additions & 0 deletions src/shared/ids.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <boost/locale/date_time_facet.hpp>
#include <boost/locale/message.hpp>
#include <boost/locale/info.hpp>
#include <boost/locale/numpunct.hpp>

namespace boost {
namespace locale {
Expand All @@ -25,17 +26,22 @@ namespace boost {
std::locale::id converter<wchar_t>::id;
std::locale::id base_message_format<wchar_t>::id;

// std::locale::id numpunct<char>::id;
// std::locale::id numpunct<wchar_t>::id;

#ifdef BOOST_LOCALE_ENABLE_CHAR16_T

std::locale::id converter<char16_t>::id;
std::locale::id base_message_format<char16_t>::id;
// std::locale::id numpunct<char16_t>::id;

#endif

#ifdef BOOST_LOCALE_ENABLE_CHAR32_T

std::locale::id converter<char32_t>::id;
std::locale::id base_message_format<char32_t>::id;
// std::locale::id numpunct<char32_t>::id;

#endif

Expand Down
34 changes: 10 additions & 24 deletions src/win32/numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <boost/locale/formatting.hpp>
#include <boost/locale/generator.hpp>
#include <boost/locale/encoding.hpp>
#include <boost/locale/numpunct.hpp>
#include <boost/shared_ptr.hpp>
#include <sstream>
#include <stdlib.h>
Expand Down Expand Up @@ -119,11 +120,11 @@ class time_put_win : public std::time_put<CharType> {


template<typename CharType>
class num_punct_win : public std::numpunct<CharType> {
class num_punct_win : public numpunct<CharType> {
public:
typedef std::basic_string<CharType> string_type;
num_punct_win(winlocale const &lc,size_t refs = 0) :
std::numpunct<CharType>(refs)
numpunct<CharType>(refs)
{
numeric_info np = wcsnumformat_l(lc) ;
if(sizeof(CharType) == 1 && np.thousands_sep == L"\xA0")
Expand All @@ -132,10 +133,6 @@ class num_punct_win : public std::numpunct<CharType> {
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)
Expand All @@ -147,28 +144,18 @@ class num_punct_win : public std::numpunct<CharType> {
{
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_;
Expand All @@ -195,12 +182,11 @@ std::locale create_formatting_impl(std::locale const &in,winlocale const &lc)
template<typename CharType>
std::locale create_parsing_impl(std::locale const &in,winlocale const &lc)
{
std::numpunct<CharType> *np = 0;
std::locale tmp(in);
if(lc.is_c())
np = new std::numpunct_byname<CharType>("C");
tmp = std::locale(tmp, new std::numpunct_byname<CharType>("C"));
else
np = new num_punct_win<CharType>(lc);
std::locale tmp(in,np);
tmp = std::locale(tmp, new num_punct_win<CharType>(lc));
tmp = std::locale(tmp,new util::base_num_parse<CharType>());
return tmp;
}
Expand Down
14 changes: 14 additions & 0 deletions test_numpunct.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include <iostream>
#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<boost::locale::numpunct<char>>(loc);
std::cout << facet.decimal_point() << ' ' << facet.thousands_sep() << '\n';
}

0 comments on commit 77d1e5c

Please sign in to comment.