diff options
author | thegeorg <thegeorg@yandex-team.com> | 2025-05-07 11:09:12 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2025-05-07 11:25:22 +0300 |
commit | 4c98f14a2491da2bc1a9d40fed1d1682c7ec5dd6 (patch) | |
tree | 8142081775c27c8780fa0282a0273ee268e13b98 /contrib/restricted/boost/locale/src/std/numeric.cpp | |
parent | 40b86c68b431bb65d67bba51ef9159066a833b68 (diff) | |
download | ydb-4c98f14a2491da2bc1a9d40fed1d1682c7ec5dd6.tar.gz |
Update contrib/restricted/boost/locale to 1.88.0
commit_hash:87b595328ea79c6ba38cb973580804486ca4a3ff
Diffstat (limited to 'contrib/restricted/boost/locale/src/std/numeric.cpp')
-rw-r--r-- | contrib/restricted/boost/locale/src/std/numeric.cpp | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/contrib/restricted/boost/locale/src/std/numeric.cpp b/contrib/restricted/boost/locale/src/std/numeric.cpp new file mode 100644 index 00000000000..b88cbd56530 --- /dev/null +++ b/contrib/restricted/boost/locale/src/std/numeric.cpp @@ -0,0 +1,319 @@ +// +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include <boost/locale/encoding.hpp> +#include <boost/locale/formatting.hpp> +#include <boost/locale/generator.hpp> +#include <algorithm> +#include <cstdlib> +#include <ios> +#include <locale> +#include <sstream> +#include <string> + +#include "../util/numeric.hpp" +#include "all_generator.hpp" + +namespace boost { namespace locale { namespace impl_std { + /// Forwarding time_put facet + /// Almost the same as `std::time_put_byname` but replaces the locale of the `ios_base` in `do_put` so that e.g. + /// weekday names are translated and formatting is as per the language of the base locale + template<typename CharType> + class time_put_from_base : public std::time_put<CharType> { + public: + using iter_type = typename std::time_put<CharType>::iter_type; + + time_put_from_base(const std::locale& base) : + base_facet_(std::use_facet<std::time_put<CharType>>(base)), base_ios_(nullptr) + { + // Imbue the ios with the base locale so the facets `do_put` uses its formatting information + base_ios_.imbue(base); + } + + iter_type do_put(iter_type out, + std::ios_base& /*ios*/, + CharType fill, + const std::tm* tm, + char format, + char modifier) const override + { + return base_facet_.put(out, base_ios_, fill, tm, format, modifier); + } + + private: + const std::time_put<CharType>& base_facet_; + mutable std::basic_ios<CharType> base_ios_; + }; + + class utf8_time_put_from_wide : public std::time_put<char> { + public: + utf8_time_put_from_wide(const std::locale& base, size_t refs = 0) : std::time_put<char>(refs), base_(base) {} + iter_type do_put(iter_type out, + std::ios_base& /*ios*/, + char fill, + const std::tm* tm, + char format, + char modifier = 0) const override + { + std::basic_ostringstream<wchar_t> wtmps; + wtmps.imbue(base_); + std::use_facet<std::time_put<wchar_t>>(base_) + .put(wtmps, wtmps, wchar_t(fill), tm, wchar_t(format), wchar_t(modifier)); + const std::string tmp = conv::utf_to_utf<char>(wtmps.str()); + return std::copy(tmp.begin(), tmp.end(), out); + } + + private: + std::locale base_; + }; + + class utf8_numpunct_from_wide : public std::numpunct<char> { + public: + utf8_numpunct_from_wide(const std::locale& base, size_t refs = 0) : std::numpunct<char>(refs) + { + typedef std::numpunct<wchar_t> wfacet_type; + const wfacet_type& wfacet = std::use_facet<wfacet_type>(base); + + truename_ = conv::utf_to_utf<char>(wfacet.truename()); + falsename_ = conv::utf_to_utf<char>(wfacet.falsename()); + + wchar_t tmp_decimal_point = wfacet.decimal_point(); + wchar_t tmp_thousands_sep = wfacet.thousands_sep(); + std::string tmp_grouping = wfacet.grouping(); + + if(32 <= tmp_thousands_sep && tmp_thousands_sep <= 126 && 32 <= tmp_decimal_point + && tmp_decimal_point <= 126) { + thousands_sep_ = static_cast<char>(tmp_thousands_sep); + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_ = tmp_grouping; + } else if(32 <= tmp_decimal_point && tmp_decimal_point <= 126 && tmp_thousands_sep == 0xA0) { + // workaround common bug - substitute NBSP with ordinary space + thousands_sep_ = ' '; + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_ = tmp_grouping; + } else if(32 <= tmp_decimal_point && tmp_decimal_point <= 126) { + thousands_sep_ = ','; + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_ = std::string(); + } else { + thousands_sep_ = ','; + decimal_point_ = '.'; + grouping_ = std::string(); + } + } + + char do_decimal_point() const override { return decimal_point_; } + char do_thousands_sep() const override { return thousands_sep_; } + std::string do_grouping() const override { return grouping_; } + std::string do_truename() const override { return truename_; } + std::string do_falsename() const override { return falsename_; } + + private: + std::string truename_; + std::string falsename_; + char thousands_sep_; + char decimal_point_; + std::string grouping_; + }; + + template<bool Intl> + class utf8_moneypunct_from_wide : public std::moneypunct<char, Intl> { + public: + utf8_moneypunct_from_wide(const std::locale& base, size_t refs = 0) : std::moneypunct<char, Intl>(refs) + { + typedef std::moneypunct<wchar_t, Intl> wfacet_type; + const wfacet_type& wfacet = std::use_facet<wfacet_type>(base); + + curr_symbol_ = conv::utf_to_utf<char>(wfacet.curr_symbol()); + positive_sign_ = conv::utf_to_utf<char>(wfacet.positive_sign()); + negative_sign_ = conv::utf_to_utf<char>(wfacet.negative_sign()); + frac_digits_ = wfacet.frac_digits(); + pos_format_ = wfacet.pos_format(); + neg_format_ = wfacet.neg_format(); + + wchar_t tmp_decimal_point = wfacet.decimal_point(); + wchar_t tmp_thousands_sep = wfacet.thousands_sep(); + std::string tmp_grouping = wfacet.grouping(); + if(32 <= tmp_thousands_sep && tmp_thousands_sep <= 126 && 32 <= tmp_decimal_point + && tmp_decimal_point <= 126) { + thousands_sep_ = static_cast<char>(tmp_thousands_sep); + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_ = tmp_grouping; + } else if(32 <= tmp_decimal_point && tmp_decimal_point <= 126 && tmp_thousands_sep == 0xA0) { + // workaround common bug - substitute NBSP with ordinary space + thousands_sep_ = ' '; + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_ = tmp_grouping; + } else if(32 <= tmp_decimal_point && tmp_decimal_point <= 126) { + thousands_sep_ = ','; + decimal_point_ = static_cast<char>(tmp_decimal_point); + grouping_ = std::string(); + } else { + thousands_sep_ = ','; + decimal_point_ = '.'; + grouping_ = std::string(); + } + } + + char do_decimal_point() const override { return decimal_point_; } + + char do_thousands_sep() const override { return thousands_sep_; } + + std::string do_grouping() const override { return grouping_; } + + std::string do_curr_symbol() const override { return curr_symbol_; } + std::string do_positive_sign() const override { return positive_sign_; } + std::string do_negative_sign() const override { return negative_sign_; } + + int do_frac_digits() const override { return frac_digits_; } + + std::money_base::pattern do_pos_format() const override { return pos_format_; } + + std::money_base::pattern do_neg_format() const override { return neg_format_; } + + private: + char thousands_sep_; + char decimal_point_; + std::string grouping_; + std::string curr_symbol_; + std::string positive_sign_; + std::string negative_sign_; + int frac_digits_; + std::money_base::pattern pos_format_, neg_format_; + }; + + class utf8_numpunct : public std::numpunct_byname<char> { + public: + typedef std::numpunct_byname<char> base_type; + utf8_numpunct(const std::string& name, size_t refs = 0) : std::numpunct_byname<char>(name, refs) {} + char do_thousands_sep() const override + { + unsigned char bs = base_type::do_thousands_sep(); + if(bs > 127) + if(bs == 0xA0) + return ' '; + else + return 0; + else + return bs; + } + std::string do_grouping() const override + { + unsigned char bs = base_type::do_thousands_sep(); + if(bs > 127 && bs != 0xA0) + return std::string(); + return base_type::do_grouping(); + } + }; + + template<bool Intl> + class utf8_moneypunct : public std::moneypunct_byname<char, Intl> { + public: + typedef std::moneypunct_byname<char, Intl> base_type; + utf8_moneypunct(const std::string& name, size_t refs = 0) : std::moneypunct_byname<char, Intl>(name, refs) {} + char do_thousands_sep() const override + { + unsigned char bs = base_type::do_thousands_sep(); + if(bs > 127) + if(bs == 0xA0) + return ' '; + else + return 0; + else + return bs; + } + std::string do_grouping() const override + { + unsigned char bs = base_type::do_thousands_sep(); + if(bs > 127 && bs != 0xA0) + return std::string(); + return base_type::do_grouping(); + } + }; + + template<typename CharType> + std::locale create_basic_parsing(const std::locale& in, const std::string& locale_name) + { + std::locale tmp = std::locale(in, new std::numpunct_byname<CharType>(locale_name)); + tmp = std::locale(tmp, new std::moneypunct_byname<CharType, true>(locale_name)); + tmp = std::locale(tmp, new std::moneypunct_byname<CharType, false>(locale_name)); + tmp = std::locale(tmp, new std::ctype_byname<CharType>(locale_name)); + return std::locale(tmp, new util::base_num_parse<CharType>()); + } + + template<typename CharType> + std::locale create_basic_formatting(const std::locale& in, const std::string& locale_name) + { + std::locale tmp = create_basic_parsing<CharType>(in, locale_name); + tmp = std::locale(tmp, new time_put_from_base<CharType>(std::locale(locale_name))); + return std::locale(tmp, new util::base_num_format<CharType>()); + } + + std::locale + create_formatting(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf) + { + switch(type) { + case char_facet_t::nochar: break; + case char_facet_t::char_f: + if(utf != utf8_support::none) { + const std::locale base(locale_name); + std::time_put<char>* time_put; + if(utf == utf8_support::from_wide) + time_put = new utf8_time_put_from_wide(base); + else + time_put = new time_put_from_base<char>(base); + std::locale tmp(in, time_put); + // Fix possibly invalid UTF-8 + tmp = std::locale(tmp, new utf8_numpunct_from_wide(base)); + tmp = std::locale(tmp, new utf8_moneypunct_from_wide<true>(base)); + tmp = std::locale(tmp, new utf8_moneypunct_from_wide<false>(base)); + return std::locale(tmp, new util::base_num_format<char>()); + } else + return create_basic_formatting<char>(in, locale_name); + case char_facet_t::wchar_f: return create_basic_formatting<wchar_t>(in, locale_name); +#ifdef __cpp_char8_t + case char_facet_t::char8_f: break; // std-facet not available (yet) +#endif +#ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char_facet_t::char16_f: return create_basic_formatting<char16_t>(in, locale_name); +#endif +#ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char_facet_t::char32_f: return create_basic_formatting<char32_t>(in, locale_name); +#endif + } + return in; + } + + std::locale + create_parsing(const std::locale& in, const std::string& locale_name, char_facet_t type, utf8_support utf) + { + switch(type) { + case char_facet_t::nochar: break; + case char_facet_t::char_f: + if(utf != utf8_support::none) { + const std::locale base(locale_name); + // Fix possibly invalid UTF-8 + std::locale tmp = std::locale(in, new utf8_numpunct_from_wide(base)); + tmp = std::locale(tmp, new utf8_moneypunct_from_wide<true>(base)); + tmp = std::locale(tmp, new utf8_moneypunct_from_wide<false>(base)); + return std::locale(tmp, new util::base_num_parse<char>()); + } else + return create_basic_parsing<char>(in, locale_name); + case char_facet_t::wchar_f: return create_basic_parsing<wchar_t>(in, locale_name); +#ifdef __cpp_char8_t + case char_facet_t::char8_f: break; // std-facet not available (yet) +#endif +#ifdef BOOST_LOCALE_ENABLE_CHAR16_T + case char_facet_t::char16_f: return create_basic_parsing<char16_t>(in, locale_name); +#endif +#ifdef BOOST_LOCALE_ENABLE_CHAR32_T + case char_facet_t::char32_f: return create_basic_parsing<char32_t>(in, locale_name); +#endif + } + return in; + } + +}}} // namespace boost::locale::impl_std |