summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/boost/locale/src/util/numeric.hpp
diff options
context:
space:
mode:
authorthegeorg <[email protected]>2025-05-07 11:09:12 +0300
committerthegeorg <[email protected]>2025-05-07 11:25:22 +0300
commit4c98f14a2491da2bc1a9d40fed1d1682c7ec5dd6 (patch)
tree8142081775c27c8780fa0282a0273ee268e13b98 /contrib/restricted/boost/locale/src/util/numeric.hpp
parent40b86c68b431bb65d67bba51ef9159066a833b68 (diff)
Update contrib/restricted/boost/locale to 1.88.0
commit_hash:87b595328ea79c6ba38cb973580804486ca4a3ff
Diffstat (limited to 'contrib/restricted/boost/locale/src/util/numeric.hpp')
-rw-r--r--contrib/restricted/boost/locale/src/util/numeric.hpp376
1 files changed, 376 insertions, 0 deletions
diff --git a/contrib/restricted/boost/locale/src/util/numeric.hpp b/contrib/restricted/boost/locale/src/util/numeric.hpp
new file mode 100644
index 00000000000..e54c95c5580
--- /dev/null
+++ b/contrib/restricted/boost/locale/src/util/numeric.hpp
@@ -0,0 +1,376 @@
+//
+// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
+//
+// Distributed under the Boost Software License, Version 1.0.
+// https://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_LOCALE_IMPL_UTIL_NUMERIC_HPP
+#define BOOST_LOCALE_IMPL_UTIL_NUMERIC_HPP
+#include <boost/locale/formatting.hpp>
+#include <boost/locale/info.hpp>
+#include <boost/predef/os.h>
+#include <algorithm>
+#include <ctime>
+#include <ios>
+#include <locale>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "timezone.hpp"
+
+namespace boost { namespace locale { namespace util {
+ template<typename CharType>
+ struct formatting_size_traits {
+ static size_t size(const std::basic_string<CharType>& s, const std::locale& /*l*/) { return s.size(); }
+ };
+
+ template<>
+ struct formatting_size_traits<char> {
+ static size_t size(const std::string& s, const std::locale& l)
+ {
+ if(!std::has_facet<info>(l))
+ return s.size();
+ if(!std::use_facet<info>(l).utf8())
+ return s.size();
+ // count code points, poor man's text size
+ return std::count_if(s.begin(), s.end(), [](const unsigned char c) {
+ return (c <= 127) // ASCII
+ || ((c & 0xC0) == 0xC0); // first UTF-8 byte
+ });
+ }
+ };
+
+ template<typename CharType>
+ class base_num_format : public std::num_put<CharType> {
+ public:
+ typedef typename std::num_put<CharType>::iter_type iter_type;
+ typedef std::basic_string<CharType> string_type;
+
+ base_num_format(size_t refs = 0) : std::num_put<CharType>(refs) {}
+
+ protected:
+ iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, long val) const override
+ {
+ return do_real_put(out, ios, fill, val);
+ }
+ iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, unsigned long val) const override
+ {
+ return do_real_put(out, ios, fill, val);
+ }
+ iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, double val) const override
+ {
+ return do_real_put(out, ios, fill, val);
+ }
+ iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, long double val) const override
+ {
+ return do_real_put(out, ios, fill, val);
+ }
+
+ iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, long long val) const override
+ {
+ return do_real_put(out, ios, fill, val);
+ }
+ iter_type do_put(iter_type out, std::ios_base& ios, CharType fill, unsigned long long val) const override
+ {
+ return do_real_put(out, ios, fill, val);
+ }
+
+ private:
+ template<typename ValueType>
+ iter_type do_real_put(iter_type out, std::ios_base& ios, CharType fill, ValueType val) const
+ {
+ typedef std::num_put<CharType> super;
+
+ ios_info& info = ios_info::get(ios);
+
+ switch(info.display_flags()) {
+ case flags::posix: {
+ typedef std::basic_ostringstream<CharType> sstream_type;
+ sstream_type ss;
+ ss.imbue(std::locale::classic());
+ ss.flags(ios.flags());
+ ss.precision(ios.precision());
+ ss.width(ios.width());
+ iter_type ret_ptr = super::do_put(out, ss, fill, val);
+ ios.width(0);
+ return ret_ptr;
+ }
+ case flags::date: return format_time(out, ios, fill, static_cast<std::time_t>(val), 'x');
+ case flags::time: return format_time(out, ios, fill, static_cast<std::time_t>(val), 'X');
+ case flags::datetime: return format_time(out, ios, fill, static_cast<std::time_t>(val), 'c');
+ case flags::strftime:
+ return format_time(out,
+ ios,
+ fill,
+ static_cast<std::time_t>(val),
+ info.date_time_pattern<CharType>());
+ case flags::currency: {
+ bool nat = info.currency_flags() == flags::currency_default
+ || info.currency_flags() == flags::currency_national;
+ bool intl = !nat;
+ return do_format_currency(intl, out, ios, fill, static_cast<long double>(val));
+ }
+
+ case flags::number:
+ case flags::percent:
+ case flags::spellout:
+ case flags::ordinal: break;
+ }
+ return super::do_put(out, ios, fill, val);
+ }
+
+ virtual iter_type
+ do_format_currency(bool intl, iter_type out, std::ios_base& ios, CharType fill, long double val) const
+ {
+ if(intl)
+ return format_currency<true>(out, ios, fill, val);
+ else
+ return format_currency<false>(out, ios, fill, val);
+ }
+
+ template<bool intl>
+ iter_type format_currency(iter_type out, std::ios_base& ios, CharType fill, long double val) const
+ {
+ std::locale loc = ios.getloc();
+ int digits = std::use_facet<std::moneypunct<CharType, intl>>(loc).frac_digits();
+ while(digits > 0) {
+ val *= 10;
+ digits--;
+ }
+ std::ios_base::fmtflags f = ios.flags();
+ ios.flags(f | std::ios_base::showbase);
+ out = std::use_facet<std::money_put<CharType>>(loc).put(out, intl, ios, fill, val);
+ ios.flags(f);
+ return out;
+ }
+
+ iter_type format_time(iter_type out, std::ios_base& ios, CharType fill, std::time_t time, char c) const
+ {
+ string_type fmt;
+ fmt += CharType('%');
+ fmt += CharType(c);
+ return format_time(out, ios, fill, time, fmt);
+ }
+
+ iter_type
+ format_time(iter_type out, std::ios_base& ios, CharType fill, std::time_t time, const string_type& format) const
+ {
+ const std::string& tz = ios_info::get(ios).time_zone();
+#if BOOST_OS_BSD_FREE || defined(__APPLE__)
+ std::vector<char> tz_nonconst;
+#endif
+ std::tm tm;
+ if(tz.empty()) {
+#ifdef BOOST_WINDOWS
+ // Windows uses TLS
+ tm = *localtime(&time);
+#else
+ localtime_r(&time, &tm);
+#endif
+ } else {
+ int gmtoff = parse_tz(tz);
+ time += gmtoff;
+#ifdef BOOST_WINDOWS
+ // Windows uses TLS
+ tm = *gmtime(&time);
+#else
+ gmtime_r(&time, &tm);
+#endif
+
+#if BOOST_OS_LINUX || BOOST_OS_BSD_FREE || defined(__APPLE__)
+ // These have extra fields to specify timezone
+ if(gmtoff != 0) {
+# if BOOST_OS_BSD_FREE || defined(__APPLE__)
+ // bsd and apple want tm_zone be non-const
+ tz_nonconst.assign(tz.begin(), tz.end());
+ tm.tm_zone = tz_nonconst.data();
+# else
+ tm.tm_zone = tz.data();
+# endif
+ tm.tm_gmtoff = gmtoff;
+ }
+#endif
+ }
+ std::basic_ostringstream<CharType> tmp_out;
+ std::use_facet<std::time_put<CharType>>(ios.getloc())
+ .put(tmp_out, tmp_out, fill, &tm, format.c_str(), format.c_str() + format.size());
+ string_type str = tmp_out.str();
+ std::streamsize on_left = 0, on_right = 0;
+ std::streamsize points = formatting_size_traits<CharType>::size(str, ios.getloc());
+ if(points < ios.width()) {
+ std::streamsize n = ios.width() - points;
+
+ std::ios_base::fmtflags flags = ios.flags() & std::ios_base::adjustfield;
+
+ // we do not really know internal point, so we assume that it does not
+ // exist. so according to the standard field should be right aligned
+ if(flags != std::ios_base::left)
+ on_left = n;
+ on_right = n - on_left;
+ }
+ while(on_left > 0) {
+ *out++ = fill;
+ on_left--;
+ }
+ std::copy(str.begin(), str.end(), out);
+ while(on_right > 0) {
+ *out++ = fill;
+ on_right--;
+ }
+ ios.width(0);
+ return out;
+ }
+
+ }; // num_format
+
+ template<typename CharType>
+ class base_num_parse : public std::num_get<CharType> {
+ public:
+ base_num_parse(size_t refs = 0) : std::num_get<CharType>(refs) {}
+
+ protected:
+ typedef typename std::num_get<CharType>::iter_type iter_type;
+ typedef std::basic_string<CharType> string_type;
+
+ iter_type
+ do_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, long& val) const override
+ {
+ return do_real_get(in, end, ios, err, val);
+ }
+
+ iter_type do_get(iter_type in,
+ iter_type end,
+ std::ios_base& ios,
+ std::ios_base::iostate& err,
+ unsigned short& val) const override
+ {
+ return do_real_get(in, end, ios, err, val);
+ }
+
+ iter_type do_get(iter_type in,
+ iter_type end,
+ std::ios_base& ios,
+ std::ios_base::iostate& err,
+ unsigned int& val) const override
+ {
+ return do_real_get(in, end, ios, err, val);
+ }
+
+ iter_type do_get(iter_type in,
+ iter_type end,
+ std::ios_base& ios,
+ std::ios_base::iostate& err,
+ unsigned long& val) const override
+ {
+ return do_real_get(in, end, ios, err, val);
+ }
+
+ iter_type
+ do_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, float& val) const override
+ {
+ return do_real_get(in, end, ios, err, val);
+ }
+
+ iter_type
+ do_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, double& val) const override
+ {
+ return do_real_get(in, end, ios, err, val);
+ }
+
+ iter_type do_get(iter_type in,
+ iter_type end,
+ std::ios_base& ios,
+ std::ios_base::iostate& err,
+ long double& val) const override
+ {
+ return do_real_get(in, end, ios, err, val);
+ }
+
+ iter_type do_get(iter_type in,
+ iter_type end,
+ std::ios_base& ios,
+ std::ios_base::iostate& err,
+ long long& val) const override
+ {
+ return do_real_get(in, end, ios, err, val);
+ }
+
+ iter_type do_get(iter_type in,
+ iter_type end,
+ std::ios_base& ios,
+ std::ios_base::iostate& err,
+ unsigned long long& val) const override
+ {
+ return do_real_get(in, end, ios, err, val);
+ }
+
+ private:
+ template<typename ValueType>
+ iter_type
+ do_real_get(iter_type in, iter_type end, std::ios_base& ios, std::ios_base::iostate& err, ValueType& val) const
+ {
+ typedef std::num_get<CharType> super;
+
+ ios_info& info = ios_info::get(ios);
+
+ switch(info.display_flags()) {
+ case flags::posix: {
+ std::stringstream ss;
+ ss.imbue(std::locale::classic());
+ ss.flags(ios.flags());
+ ss.precision(ios.precision());
+ return super::do_get(in, end, ss, err, val);
+ }
+ case flags::currency: {
+ long double ret_val = 0;
+ if(info.currency_flags() == flags::currency_default
+ || info.currency_flags() == flags::currency_national)
+ in = parse_currency<false>(in, end, ios, err, ret_val);
+ else
+ in = parse_currency<true>(in, end, ios, err, ret_val);
+ if(!(err & std::ios_base::failbit))
+ val = static_cast<ValueType>(ret_val);
+ return in;
+ }
+
+ // date-time parsing is not supported
+ // due to buggy standard
+ case flags::date:
+ case flags::time:
+ case flags::datetime:
+ case flags::strftime:
+
+ case flags::number:
+ case flags::percent:
+ case flags::spellout:
+ case flags::ordinal: break;
+ }
+ return super::do_get(in, end, ios, err, val);
+ }
+
+ template<bool intl>
+ iter_type parse_currency(iter_type in,
+ iter_type end,
+ std::ios_base& ios,
+ std::ios_base::iostate& err,
+ long double& val) const
+ {
+ std::locale loc = ios.getloc();
+ int digits = std::use_facet<std::moneypunct<CharType, intl>>(loc).frac_digits();
+ long double rval;
+ in = std::use_facet<std::money_get<CharType>>(loc).get(in, end, intl, ios, err, rval);
+ if(!(err & std::ios::failbit)) {
+ while(digits > 0) {
+ rval /= 10;
+ digits--;
+ }
+ val = rval;
+ }
+ return in;
+ }
+ };
+
+}}} // namespace boost::locale::util
+
+#endif