From b15c37e7632bd19cc745e916b50f1d57e7734ae9 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Wed, 25 Jun 2025 09:19:57 +0200 Subject: [PATCH] [libc++] Granularize --- libcxx/include/CMakeLists.txt | 9 + libcxx/include/__chrono/formatter.h | 4 +- libcxx/include/__filesystem/path.h | 1 - libcxx/include/__filesystem/u8path.h | 7 +- libcxx/include/__locale_dir/check_grouping.h | 31 + libcxx/include/__locale_dir/get_c_locale.h | 40 + libcxx/include/__locale_dir/messages.h | 143 + libcxx/include/__locale_dir/money.h | 873 +++++ libcxx/include/__locale_dir/num.h | 1072 +++++ libcxx/include/__locale_dir/scan_keyword.h | 143 + libcxx/include/__locale_dir/time.h | 766 ++++ libcxx/include/__locale_dir/wbuffer_convert.h | 430 ++ libcxx/include/__locale_dir/wstring_convert.h | 254 ++ libcxx/include/__ostream/basic_ostream.h | 4 +- libcxx/include/__ostream/print.h | 2 +- libcxx/include/__thread/thread.h | 2 +- libcxx/include/experimental/iterator | 5 + libcxx/include/iomanip | 9 +- libcxx/include/istream | 7 +- libcxx/include/locale | 3488 +---------------- libcxx/include/module.modulemap.in | 11 +- libcxx/include/ostream | 5 + libcxx/include/sstream | 2 +- .../locale.categories/__scan_keyword.pass.cpp | 5 +- .../test/libcxx/transitive_includes/cxx26.csv | 18 - .../ext.manip/get_money.pass.cpp | 3 +- .../ext.manip/get_time.pass.cpp | 4 +- .../ext.manip/put_time.pass.cpp | 3 +- .../locale.time.get.byname/get_date.pass.cpp | 4 +- .../get_monthname.pass.cpp | 4 +- .../locale.time.get.byname/get_one.pass.cpp | 4 +- .../locale.time.get.byname/get_time.pass.cpp | 4 +- .../get_weekday.pass.cpp | 4 +- .../locale.time.get.byname/get_year.pass.cpp | 4 +- .../locale.time.get.members/get_date.pass.cpp | 4 +- .../locale.time.get.members/get_many.pass.cpp | 4 +- .../get_monthname.pass.cpp | 4 +- .../locale.time.get.members/get_one.pass.cpp | 4 +- .../locale.time.get.members/get_time.pass.cpp | 4 +- .../get_weekday.pass.cpp | 4 +- .../locale.time.get.members/get_year.pass.cpp | 4 +- libcxx/test/support/concat_macros.h | 1 + .../header_exportable_declarations.cpp | 2 + 43 files changed, 3864 insertions(+), 3532 deletions(-) create mode 100644 libcxx/include/__locale_dir/check_grouping.h create mode 100644 libcxx/include/__locale_dir/get_c_locale.h create mode 100644 libcxx/include/__locale_dir/messages.h create mode 100644 libcxx/include/__locale_dir/money.h create mode 100644 libcxx/include/__locale_dir/num.h create mode 100644 libcxx/include/__locale_dir/scan_keyword.h create mode 100644 libcxx/include/__locale_dir/time.h create mode 100644 libcxx/include/__locale_dir/wbuffer_convert.h create mode 100644 libcxx/include/__locale_dir/wstring_convert.h diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index c334b25574305..e2e3905777339 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -511,13 +511,19 @@ set(files __iterator/unreachable_sentinel.h __iterator/wrap_iter.h __locale + __locale_dir/check_grouping.h + __locale_dir/get_c_locale.h __locale_dir/locale_base_api.h __locale_dir/locale_base_api/android.h __locale_dir/locale_base_api/bsd_locale_fallbacks.h __locale_dir/locale_base_api/ibm.h __locale_dir/locale_base_api/musl.h __locale_dir/locale_base_api/openbsd.h + __locale_dir/messages.h + __locale_dir/money.h + __locale_dir/num.h __locale_dir/pad_and_output.h + __locale_dir/scan_keyword.h __locale_dir/support/apple.h __locale_dir/support/bsd_like.h __locale_dir/support/freebsd.h @@ -526,6 +532,9 @@ set(files __locale_dir/support/no_locale/characters.h __locale_dir/support/no_locale/strtonum.h __locale_dir/support/windows.h + __locale_dir/time.h + __locale_dir/wbuffer_convert.h + __locale_dir/wstring_convert.h __math/abs.h __math/copysign.h __math/error_functions.h diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h index 86b606d27847b..49758397f6185 100644 --- a/libcxx/include/__chrono/formatter.h +++ b/libcxx/include/__chrono/formatter.h @@ -50,12 +50,14 @@ # include <__format/formatter.h> # include <__format/parser_std_format_spec.h> # include <__format/write_escaped.h> +# include <__iterator/istreambuf_iterator.h> +# include <__iterator/ostreambuf_iterator.h> +# include <__locale_dir/time.h> # include <__memory/addressof.h> # include <__type_traits/is_specialization.h> # include # include # include -# include # include # include diff --git a/libcxx/include/__filesystem/path.h b/libcxx/include/__filesystem/path.h index a2c28bfd79bb9..381e5678a5855 100644 --- a/libcxx/include/__filesystem/path.h +++ b/libcxx/include/__filesystem/path.h @@ -29,7 +29,6 @@ #if _LIBCPP_HAS_LOCALIZATION # include // for quoted -# include #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/__filesystem/u8path.h b/libcxx/include/__filesystem/u8path.h index e13980298d9e9..a701425e42919 100644 --- a/libcxx/include/__filesystem/u8path.h +++ b/libcxx/include/__filesystem/u8path.h @@ -13,14 +13,9 @@ #include <__algorithm/unwrap_iter.h> #include <__config> #include <__filesystem/path.h> +#include <__locale> #include -// Only required on Windows for __widen_from_utf8, and included conservatively -// because it requires support for localization. -#if defined(_LIBCPP_WIN32API) -# include -#endif - #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif diff --git a/libcxx/include/__locale_dir/check_grouping.h b/libcxx/include/__locale_dir/check_grouping.h new file mode 100644 index 0000000000000..93e9e404bb5f3 --- /dev/null +++ b/libcxx/include/__locale_dir/check_grouping.h @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_CHECK_GROUPING_H +#define _LIBCPP___LOCALE_DIR_CHECK_GROUPING_H + +#include <__config> +#include <__fwd/string.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_EXPORTED_FROM_ABI void +__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, ios_base::iostate& __err); + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_CHECK_GROUPING_H diff --git a/libcxx/include/__locale_dir/get_c_locale.h b/libcxx/include/__locale_dir/get_c_locale.h new file mode 100644 index 0000000000000..e8bac9a87095b --- /dev/null +++ b/libcxx/include/__locale_dir/get_c_locale.h @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_GET_C_LOCALE_H +#define _LIBCPP___LOCALE_DIR_GET_C_LOCALE_H + +#include <__config> +#include <__locale_dir/locale_base_api.h> + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// FIXME: This should really be part of the locale base API + +# if defined(__APPLE__) || defined(__FreeBSD__) +# define _LIBCPP_GET_C_LOCALE 0 +# elif defined(__NetBSD__) +# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE +# else +# define _LIBCPP_GET_C_LOCALE __cloc() +// Get the C locale object +_LIBCPP_EXPORTED_FROM_ABI __locale::__locale_t __cloc(); +# define __cloc_defined +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_GET_C_LOCALE_H diff --git a/libcxx/include/__locale_dir/messages.h b/libcxx/include/__locale_dir/messages.h new file mode 100644 index 0000000000000..c04bf04025ff0 --- /dev/null +++ b/libcxx/include/__locale_dir/messages.h @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_MESSAGES_H +#define _LIBCPP___LOCALE_DIR_MESSAGES_H + +#include <__config> +#include <__iterator/back_insert_iterator.h> +#include <__locale> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +// Most unix variants have catopen. These are the specific ones that don't. +# if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION) && !defined(__EMSCRIPTEN__) +# define _LIBCPP_HAS_CATOPEN 1 +# include +# else +# define _LIBCPP_HAS_CATOPEN 0 +# endif +# else +# define _LIBCPP_HAS_CATOPEN 0 +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_EXPORTED_FROM_ABI messages_base { +public: + typedef intptr_t catalog; + + _LIBCPP_HIDE_FROM_ABI messages_base() {} +}; + +template +class messages : public locale::facet, public messages_base { +public: + typedef _CharT char_type; + typedef basic_string<_CharT> string_type; + + _LIBCPP_HIDE_FROM_ABI explicit messages(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI catalog open(const basic_string& __nm, const locale& __loc) const { + return do_open(__nm, __loc); + } + + _LIBCPP_HIDE_FROM_ABI string_type get(catalog __c, int __set, int __msgid, const string_type& __dflt) const { + return do_get(__c, __set, __msgid, __dflt); + } + + _LIBCPP_HIDE_FROM_ABI void close(catalog __c) const { do_close(__c); } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages() override {} + + virtual catalog do_open(const basic_string&, const locale&) const; + virtual string_type do_get(catalog, int __set, int __msgid, const string_type& __dflt) const; + virtual void do_close(catalog) const; +}; + +template +locale::id messages<_CharT>::id; + +template +typename messages<_CharT>::catalog messages<_CharT>::do_open(const basic_string& __nm, const locale&) const { +# if _LIBCPP_HAS_CATOPEN + return (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE); +# else // !_LIBCPP_HAS_CATOPEN + (void)__nm; + return -1; +# endif // _LIBCPP_HAS_CATOPEN +} + +template +typename messages<_CharT>::string_type +messages<_CharT>::do_get(catalog __c, int __set, int __msgid, const string_type& __dflt) const { +# if _LIBCPP_HAS_CATOPEN + string __ndflt; + __narrow_to_utf8()( + std::back_inserter(__ndflt), __dflt.c_str(), __dflt.c_str() + __dflt.size()); + nl_catd __cat = (nl_catd)__c; + static_assert(sizeof(catalog) >= sizeof(nl_catd), "Unexpected nl_catd type"); + char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str()); + string_type __w; + __widen_from_utf8()(std::back_inserter(__w), __n, __n + std::strlen(__n)); + return __w; +# else // !_LIBCPP_HAS_CATOPEN + (void)__c; + (void)__set; + (void)__msgid; + return __dflt; +# endif // _LIBCPP_HAS_CATOPEN +} + +template +void messages<_CharT>::do_close(catalog __c) const { +# if _LIBCPP_HAS_CATOPEN + catclose((nl_catd)__c); +# else // !_LIBCPP_HAS_CATOPEN + (void)__c; +# endif // _LIBCPP_HAS_CATOPEN +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages; +# endif + +template +class messages_byname : public messages<_CharT> { +public: + typedef messages_base::catalog catalog; + typedef basic_string<_CharT> string_type; + + _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const char*, size_t __refs = 0) : messages<_CharT>(__refs) {} + + _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const string&, size_t __refs = 0) : messages<_CharT>(__refs) {} + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages_byname() override {} +}; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname; +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_MESSAGES_H diff --git a/libcxx/include/__locale_dir/money.h b/libcxx/include/__locale_dir/money.h new file mode 100644 index 0000000000000..c1296665505e1 --- /dev/null +++ b/libcxx/include/__locale_dir/money.h @@ -0,0 +1,873 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_MONEY_H +#define _LIBCPP___LOCALE_DIR_MONEY_H + +#include <__algorithm/copy.h> +#include <__algorithm/equal.h> +#include <__algorithm/find.h> +#include <__algorithm/reverse.h> +#include <__config> +#include <__locale> +#include <__locale_dir/check_grouping.h> +#include <__locale_dir/get_c_locale.h> +#include <__locale_dir/pad_and_output.h> +#include <__memory/unique_ptr.h> +#include +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +// money_base + +class _LIBCPP_EXPORTED_FROM_ABI money_base { +public: + enum part { none, space, symbol, sign, value }; + struct pattern { + char field[4]; + }; + + _LIBCPP_HIDE_FROM_ABI money_base() {} +}; + +// moneypunct + +template +class moneypunct : public locale::facet, public money_base { +public: + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI char_type decimal_point() const { return do_decimal_point(); } + _LIBCPP_HIDE_FROM_ABI char_type thousands_sep() const { return do_thousands_sep(); } + _LIBCPP_HIDE_FROM_ABI string grouping() const { return do_grouping(); } + _LIBCPP_HIDE_FROM_ABI string_type curr_symbol() const { return do_curr_symbol(); } + _LIBCPP_HIDE_FROM_ABI string_type positive_sign() const { return do_positive_sign(); } + _LIBCPP_HIDE_FROM_ABI string_type negative_sign() const { return do_negative_sign(); } + _LIBCPP_HIDE_FROM_ABI int frac_digits() const { return do_frac_digits(); } + _LIBCPP_HIDE_FROM_ABI pattern pos_format() const { return do_pos_format(); } + _LIBCPP_HIDE_FROM_ABI pattern neg_format() const { return do_neg_format(); } + + static locale::id id; + static const bool intl = _International; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct() override {} + + virtual char_type do_decimal_point() const { return numeric_limits::max(); } + virtual char_type do_thousands_sep() const { return numeric_limits::max(); } + virtual string do_grouping() const { return string(); } + virtual string_type do_curr_symbol() const { return string_type(); } + virtual string_type do_positive_sign() const { return string_type(); } + virtual string_type do_negative_sign() const { return string_type(1, '-'); } + virtual int do_frac_digits() const { return 0; } + virtual pattern do_pos_format() const { + pattern __p = {{symbol, sign, none, value}}; + return __p; + } + virtual pattern do_neg_format() const { + pattern __p = {{symbol, sign, none, value}}; + return __p; + } +}; + +template +locale::id moneypunct<_CharT, _International>::id; + +template +const bool moneypunct<_CharT, _International>::intl; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; +# endif + +// moneypunct_byname + +template +class moneypunct_byname : public moneypunct<_CharT, _International> { +public: + typedef money_base::pattern pattern; + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const char* __nm, size_t __refs = 0) + : moneypunct<_CharT, _International>(__refs) { + init(__nm); + } + + _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const string& __nm, size_t __refs = 0) + : moneypunct<_CharT, _International>(__refs) { + init(__nm.c_str()); + } + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct_byname() override {} + + char_type do_decimal_point() const override { return __decimal_point_; } + char_type do_thousands_sep() const override { return __thousands_sep_; } + string do_grouping() const override { return __grouping_; } + string_type do_curr_symbol() const override { return __curr_symbol_; } + string_type do_positive_sign() const override { return __positive_sign_; } + string_type do_negative_sign() const override { return __negative_sign_; } + int do_frac_digits() const override { return __frac_digits_; } + pattern do_pos_format() const override { return __pos_format_; } + pattern do_neg_format() const override { return __neg_format_; } + +private: + char_type __decimal_point_; + char_type __thousands_sep_; + string __grouping_; + string_type __curr_symbol_; + string_type __positive_sign_; + string_type __negative_sign_; + int __frac_digits_; + pattern __pos_format_; + pattern __neg_format_; + + void init(const char*); +}; + +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; + +# if _LIBCPP_HAS_WIDE_CHARACTERS +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +template <> +_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; +# endif + +// money_get + +template +class __money_get { +protected: + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI __money_get() {} + + static void __gather_info( + bool __intl, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __psn, + string_type& __nsn, + int& __fd); +}; + +template +void __money_get<_CharT>::__gather_info( + bool __intl, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __psn, + string_type& __nsn, + int& __fd) { + if (__intl) { + const moneypunct& __mp = std::use_facet >(__loc); + __pat = __mp.neg_format(); + __nsn = __mp.negative_sign(); + __psn = __mp.positive_sign(); + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } else { + const moneypunct& __mp = std::use_facet >(__loc); + __pat = __mp.neg_format(); + __nsn = __mp.negative_sign(); + __psn = __mp.positive_sign(); + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get; +# endif + +template > +class money_get : public locale::facet, private __money_get<_CharT> { +public: + typedef _CharT char_type; + typedef _InputIterator iter_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit money_get(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + return do_get(__b, __e, __intl, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const { + return do_get(__b, __e, __intl, __iob, __err, __v); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_get() override {} + + virtual iter_type + do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const; + virtual iter_type + do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const; + +private: + static bool __do_get( + iter_type& __b, + iter_type __e, + bool __intl, + const locale& __loc, + ios_base::fmtflags __flags, + ios_base::iostate& __err, + bool& __neg, + const ctype& __ct, + unique_ptr& __wb, + char_type*& __wn, + char_type* __we); +}; + +template +locale::id money_get<_CharT, _InputIterator>::id; + +_LIBCPP_EXPORTED_FROM_ABI void __do_nothing(void*); + +template +_LIBCPP_HIDE_FROM_ABI void __double_or_nothing(unique_ptr<_Tp, void (*)(void*)>& __b, _Tp*& __n, _Tp*& __e) { + bool __owns = __b.get_deleter() != __do_nothing; + size_t __cur_cap = static_cast(__e - __b.get()) * sizeof(_Tp); + size_t __new_cap = __cur_cap < numeric_limits::max() / 2 ? 2 * __cur_cap : numeric_limits::max(); + if (__new_cap == 0) + __new_cap = sizeof(_Tp); + size_t __n_off = static_cast(__n - __b.get()); + _Tp* __t = (_Tp*)std::realloc(__owns ? __b.get() : 0, __new_cap); + if (__t == 0) + std::__throw_bad_alloc(); + if (__owns) + __b.release(); + else + std::memcpy(__t, __b.get(), __cur_cap); + __b = unique_ptr<_Tp, void (*)(void*)>(__t, free); + __new_cap /= sizeof(_Tp); + __n = __b.get() + __n_off; + __e = __b.get() + __new_cap; +} + +// true == success +template +bool money_get<_CharT, _InputIterator>::__do_get( + iter_type& __b, + iter_type __e, + bool __intl, + const locale& __loc, + ios_base::fmtflags __flags, + ios_base::iostate& __err, + bool& __neg, + const ctype& __ct, + unique_ptr& __wb, + char_type*& __wn, + char_type* __we) { + if (__b == __e) { + __err |= ios_base::failbit; + return false; + } + const unsigned __bz = 100; + unsigned __gbuf[__bz]; + unique_ptr __gb(__gbuf, __do_nothing); + unsigned* __gn = __gb.get(); + unsigned* __ge = __gn + __bz; + money_base::pattern __pat; + char_type __dp; + char_type __ts; + string __grp; + string_type __sym; + string_type __psn; + string_type __nsn; + // Capture the spaces read into money_base::{space,none} so they + // can be compared to initial spaces in __sym. + string_type __spaces; + int __fd; + __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp, __sym, __psn, __nsn, __fd); + const string_type* __trailing_sign = 0; + __wn = __wb.get(); + for (unsigned __p = 0; __p < 4 && __b != __e; ++__p) { + switch (__pat.field[__p]) { + case money_base::space: + if (__p != 3) { + if (__ct.is(ctype_base::space, *__b)) + __spaces.push_back(*__b++); + else { + __err |= ios_base::failbit; + return false; + } + } + [[__fallthrough__]]; + case money_base::none: + if (__p != 3) { + while (__b != __e && __ct.is(ctype_base::space, *__b)) + __spaces.push_back(*__b++); + } + break; + case money_base::sign: + if (__psn.size() > 0 && *__b == __psn[0]) { + ++__b; + __neg = false; + if (__psn.size() > 1) + __trailing_sign = std::addressof(__psn); + break; + } + if (__nsn.size() > 0 && *__b == __nsn[0]) { + ++__b; + __neg = true; + if (__nsn.size() > 1) + __trailing_sign = std::addressof(__nsn); + break; + } + if (__psn.size() > 0 && __nsn.size() > 0) { // sign is required + __err |= ios_base::failbit; + return false; + } + if (__psn.size() == 0 && __nsn.size() == 0) + // locale has no way of specifying a sign. Use the initial value of __neg as a default + break; + __neg = (__nsn.size() == 0); + break; + case money_base::symbol: { + bool __more_needed = + __trailing_sign || (__p < 2) || (__p == 2 && __pat.field[3] != static_cast(money_base::none)); + bool __sb = (__flags & ios_base::showbase) != 0; + if (__sb || __more_needed) { + typename string_type::const_iterator __sym_space_end = __sym.begin(); + if (__p > 0 && (__pat.field[__p - 1] == money_base::none || __pat.field[__p - 1] == money_base::space)) { + // Match spaces we've already read against spaces at + // the beginning of __sym. + while (__sym_space_end != __sym.end() && __ct.is(ctype_base::space, *__sym_space_end)) + ++__sym_space_end; + const size_t __num_spaces = __sym_space_end - __sym.begin(); + if (__num_spaces > __spaces.size() || + !std::equal(__spaces.end() - __num_spaces, __spaces.end(), __sym.begin())) { + // No match. Put __sym_space_end back at the + // beginning of __sym, which will prevent a + // match in the next loop. + __sym_space_end = __sym.begin(); + } + } + typename string_type::const_iterator __sym_curr_char = __sym_space_end; + while (__sym_curr_char != __sym.end() && __b != __e && *__b == *__sym_curr_char) { + ++__b; + ++__sym_curr_char; + } + if (__sb && __sym_curr_char != __sym.end()) { + __err |= ios_base::failbit; + return false; + } + } + } break; + case money_base::value: { + unsigned __ng = 0; + for (; __b != __e; ++__b) { + char_type __c = *__b; + if (__ct.is(ctype_base::digit, __c)) { + if (__wn == __we) + std::__double_or_nothing(__wb, __wn, __we); + *__wn++ = __c; + ++__ng; + } else if (__grp.size() > 0 && __ng > 0 && __c == __ts) { + if (__gn == __ge) + std::__double_or_nothing(__gb, __gn, __ge); + *__gn++ = __ng; + __ng = 0; + } else + break; + } + if (__gb.get() != __gn && __ng > 0) { + if (__gn == __ge) + std::__double_or_nothing(__gb, __gn, __ge); + *__gn++ = __ng; + } + if (__fd > 0) { + if (__b == __e || *__b != __dp) { + __err |= ios_base::failbit; + return false; + } + for (++__b; __fd > 0; --__fd, ++__b) { + if (__b == __e || !__ct.is(ctype_base::digit, *__b)) { + __err |= ios_base::failbit; + return false; + } + if (__wn == __we) + std::__double_or_nothing(__wb, __wn, __we); + *__wn++ = *__b; + } + } + if (__wn == __wb.get()) { + __err |= ios_base::failbit; + return false; + } + } break; + } + } + if (__trailing_sign) { + for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b) { + if (__b == __e || *__b != (*__trailing_sign)[__i]) { + __err |= ios_base::failbit; + return false; + } + } + } + if (__gb.get() != __gn) { + ios_base::iostate __et = ios_base::goodbit; + __check_grouping(__grp, __gb.get(), __gn, __et); + if (__et) { + __err |= ios_base::failbit; + return false; + } + } + return true; +} + +template +_InputIterator money_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + const int __bz = 100; + char_type __wbuf[__bz]; + unique_ptr __wb(__wbuf, __do_nothing); + char_type* __wn; + char_type* __we = __wbuf + __bz; + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + bool __neg = false; + if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) { + const char __src[] = "0123456789"; + char_type __atoms[sizeof(__src) - 1]; + __ct.widen(__src, __src + (sizeof(__src) - 1), __atoms); + char __nbuf[__bz]; + char* __nc = __nbuf; + const char* __nc_in = __nc; + unique_ptr __h(nullptr, free); + if (__wn - __wb.get() > __bz - 2) { + __h.reset((char*)malloc(static_cast(__wn - __wb.get() + 2))); + if (__h.get() == nullptr) + std::__throw_bad_alloc(); + __nc = __h.get(); + __nc_in = __nc; + } + if (__neg) + *__nc++ = '-'; + for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc) + *__nc = __src[std::find(__atoms, std::end(__atoms), *__w) - __atoms]; + *__nc = char(); + if (sscanf(__nc_in, "%Lf", &__v) != 1) + std::__throw_runtime_error("money_get error"); + } + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +template +_InputIterator money_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const { + const int __bz = 100; + char_type __wbuf[__bz]; + unique_ptr __wb(__wbuf, __do_nothing); + char_type* __wn; + char_type* __we = __wbuf + __bz; + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + bool __neg = false; + if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) { + __v.clear(); + if (__neg) + __v.push_back(__ct.widen('-')); + char_type __z = __ct.widen('0'); + char_type* __w; + for (__w = __wb.get(); __w < __wn - 1; ++__w) + if (*__w != __z) + break; + __v.append(__w, __wn); + } + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get; +# endif + +// money_put + +template +class __money_put { +protected: + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI __money_put() {} + + static void __gather_info( + bool __intl, + bool __neg, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __sn, + int& __fd); + static void __format( + char_type* __mb, + char_type*& __mi, + char_type*& __me, + ios_base::fmtflags __flags, + const char_type* __db, + const char_type* __de, + const ctype& __ct, + bool __neg, + const money_base::pattern& __pat, + char_type __dp, + char_type __ts, + const string& __grp, + const string_type& __sym, + const string_type& __sn, + int __fd); +}; + +template +void __money_put<_CharT>::__gather_info( + bool __intl, + bool __neg, + const locale& __loc, + money_base::pattern& __pat, + char_type& __dp, + char_type& __ts, + string& __grp, + string_type& __sym, + string_type& __sn, + int& __fd) { + if (__intl) { + const moneypunct& __mp = std::use_facet >(__loc); + if (__neg) { + __pat = __mp.neg_format(); + __sn = __mp.negative_sign(); + } else { + __pat = __mp.pos_format(); + __sn = __mp.positive_sign(); + } + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } else { + const moneypunct& __mp = std::use_facet >(__loc); + if (__neg) { + __pat = __mp.neg_format(); + __sn = __mp.negative_sign(); + } else { + __pat = __mp.pos_format(); + __sn = __mp.positive_sign(); + } + __dp = __mp.decimal_point(); + __ts = __mp.thousands_sep(); + __grp = __mp.grouping(); + __sym = __mp.curr_symbol(); + __fd = __mp.frac_digits(); + } +} + +template +void __money_put<_CharT>::__format( + char_type* __mb, + char_type*& __mi, + char_type*& __me, + ios_base::fmtflags __flags, + const char_type* __db, + const char_type* __de, + const ctype& __ct, + bool __neg, + const money_base::pattern& __pat, + char_type __dp, + char_type __ts, + const string& __grp, + const string_type& __sym, + const string_type& __sn, + int __fd) { + __me = __mb; + for (char __p : __pat.field) { + switch (__p) { + case money_base::none: + __mi = __me; + break; + case money_base::space: + __mi = __me; + *__me++ = __ct.widen(' '); + break; + case money_base::sign: + if (!__sn.empty()) + *__me++ = __sn[0]; + break; + case money_base::symbol: + if (!__sym.empty() && (__flags & ios_base::showbase)) + __me = std::copy(__sym.begin(), __sym.end(), __me); + break; + case money_base::value: { + // remember start of value so we can reverse it + char_type* __t = __me; + // find beginning of digits + if (__neg) + ++__db; + // find end of digits + const char_type* __d; + for (__d = __db; __d < __de; ++__d) + if (!__ct.is(ctype_base::digit, *__d)) + break; + // print fractional part + if (__fd > 0) { + int __f; + for (__f = __fd; __d > __db && __f > 0; --__f) + *__me++ = *--__d; + char_type __z = __f > 0 ? __ct.widen('0') : char_type(); + for (; __f > 0; --__f) + *__me++ = __z; + *__me++ = __dp; + } + // print units part + if (__d == __db) { + *__me++ = __ct.widen('0'); + } else { + unsigned __ng = 0; + unsigned __ig = 0; + unsigned __gl = __grp.empty() ? numeric_limits::max() : static_cast(__grp[__ig]); + while (__d != __db) { + if (__ng == __gl) { + *__me++ = __ts; + __ng = 0; + if (++__ig < __grp.size()) + __gl = __grp[__ig] == numeric_limits::max() + ? numeric_limits::max() + : static_cast(__grp[__ig]); + } + *__me++ = *--__d; + ++__ng; + } + } + // reverse it + std::reverse(__t, __me); + } break; + } + } + // print rest of sign, if any + if (__sn.size() > 1) + __me = std::copy(__sn.begin() + 1, __sn.end(), __me); + // set alignment + if ((__flags & ios_base::adjustfield) == ios_base::left) + __mi = __me; + else if ((__flags & ios_base::adjustfield) != ios_base::internal) + __mi = __mb; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put; +# endif + +template > +class money_put : public locale::facet, private __money_put<_CharT> { +public: + typedef _CharT char_type; + typedef _OutputIterator iter_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit money_put(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type + put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const { + return do_put(__s, __intl, __iob, __fl, __units); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const { + return do_put(__s, __intl, __iob, __fl, __digits); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_put() override {} + + virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const; + virtual iter_type + do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const; +}; + +template +locale::id money_put<_CharT, _OutputIterator>::id; + +template +_OutputIterator money_put<_CharT, _OutputIterator>::do_put( + iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const { + // convert to char + const size_t __bs = 100; + char __buf[__bs]; + char* __bb = __buf; + char_type __digits[__bs]; + char_type* __db = __digits; + int __n = snprintf(__bb, __bs, "%.0Lf", __units); + unique_ptr __hn(nullptr, free); + unique_ptr __hd(0, free); + // secure memory for digit storage + if (static_cast(__n) > __bs - 1) { + __n = __locale::__asprintf(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units); + if (__n == -1) + std::__throw_bad_alloc(); + __hn.reset(__bb); + __hd.reset((char_type*)malloc(static_cast(__n) * sizeof(char_type))); + if (__hd == nullptr) + std::__throw_bad_alloc(); + __db = __hd.get(); + } + // gather info + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + __ct.widen(__bb, __bb + __n, __db); + bool __neg = __n > 0 && __bb[0] == '-'; + money_base::pattern __pat; + char_type __dp; + char_type __ts; + string __grp; + string_type __sym; + string_type __sn; + int __fd; + this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd); + // secure memory for formatting + char_type __mbuf[__bs]; + char_type* __mb = __mbuf; + unique_ptr __hw(0, free); + size_t __exn = __n > __fd ? (static_cast(__n) - static_cast(__fd)) * 2 + __sn.size() + __sym.size() + + static_cast(__fd) + 1 + : __sn.size() + __sym.size() + static_cast(__fd) + 2; + if (__exn > __bs) { + __hw.reset((char_type*)malloc(__exn * sizeof(char_type))); + __mb = __hw.get(); + if (__mb == 0) + std::__throw_bad_alloc(); + } + // format + char_type* __mi; + char_type* __me; + this->__format( + __mb, __mi, __me, __iob.flags(), __db, __db + __n, __ct, __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd); + return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl); +} + +template +_OutputIterator money_put<_CharT, _OutputIterator>::do_put( + iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const { + // gather info + locale __loc = __iob.getloc(); + const ctype& __ct = std::use_facet >(__loc); + bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-'); + money_base::pattern __pat; + char_type __dp; + char_type __ts; + string __grp; + string_type __sym; + string_type __sn; + int __fd; + this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd); + // secure memory for formatting + char_type __mbuf[100]; + char_type* __mb = __mbuf; + unique_ptr __h(0, free); + size_t __exn = + static_cast(__digits.size()) > __fd + ? (__digits.size() - static_cast(__fd)) * 2 + __sn.size() + __sym.size() + static_cast(__fd) + + 1 + : __sn.size() + __sym.size() + static_cast(__fd) + 2; + if (__exn > 100) { + __h.reset((char_type*)malloc(__exn * sizeof(char_type))); + __mb = __h.get(); + if (__mb == 0) + std::__throw_bad_alloc(); + } + // format + char_type* __mi; + char_type* __me; + this->__format( + __mb, + __mi, + __me, + __iob.flags(), + __digits.data(), + __digits.data() + __digits.size(), + __ct, + __neg, + __pat, + __dp, + __ts, + __grp, + __sym, + __sn, + __fd); + return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl); +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put; +# endif + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_MONEY_H diff --git a/libcxx/include/__locale_dir/num.h b/libcxx/include/__locale_dir/num.h new file mode 100644 index 0000000000000..7ca8ffe348959 --- /dev/null +++ b/libcxx/include/__locale_dir/num.h @@ -0,0 +1,1072 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_NUM_H +#define _LIBCPP___LOCALE_DIR_NUM_H + +#include <__algorithm/find.h> +#include <__algorithm/reverse.h> +#include <__charconv/to_chars_integral.h> +#include <__charconv/traits.h> +#include <__config> +#include <__iterator/istreambuf_iterator.h> +#include <__iterator/ostreambuf_iterator.h> +#include <__locale_dir/check_grouping.h> +#include <__locale_dir/get_c_locale.h> +#include <__locale_dir/pad_and_output.h> +#include <__locale_dir/scan_keyword.h> +#include <__memory/unique_ptr.h> +#include <__system_error/errc.h> +#include +#include +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +// TODO: Properly qualify calls now that the locale base API defines functions instead of macros +// NOLINTBEGIN(libcpp-robust-against-adl) + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct _LIBCPP_EXPORTED_FROM_ABI __num_get_base { + static const int __num_get_buf_sz = 40; + + static int __get_base(ios_base&); + static const char __src[33]; // "0123456789abcdefABCDEFxX+-pPiInN" + // count of leading characters in __src used for parsing integers ("012..X+-") + static const size_t __int_chr_cnt = 26; + // count of leading characters in __src used for parsing floating-point values ("012..-pP") + static const size_t __fp_chr_cnt = 28; +}; + +template +struct __num_get : protected __num_get_base { + static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep); + + static int __stage2_float_loop( + _CharT __ct, + bool& __in_units, + char& __exp, + char* __a, + char*& __a_end, + _CharT __decimal_point, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + unsigned& __dc, + _CharT* __atoms); + + [[__deprecated__("This exists only for ABI compatibility")]] static string + __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep); + static int __stage2_int_loop( + _CharT __ct, + int __base, + char* __a, + char*& __a_end, + unsigned& __dc, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + _CharT* __atoms); + + _LIBCPP_HIDE_FROM_ABI static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) { + locale __loc = __iob.getloc(); + const numpunct<_CharT>& __np = use_facet >(__loc); + __thousands_sep = __np.thousands_sep(); + return __np.grouping(); + } + + _LIBCPP_HIDE_FROM_ABI const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const { + return __do_widen_p(__iob, __atoms); + } + +private: + template + _LIBCPP_HIDE_FROM_ABI const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const { + locale __loc = __iob.getloc(); + use_facet >(__loc).widen(__src, __src + __int_chr_cnt, __atoms); + return __atoms; + } + + _LIBCPP_HIDE_FROM_ABI const char* __do_widen_p(ios_base& __iob, char* __atoms) const { + (void)__iob; + (void)__atoms; + return __src; + } +}; + +template +string __num_get<_CharT>::__stage2_float_prep( + ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep) { + locale __loc = __iob.getloc(); + std::use_facet >(__loc).widen(__src, __src + __fp_chr_cnt, __atoms); + const numpunct<_CharT>& __np = std::use_facet >(__loc); + __decimal_point = __np.decimal_point(); + __thousands_sep = __np.thousands_sep(); + return __np.grouping(); +} + +template +int __num_get<_CharT>::__stage2_int_loop( + _CharT __ct, + int __base, + char* __a, + char*& __a_end, + unsigned& __dc, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + _CharT* __atoms) { + if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25])) { + *__a_end++ = __ct == __atoms[24] ? '+' : '-'; + __dc = 0; + return 0; + } + if (__grouping.size() != 0 && __ct == __thousands_sep) { + if (__g_end - __g < __num_get_buf_sz) { + *__g_end++ = __dc; + __dc = 0; + } + return 0; + } + ptrdiff_t __f = std::find(__atoms, __atoms + __int_chr_cnt, __ct) - __atoms; + if (__f >= 24) + return -1; + switch (__base) { + case 8: + case 10: + if (__f >= __base) + return -1; + break; + case 16: + if (__f < 22) + break; + if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0') { + __dc = 0; + *__a_end++ = __src[__f]; + return 0; + } + return -1; + } + *__a_end++ = __src[__f]; + ++__dc; + return 0; +} + +template +int __num_get<_CharT>::__stage2_float_loop( + _CharT __ct, + bool& __in_units, + char& __exp, + char* __a, + char*& __a_end, + _CharT __decimal_point, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + unsigned& __dc, + _CharT* __atoms) { + if (__ct == __decimal_point) { + if (!__in_units) + return -1; + __in_units = false; + *__a_end++ = '.'; + if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz) + *__g_end++ = __dc; + return 0; + } + if (__ct == __thousands_sep && __grouping.size() != 0) { + if (!__in_units) + return -1; + if (__g_end - __g < __num_get_buf_sz) { + *__g_end++ = __dc; + __dc = 0; + } + return 0; + } + ptrdiff_t __f = std::find(__atoms, __atoms + __num_get_base::__fp_chr_cnt, __ct) - __atoms; + if (__f >= static_cast(__num_get_base::__fp_chr_cnt)) + return -1; + char __x = __src[__f]; + if (__x == '-' || __x == '+') { + if (__a_end == __a || (std::toupper(__a_end[-1]) == std::toupper(__exp))) { + *__a_end++ = __x; + return 0; + } + return -1; + } + if (__x == 'x' || __x == 'X') + __exp = 'P'; + else if (std::toupper(__x) == __exp) { + __exp = std::tolower(__exp); + if (__in_units) { + __in_units = false; + if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz) + *__g_end++ = __dc; + } + } + *__a_end++ = __x; + if (__f >= 22) + return 0; + ++__dc; + return 0; +} + +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get; +# endif + +template +_LIBCPP_HIDE_FROM_ABI _Tp __do_strtod(const char* __a, char** __p2); + +template <> +inline _LIBCPP_HIDE_FROM_ABI float __do_strtod(const char* __a, char** __p2) { + return __locale::__strtof(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template <> +inline _LIBCPP_HIDE_FROM_ABI double __do_strtod(const char* __a, char** __p2) { + return __locale::__strtod(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template <> +inline _LIBCPP_HIDE_FROM_ABI long double __do_strtod(const char* __a, char** __p2) { + return __locale::__strtold(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) { + if (__a != __a_end) { + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + _Tp __ld = std::__do_strtod<_Tp>(__a, &__p2); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE) + __err = ios_base::failbit; + return __ld; + } + __err = ios_base::failbit; + return 0; +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp +__num_get_signed_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { + if (__a != __a_end) { + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + long long __ll = __locale::__strtoll(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE || __ll < numeric_limits<_Tp>::min() || numeric_limits<_Tp>::max() < __ll) { + __err = ios_base::failbit; + if (__ll > 0) + return numeric_limits<_Tp>::max(); + else + return numeric_limits<_Tp>::min(); + } + return static_cast<_Tp>(__ll); + } + __err = ios_base::failbit; + return 0; +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp +__num_get_unsigned_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { + if (__a != __a_end) { + const bool __negate = *__a == '-'; + if (__negate && ++__a == __a_end) { + __err = ios_base::failbit; + return 0; + } + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + unsigned long long __ll = __locale::__strtoull(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll) { + __err = ios_base::failbit; + return numeric_limits<_Tp>::max(); + } + _Tp __res = static_cast<_Tp>(__ll); + if (__negate) + __res = -__res; + return __res; + } + __err = ios_base::failbit; + return 0; +} + +template > +class num_get : public locale::facet, private __num_get<_CharT> { +public: + typedef _CharT char_type; + typedef _InputIterator iter_type; + + _LIBCPP_HIDE_FROM_ABI explicit num_get(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { + return do_get(__b, __e, __iob, __err, __v); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_get() override {} + + template + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_floating_point(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const { + // Stage 1, nothing to do + // Stage 2 + char_type __atoms[__num_get_base::__fp_chr_cnt]; + char_type __decimal_point; + char_type __thousands_sep; + string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + bool __in_units = true; + char __exp = 'E'; + bool __is_leading_parsed = false; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_float_loop( + *__b, + __in_units, + __exp, + __a, + __a_end, + __decimal_point, + __thousands_sep, + __grouping, + __g, + __g_end, + __dc, + __atoms)) + break; + + // the leading character excluding the sign must be a decimal digit + if (!__is_leading_parsed) { + if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') { + if (('0' <= __a[0] && __a[0] <= '9') || __a[0] == '.') + __is_leading_parsed = true; + else + break; + } else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) { + if (('0' <= __a[1] && __a[1] <= '9') || __a[1] == '.') + __is_leading_parsed = true; + else + break; + } + } + } + if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_float<_Fp>(__a, __a_end, __err); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } + + template + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_signed(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const { + // Stage 1 + int __base = this->__get_base(__iob); + // Stage 2 + char_type __thousands_sep; + const int __atoms_size = __num_get_base::__int_chr_cnt; + char_type __atoms1[__atoms_size]; + const char_type* __atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_int_loop( + *__b, + __base, + __a, + __a_end, + __dc, + __thousands_sep, + __grouping, + __g, + __g_end, + const_cast(__atoms))) + break; + } + if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } + + template + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_unsigned(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const { + // Stage 1 + int __base = this->__get_base(__iob); + // Stage 2 + char_type __thousands_sep; + const int __atoms_size = __num_get_base::__int_chr_cnt; + char_type __atoms1[__atoms_size]; + const char_type* __atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_int_loop( + *__b, + __base, + __a, + __a_end, + __dc, + __thousands_sep, + __grouping, + __g, + __g_end, + const_cast(__atoms))) + break; + } + if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const; + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const { + return this->__do_get_signed(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const { + return this->__do_get_signed(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const { + return this->__do_get_unsigned(__b, __e, __iob, __err, __v); + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const { + return this->__do_get_floating_point(__b, __e, __iob, __err, __v); + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const { + return this->__do_get_floating_point(__b, __e, __iob, __err, __v); + } + + virtual iter_type + do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { + return this->__do_get_floating_point(__b, __e, __iob, __err, __v); + } + + virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const; +}; + +template +locale::id num_get<_CharT, _InputIterator>::id; + +template +_InputIterator num_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { + if ((__iob.flags() & ios_base::boolalpha) == 0) { + long __lv = -1; + __b = do_get(__b, __e, __iob, __err, __lv); + switch (__lv) { + case 0: + __v = false; + break; + case 1: + __v = true; + break; + default: + __v = true; + __err = ios_base::failbit; + break; + } + return __b; + } + const ctype<_CharT>& __ct = std::use_facet >(__iob.getloc()); + const numpunct<_CharT>& __np = std::use_facet >(__iob.getloc()); + typedef typename numpunct<_CharT>::string_type string_type; + const string_type __names[2] = {__np.truename(), __np.falsename()}; + const string_type* __i = std::__scan_keyword(__b, __e, __names, __names + 2, __ct, __err); + __v = __i == __names; + return __b; +} + +template +_InputIterator num_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { + // Stage 1 + int __base = 16; + // Stage 2 + char_type __atoms[__num_get_base::__int_chr_cnt]; + char_type __thousands_sep = char_type(); + string __grouping; + std::use_facet >(__iob.getloc()) + .widen(__num_get_base::__src, __num_get_base::__src + __num_get_base::__int_chr_cnt, __atoms); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, __thousands_sep, __grouping, __g, __g_end, __atoms)) + break; + } + // Stage 3 + __buf.resize(__a_end - __a); + if (__locale::__sscanf(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1) + __err = ios_base::failbit; + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get; +# endif + +struct _LIBCPP_EXPORTED_FROM_ABI __num_put_base { +protected: + static void __format_int(char* __fmt, const char* __len, bool __signd, ios_base::fmtflags __flags); + static bool __format_float(char* __fmt, const char* __len, ios_base::fmtflags __flags); + static char* __identify_padding(char* __nb, char* __ne, const ios_base& __iob); +}; + +template +struct __num_put : protected __num_put_base { + static void __widen_and_group_int( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc); + static void __widen_and_group_float( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc); +}; + +template +void __num_put<_CharT>::__widen_and_group_int( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) { + const ctype<_CharT>& __ct = std::use_facet >(__loc); + const numpunct<_CharT>& __npt = std::use_facet >(__loc); + string __grouping = __npt.grouping(); + if (__grouping.empty()) { + __ct.widen(__nb, __ne, __ob); + __oe = __ob + (__ne - __nb); + } else { + __oe = __ob; + char* __nf = __nb; + if (*__nf == '-' || *__nf == '+') + *__oe++ = __ct.widen(*__nf++); + if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) { + *__oe++ = __ct.widen(*__nf++); + *__oe++ = __ct.widen(*__nf++); + } + std::reverse(__nf, __ne); + _CharT __thousands_sep = __npt.thousands_sep(); + unsigned __dc = 0; + unsigned __dg = 0; + for (char* __p = __nf; __p < __ne; ++__p) { + if (static_cast(__grouping[__dg]) > 0 && __dc == static_cast(__grouping[__dg])) { + *__oe++ = __thousands_sep; + __dc = 0; + if (__dg < __grouping.size() - 1) + ++__dg; + } + *__oe++ = __ct.widen(*__p); + ++__dc; + } + std::reverse(__ob + (__nf - __nb), __oe); + } + if (__np == __ne) + __op = __oe; + else + __op = __ob + (__np - __nb); +} + +template +void __num_put<_CharT>::__widen_and_group_float( + char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) { + const ctype<_CharT>& __ct = std::use_facet >(__loc); + const numpunct<_CharT>& __npt = std::use_facet >(__loc); + string __grouping = __npt.grouping(); + __oe = __ob; + char* __nf = __nb; + if (*__nf == '-' || *__nf == '+') + *__oe++ = __ct.widen(*__nf++); + char* __ns; + if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) { + *__oe++ = __ct.widen(*__nf++); + *__oe++ = __ct.widen(*__nf++); + for (__ns = __nf; __ns < __ne; ++__ns) + if (!__locale::__isxdigit(*__ns, _LIBCPP_GET_C_LOCALE)) + break; + } else { + for (__ns = __nf; __ns < __ne; ++__ns) + if (!__locale::__isdigit(*__ns, _LIBCPP_GET_C_LOCALE)) + break; + } + if (__grouping.empty()) { + __ct.widen(__nf, __ns, __oe); + __oe += __ns - __nf; + } else { + std::reverse(__nf, __ns); + _CharT __thousands_sep = __npt.thousands_sep(); + unsigned __dc = 0; + unsigned __dg = 0; + for (char* __p = __nf; __p < __ns; ++__p) { + if (__grouping[__dg] > 0 && __dc == static_cast(__grouping[__dg])) { + *__oe++ = __thousands_sep; + __dc = 0; + if (__dg < __grouping.size() - 1) + ++__dg; + } + *__oe++ = __ct.widen(*__p); + ++__dc; + } + std::reverse(__ob + (__nf - __nb), __oe); + } + for (__nf = __ns; __nf < __ne; ++__nf) { + if (*__nf == '.') { + *__oe++ = __npt.decimal_point(); + ++__nf; + break; + } else + *__oe++ = __ct.widen(*__nf); + } + __ct.widen(__nf, __ne, __oe); + __oe += __ne - __nf; + if (__np == __ne) + __op = __oe; + else + __op = __ob + (__np - __nb); +} + +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put; +# endif + +template > +class num_put : public locale::facet, private __num_put<_CharT> { +public: + typedef _CharT char_type; + typedef _OutputIterator iter_type; + + _LIBCPP_HIDE_FROM_ABI explicit num_put(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { + return do_put(__s, __iob, __fl, __v); + } + + _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const { + return do_put(__s, __iob, __fl, __v); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_put() override {} + + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const; + virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const; + + template + _LIBCPP_HIDE_FROM_ABI inline _OutputIterator + __do_put_integral(iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const; + + template + _LIBCPP_HIDE_FROM_ABI inline _OutputIterator + __do_put_floating_point(iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const; +}; + +template +locale::id num_put<_CharT, _OutputIterator>::id; + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { + if ((__iob.flags() & ios_base::boolalpha) == 0) + return do_put(__s, __iob, __fl, (unsigned long)__v); + const numpunct& __np = std::use_facet >(__iob.getloc()); + typedef typename numpunct::string_type string_type; + string_type __nm = __v ? __np.truename() : __np.falsename(); + for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s) + *__s = *__i; + return __s; +} + +template +template +_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_integral( + iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const { + // Stage 1 - Get number in narrow char + + // Worst case is octal, with showbase enabled. Note that octal is always + // printed as an unsigned value. + using _Unsigned = typename make_unsigned<_Integral>::type; + _LIBCPP_CONSTEXPR const unsigned __buffer_size = + (numeric_limits<_Unsigned>::digits / 3) // 1 char per 3 bits + + ((numeric_limits<_Unsigned>::digits % 3) != 0) // round up + + 2; // base prefix + terminating null character + + char __char_buffer[__buffer_size]; + char* __buffer_ptr = __char_buffer; + + auto __flags = __iob.flags(); + + auto __basefield = (__flags & ios_base::basefield); + + // Extract base + int __base = 10; + if (__basefield == ios_base::oct) + __base = 8; + else if (__basefield == ios_base::hex) + __base = 16; + + // Print '-' and make the argument unsigned + auto __uval = std::__to_unsigned_like(__v); + if (__basefield != ios_base::oct && __basefield != ios_base::hex && __v < 0) { + *__buffer_ptr++ = '-'; + __uval = std::__complement(__uval); + } + + // Maybe add '+' prefix + if (std::is_signed<_Integral>::value && (__flags & ios_base::showpos) && __basefield != ios_base::oct && + __basefield != ios_base::hex && __v >= 0) + *__buffer_ptr++ = '+'; + + // Add base prefix + if (__v != 0 && __flags & ios_base::showbase) { + if (__basefield == ios_base::oct) { + *__buffer_ptr++ = '0'; + } else if (__basefield == ios_base::hex) { + *__buffer_ptr++ = '0'; + *__buffer_ptr++ = (__flags & ios_base::uppercase ? 'X' : 'x'); + } + } + + auto __res = std::__to_chars_integral(__buffer_ptr, __char_buffer + __buffer_size, __uval, __base); + _LIBCPP_ASSERT_INTERNAL(__res.__ec == std::errc(0), "to_chars: invalid maximum buffer size computed?"); + + // Make letters uppercase + if (__flags & ios_base::hex && __flags & ios_base::uppercase) { + for (; __buffer_ptr != __res.__ptr; ++__buffer_ptr) + *__buffer_ptr = std::__hex_to_upper(*__buffer_ptr); + } + + char* __np = this->__identify_padding(__char_buffer, __res.__ptr, __iob); + // Stage 2 - Widen __nar while adding thousands separators + char_type __o[2 * (__buffer_size - 1) - 1]; + char_type* __op; // pad here + char_type* __oe; // end of output + this->__widen_and_group_int(__char_buffer, __np, __res.__ptr, __o, __op, __oe, __iob.getloc()); + // [__o, __oe) contains thousands_sep'd wide number + // Stage 3 & 4 + return std::__pad_and_output(__s, __o, __op, __oe, __iob, __fl); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { + return this->__do_put_integral(__s, __iob, __fl, __v); +} + +template +template +_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_floating_point( + iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const { + // Stage 1 - Get number in narrow char + char __fmt[8] = {'%', 0}; + bool __specify_precision = this->__format_float(__fmt + 1, __len, __iob.flags()); + const unsigned __nbuf = 30; + char __nar[__nbuf]; + char* __nb = __nar; + int __nc; + _LIBCPP_DIAGNOSTIC_PUSH + _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") + _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") + if (__specify_precision) + __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v); + else + __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v); + unique_ptr __nbh(nullptr, free); + if (__nc > static_cast(__nbuf - 1)) { + if (__specify_precision) + __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v); + else + __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v); + if (__nc == -1) + std::__throw_bad_alloc(); + __nbh.reset(__nb); + } + _LIBCPP_DIAGNOSTIC_POP + char* __ne = __nb + __nc; + char* __np = this->__identify_padding(__nb, __ne, __iob); + // Stage 2 - Widen __nar while adding thousands separators + char_type __o[2 * (__nbuf - 1) - 1]; + char_type* __ob = __o; + unique_ptr __obh(0, free); + if (__nb != __nar) { + __ob = (char_type*)malloc(2 * static_cast(__nc) * sizeof(char_type)); + if (__ob == 0) + std::__throw_bad_alloc(); + __obh.reset(__ob); + } + char_type* __op; // pad here + char_type* __oe; // end of output + this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc()); + // [__o, __oe) contains thousands_sep'd wide number + // Stage 3 & 4 + __s = std::__pad_and_output(__s, __ob, __op, __oe, __iob, __fl); + return __s; +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const { + return this->__do_put_floating_point(__s, __iob, __fl, __v, ""); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { + return this->__do_put_floating_point(__s, __iob, __fl, __v, "L"); +} + +template +_OutputIterator +num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const { + auto __flags = __iob.flags(); + __iob.flags((__flags & ~ios_base::basefield & ~ios_base::uppercase) | ios_base::hex | ios_base::showbase); + auto __res = __do_put_integral(__s, __iob, __fl, reinterpret_cast(__v)); + __iob.flags(__flags); + return __res; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put; +# endif + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +// NOLINTEND(libcpp-robust-against-adl) + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_NUM_H diff --git a/libcxx/include/__locale_dir/scan_keyword.h b/libcxx/include/__locale_dir/scan_keyword.h new file mode 100644 index 0000000000000..78dd0a46a8ee1 --- /dev/null +++ b/libcxx/include/__locale_dir/scan_keyword.h @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_SCAN_KEYWORD_H +#define _LIBCPP___LOCALE_DIR_SCAN_KEYWORD_H + +#include <__config> +#include <__memory/unique_ptr.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// __scan_keyword +// Scans [__b, __e) until a match is found in the basic_strings range +// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke). +// __b will be incremented (visibly), consuming CharT until a match is found +// or proved to not exist. A keyword may be "", in which will match anything. +// If one keyword is a prefix of another, and the next CharT in the input +// might match another keyword, the algorithm will attempt to find the longest +// matching keyword. If the longer matching keyword ends up not matching, then +// no keyword match is found. If no keyword match is found, __ke is returned +// and failbit is set in __err. +// Else an iterator pointing to the matching keyword is found. If more than +// one keyword matches, an iterator to the first matching keyword is returned. +// If on exit __b == __e, eofbit is set in __err. If __case_sensitive is false, +// __ct is used to force to lower case before comparing characters. +// Examples: +// Keywords: "a", "abb" +// If the input is "a", the first keyword matches and eofbit is set. +// If the input is "abc", no match is found and "ab" are consumed. +template +_LIBCPP_HIDE_FROM_ABI _ForwardIterator __scan_keyword( + _InputIterator& __b, + _InputIterator __e, + _ForwardIterator __kb, + _ForwardIterator __ke, + const _Ctype& __ct, + ios_base::iostate& __err, + bool __case_sensitive = true) { + typedef typename iterator_traits<_InputIterator>::value_type _CharT; + size_t __nkw = static_cast(std::distance(__kb, __ke)); + const unsigned char __doesnt_match = '\0'; + const unsigned char __might_match = '\1'; + const unsigned char __does_match = '\2'; + unsigned char __statbuf[100]; + unsigned char* __status = __statbuf; + unique_ptr __stat_hold(nullptr, free); + if (__nkw > sizeof(__statbuf)) { + __status = (unsigned char*)malloc(__nkw); + if (__status == nullptr) + std::__throw_bad_alloc(); + __stat_hold.reset(__status); + } + size_t __n_might_match = __nkw; // At this point, any keyword might match + size_t __n_does_match = 0; // but none of them definitely do + // Initialize all statuses to __might_match, except for "" keywords are __does_match + unsigned char* __st = __status; + for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { + if (!__ky->empty()) + *__st = __might_match; + else { + *__st = __does_match; + --__n_might_match; + ++__n_does_match; + } + } + // While there might be a match, test keywords against the next CharT + for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx) { + // Peek at the next CharT but don't consume it + _CharT __c = *__b; + if (!__case_sensitive) + __c = __ct.toupper(__c); + bool __consume = false; + // For each keyword which might match, see if the __indx character is __c + // If a match if found, consume __c + // If a match is found, and that is the last character in the keyword, + // then that keyword matches. + // If the keyword doesn't match this character, then change the keyword + // to doesn't match + __st = __status; + for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { + if (*__st == __might_match) { + _CharT __kc = (*__ky)[__indx]; + if (!__case_sensitive) + __kc = __ct.toupper(__kc); + if (__c == __kc) { + __consume = true; + if (__ky->size() == __indx + 1) { + *__st = __does_match; + --__n_might_match; + ++__n_does_match; + } + } else { + *__st = __doesnt_match; + --__n_might_match; + } + } + } + // consume if we matched a character + if (__consume) { + ++__b; + // If we consumed a character and there might be a matched keyword that + // was marked matched on a previous iteration, then such keywords + // which are now marked as not matching. + if (__n_might_match + __n_does_match > 1) { + __st = __status; + for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { + if (*__st == __does_match && __ky->size() != __indx + 1) { + *__st = __doesnt_match; + --__n_does_match; + } + } + } + } + } + // We've exited the loop because we hit eof and/or we have no more "might matches". + if (__b == __e) + __err |= ios_base::eofbit; + // Return the first matching result + for (__st = __status; __kb != __ke; ++__kb, (void)++__st) + if (*__st == __does_match) + break; + if (__kb == __ke) + __err |= ios_base::failbit; + return __kb; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_SCAN_KEYWORD_H diff --git a/libcxx/include/__locale_dir/time.h b/libcxx/include/__locale_dir/time.h new file mode 100644 index 0000000000000..5f60d5f36b349 --- /dev/null +++ b/libcxx/include/__locale_dir/time.h @@ -0,0 +1,766 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_TIME_H +#define _LIBCPP___LOCALE_DIR_TIME_H + +#include <__algorithm/copy.h> +#include <__config> +#include <__locale_dir/get_c_locale.h> +#include <__locale_dir/scan_keyword.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI int __get_up_to_n_digits( + _InputIterator& __b, _InputIterator __e, ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n) { + // Precondition: __n >= 1 + if (__b == __e) { + __err |= ios_base::eofbit | ios_base::failbit; + return 0; + } + // get first digit + _CharT __c = *__b; + if (!__ct.is(ctype_base::digit, __c)) { + __err |= ios_base::failbit; + return 0; + } + int __r = __ct.narrow(__c, 0) - '0'; + for (++__b, (void)--__n; __b != __e && __n > 0; ++__b, (void)--__n) { + // get next digit + __c = *__b; + if (!__ct.is(ctype_base::digit, __c)) + return __r; + __r = __r * 10 + __ct.narrow(__c, 0) - '0'; + } + if (__b == __e) + __err |= ios_base::eofbit; + return __r; +} + +class _LIBCPP_EXPORTED_FROM_ABI time_base { +public: + enum dateorder { no_order, dmy, mdy, ymd, ydm }; +}; + +template +class __time_get_c_storage { +protected: + typedef basic_string<_CharT> string_type; + + virtual const string_type* __weeks() const; + virtual const string_type* __months() const; + virtual const string_type* __am_pm() const; + virtual const string_type& __c() const; + virtual const string_type& __r() const; + virtual const string_type& __x() const; + virtual const string_type& __X() const; + + _LIBCPP_HIDE_FROM_ABI ~__time_get_c_storage() {} +}; + +template <> +_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__weeks() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__months() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__am_pm() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__c() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__r() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__x() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__X() const; + +# if _LIBCPP_HAS_WIDE_CHARACTERS +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__weeks() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__months() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__am_pm() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__c() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__r() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__x() const; +template <> +_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__X() const; +# endif + +template > +class time_get : public locale::facet, public time_base, private __time_get_c_storage<_CharT> { +public: + typedef _CharT char_type; + typedef _InputIterator iter_type; + typedef time_base::dateorder dateorder; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit time_get(size_t __refs = 0) : locale::facet(__refs) {} + + _LIBCPP_HIDE_FROM_ABI dateorder date_order() const { return this->do_date_order(); } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_time(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_date(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_weekday(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_monthname(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + return do_get_year(__b, __e, __iob, __err, __tm); + } + + _LIBCPP_HIDE_FROM_ABI iter_type + get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod = 0) + const { + return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod); + } + + iter_type + get(iter_type __b, + iter_type __e, + ios_base& __iob, + ios_base::iostate& __err, + tm* __tm, + const char_type* __fmtb, + const char_type* __fmte) const; + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get() override {} + + virtual dateorder do_date_order() const; + virtual iter_type + do_get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type + do_get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; + virtual iter_type do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod) const; + +private: + void __get_white_space(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + + void __get_weekdayname( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_monthname( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_day(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_month(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_year(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_year4(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_hour(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_12_hour(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_am_pm(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_minute(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_second(int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void + __get_weekday(int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; + void __get_day_year_num( + int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; +}; + +template +locale::id time_get<_CharT, _InputIterator>::id; + +// time_get primitives + +template +void time_get<_CharT, _InputIterator>::__get_weekdayname( + int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + // Note: ignoring case comes from the POSIX strptime spec + const string_type* __wk = this->__weeks(); + ptrdiff_t __i = std::__scan_keyword(__b, __e, __wk, __wk + 14, __ct, __err, false) - __wk; + if (__i < 14) + __w = __i % 7; +} + +template +void time_get<_CharT, _InputIterator>::__get_monthname( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + // Note: ignoring case comes from the POSIX strptime spec + const string_type* __month = this->__months(); + ptrdiff_t __i = std::__scan_keyword(__b, __e, __month, __month + 24, __ct, __err, false) - __month; + if (__i < 24) + __m = __i % 12; +} + +template +void time_get<_CharT, _InputIterator>::__get_day( + int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31) + __d = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_month( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1; + if (!(__err & ios_base::failbit) && 0 <= __t && __t <= 11) + __m = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_year( + int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4); + if (!(__err & ios_base::failbit)) { + if (__t < 69) + __t += 2000; + else if (69 <= __t && __t <= 99) + __t += 1900; + __y = __t - 1900; + } +} + +template +void time_get<_CharT, _InputIterator>::__get_year4( + int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4); + if (!(__err & ios_base::failbit)) + __y = __t - 1900; +} + +template +void time_get<_CharT, _InputIterator>::__get_hour( + int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && __t <= 23) + __h = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_12_hour( + int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12) + __h = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_minute( + int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && __t <= 59) + __m = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_second( + int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); + if (!(__err & ios_base::failbit) && __t <= 60) + __s = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_weekday( + int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 1); + if (!(__err & ios_base::failbit) && __t <= 6) + __w = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_day_year_num( + int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 3); + if (!(__err & ios_base::failbit) && __t <= 365) + __d = __t; + else + __err |= ios_base::failbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_white_space( + iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b) + ; + if (__b == __e) + __err |= ios_base::eofbit; +} + +template +void time_get<_CharT, _InputIterator>::__get_am_pm( + int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + const string_type* __ap = this->__am_pm(); + if (__ap[0].size() + __ap[1].size() == 0) { + __err |= ios_base::failbit; + return; + } + ptrdiff_t __i = std::__scan_keyword(__b, __e, __ap, __ap + 2, __ct, __err, false) - __ap; + if (__i == 0 && __h == 12) + __h = 0; + else if (__i == 1 && __h < 12) + __h += 12; +} + +template +void time_get<_CharT, _InputIterator>::__get_percent( + iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { + if (__b == __e) { + __err |= ios_base::eofbit | ios_base::failbit; + return; + } + if (__ct.narrow(*__b, 0) != '%') + __err |= ios_base::failbit; + else if (++__b == __e) + __err |= ios_base::eofbit; +} + +// time_get end primitives + +template +_InputIterator time_get<_CharT, _InputIterator>::get( + iter_type __b, + iter_type __e, + ios_base& __iob, + ios_base::iostate& __err, + tm* __tm, + const char_type* __fmtb, + const char_type* __fmte) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __err = ios_base::goodbit; + while (__fmtb != __fmte && __err == ios_base::goodbit) { + if (__b == __e) { + __err = ios_base::failbit; + break; + } + if (__ct.narrow(*__fmtb, 0) == '%') { + if (++__fmtb == __fmte) { + __err = ios_base::failbit; + break; + } + char __cmd = __ct.narrow(*__fmtb, 0); + char __opt = '\0'; + if (__cmd == 'E' || __cmd == '0') { + if (++__fmtb == __fmte) { + __err = ios_base::failbit; + break; + } + __opt = __cmd; + __cmd = __ct.narrow(*__fmtb, 0); + } + __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt); + ++__fmtb; + } else if (__ct.is(ctype_base::space, *__fmtb)) { + for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb) + ; + for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b) + ; + } else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb)) { + ++__b; + ++__fmtb; + } else + __err = ios_base::failbit; + } + if (__b == __e) + __err |= ios_base::eofbit; + return __b; +} + +template +typename time_get<_CharT, _InputIterator>::dateorder time_get<_CharT, _InputIterator>::do_date_order() const { + return mdy; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_time( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; + return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt) / sizeof(__fmt[0])); +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_date( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const string_type& __fmt = this->__x(); + return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size()); +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_weekday( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct); + return __b; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_monthname( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __get_monthname(__tm->tm_mon, __b, __e, __err, __ct); + return __b; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get_year( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + __get_year(__tm->tm_year, __b, __e, __err, __ct); + return __b; +} + +template +_InputIterator time_get<_CharT, _InputIterator>::do_get( + iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char) const { + __err = ios_base::goodbit; + const ctype& __ct = std::use_facet >(__iob.getloc()); + switch (__fmt) { + case 'a': + case 'A': + __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct); + break; + case 'b': + case 'B': + case 'h': + __get_monthname(__tm->tm_mon, __b, __e, __err, __ct); + break; + case 'c': { + const string_type& __fm = this->__c(); + __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size()); + } break; + case 'd': + case 'e': + __get_day(__tm->tm_mday, __b, __e, __err, __ct); + break; + case 'D': { + const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'F': { + const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'H': + __get_hour(__tm->tm_hour, __b, __e, __err, __ct); + break; + case 'I': + __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct); + break; + case 'j': + __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct); + break; + case 'm': + __get_month(__tm->tm_mon, __b, __e, __err, __ct); + break; + case 'M': + __get_minute(__tm->tm_min, __b, __e, __err, __ct); + break; + case 'n': + case 't': + __get_white_space(__b, __e, __err, __ct); + break; + case 'p': + __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct); + break; + case 'r': { + const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'R': { + const char_type __fm[] = {'%', 'H', ':', '%', 'M'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'S': + __get_second(__tm->tm_sec, __b, __e, __err, __ct); + break; + case 'T': { + const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; + __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); + } break; + case 'w': + __get_weekday(__tm->tm_wday, __b, __e, __err, __ct); + break; + case 'x': + return do_get_date(__b, __e, __iob, __err, __tm); + case 'X': { + const string_type& __fm = this->__X(); + __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size()); + } break; + case 'y': + __get_year(__tm->tm_year, __b, __e, __err, __ct); + break; + case 'Y': + __get_year4(__tm->tm_year, __b, __e, __err, __ct); + break; + case '%': + __get_percent(__b, __e, __err, __ct); + break; + default: + __err |= ios_base::failbit; + } + return __b; +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get; +# endif + +class _LIBCPP_EXPORTED_FROM_ABI __time_get { +protected: + __locale::__locale_t __loc_; + + __time_get(const char* __nm); + __time_get(const string& __nm); + ~__time_get(); +}; + +template +class __time_get_storage : public __time_get { +protected: + typedef basic_string<_CharT> string_type; + + string_type __weeks_[14]; + string_type __months_[24]; + string_type __am_pm_[2]; + string_type __c_; + string_type __r_; + string_type __x_; + string_type __X_; + + explicit __time_get_storage(const char* __nm); + explicit __time_get_storage(const string& __nm); + + _LIBCPP_HIDE_FROM_ABI ~__time_get_storage() {} + + time_base::dateorder __do_date_order() const; + +private: + void init(const ctype<_CharT>&); + string_type __analyze(char __fmt, const ctype<_CharT>&); +}; + +# define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ + template <> \ + _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze( \ + char, const ctype<_CharT>&); \ + extern template _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() \ + const; \ + extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \ + extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \ + extern template _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ + extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type \ + __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); + +_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char) +# if _LIBCPP_HAS_WIDE_CHARACTERS +_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t) +# endif +# undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION + +template > +class time_get_byname : public time_get<_CharT, _InputIterator>, private __time_get_storage<_CharT> { +public: + typedef time_base::dateorder dateorder; + typedef _InputIterator iter_type; + typedef _CharT char_type; + typedef basic_string string_type; + + _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const char* __nm, size_t __refs = 0) + : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {} + _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const string& __nm, size_t __refs = 0) + : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {} + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get_byname() override {} + + _LIBCPP_HIDE_FROM_ABI_VIRTUAL dateorder do_date_order() const override { return this->__do_date_order(); } + +private: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __weeks() const override { return this->__weeks_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __months() const override { return this->__months_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __am_pm() const override { return this->__am_pm_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __c() const override { return this->__c_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __r() const override { return this->__r_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __x() const override { return this->__x_; } + _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __X() const override { return this->__X_; } +}; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname; +# endif + +class _LIBCPP_EXPORTED_FROM_ABI __time_put { + __locale::__locale_t __loc_; + +protected: + _LIBCPP_HIDE_FROM_ABI __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {} + __time_put(const char* __nm); + __time_put(const string& __nm); + ~__time_put(); + void __do_put(char* __nb, char*& __ne, const tm* __tm, char __fmt, char __mod) const; +# if _LIBCPP_HAS_WIDE_CHARACTERS + void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, char __fmt, char __mod) const; +# endif +}; + +template > +class time_put : public locale::facet, private __time_put { +public: + typedef _CharT char_type; + typedef _OutputIterator iter_type; + + _LIBCPP_HIDE_FROM_ABI explicit time_put(size_t __refs = 0) : locale::facet(__refs) {} + + iter_type + put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe) + const; + + _LIBCPP_HIDE_FROM_ABI iter_type + put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, char __fmt, char __mod = 0) const { + return do_put(__s, __iob, __fl, __tm, __fmt, __mod); + } + + static locale::id id; + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put() override {} + virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const; + + _LIBCPP_HIDE_FROM_ABI explicit time_put(const char* __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {} + _LIBCPP_HIDE_FROM_ABI explicit time_put(const string& __nm, size_t __refs) + : locale::facet(__refs), __time_put(__nm) {} +}; + +template +locale::id time_put<_CharT, _OutputIterator>::id; + +template +_OutputIterator time_put<_CharT, _OutputIterator>::put( + iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe) + const { + const ctype& __ct = std::use_facet >(__iob.getloc()); + for (; __pb != __pe; ++__pb) { + if (__ct.narrow(*__pb, 0) == '%') { + if (++__pb == __pe) { + *__s++ = __pb[-1]; + break; + } + char __mod = 0; + char __fmt = __ct.narrow(*__pb, 0); + if (__fmt == 'E' || __fmt == 'O') { + if (++__pb == __pe) { + *__s++ = __pb[-2]; + *__s++ = __pb[-1]; + break; + } + __mod = __fmt; + __fmt = __ct.narrow(*__pb, 0); + } + __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod); + } else + *__s++ = *__pb; + } + return __s; +} + +template +_OutputIterator time_put<_CharT, _OutputIterator>::do_put( + iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const { + char_type __nar[100]; + char_type* __nb = __nar; + char_type* __ne = __nb + 100; + __do_put(__nb, __ne, __tm, __fmt, __mod); + return std::copy(__nb, __ne, __s); +} + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put; +# endif + +template > +class time_put_byname : public time_put<_CharT, _OutputIterator> { +public: + _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const char* __nm, size_t __refs = 0) + : time_put<_CharT, _OutputIterator>(__nm, __refs) {} + + _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const string& __nm, size_t __refs = 0) + : time_put<_CharT, _OutputIterator>(__nm, __refs) {} + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put_byname() override {} +}; + +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname; +# if _LIBCPP_HAS_WIDE_CHARACTERS +extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname; +# endif + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_TIME_H diff --git a/libcxx/include/__locale_dir/wbuffer_convert.h b/libcxx/include/__locale_dir/wbuffer_convert.h new file mode 100644 index 0000000000000..a6818aadf5d0b --- /dev/null +++ b/libcxx/include/__locale_dir/wbuffer_convert.h @@ -0,0 +1,430 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_WBUFFER_CONVERT_H +#define _LIBCPP___LOCALE_DIR_WBUFFER_CONVERT_H + +#include <__algorithm/reverse.h> +#include <__config> +#include <__string/char_traits.h> +#include +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +# if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template > +class _LIBCPP_DEPRECATED_IN_CXX17 wbuffer_convert : public basic_streambuf<_Elem, _Tr> { +public: + // types: + typedef _Elem char_type; + typedef _Tr traits_type; + typedef typename traits_type::int_type int_type; + typedef typename traits_type::pos_type pos_type; + typedef typename traits_type::off_type off_type; + typedef typename _Codecvt::state_type state_type; + +private: + char* __extbuf_; + const char* __extbufnext_; + const char* __extbufend_; + char __extbuf_min_[8]; + size_t __ebs_; + char_type* __intbuf_; + size_t __ibs_; + streambuf* __bufptr_; + _Codecvt* __cv_; + state_type __st_; + ios_base::openmode __cm_; + bool __owns_eb_; + bool __owns_ib_; + bool __always_noconv_; + +public: +# ifndef _LIBCPP_CXX03_LANG + _LIBCPP_HIDE_FROM_ABI wbuffer_convert() : wbuffer_convert(nullptr) {} + explicit _LIBCPP_HIDE_FROM_ABI + wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type()); +# else + _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI + wbuffer_convert(streambuf* __bytebuf = nullptr, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type()); +# endif + + _LIBCPP_HIDE_FROM_ABI ~wbuffer_convert(); + + _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf() const { return __bufptr_; } + _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf(streambuf* __bytebuf) { + streambuf* __r = __bufptr_; + __bufptr_ = __bytebuf; + return __r; + } + + wbuffer_convert(const wbuffer_convert&) = delete; + wbuffer_convert& operator=(const wbuffer_convert&) = delete; + + _LIBCPP_HIDE_FROM_ABI state_type state() const { return __st_; } + +protected: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type underflow(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type pbackfail(int_type __c = traits_type::eof()); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type overflow(int_type __c = traits_type::eof()); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual basic_streambuf* setbuf(char_type* __s, streamsize __n); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type + seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __wch = ios_base::in | ios_base::out); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type + seekpos(pos_type __sp, ios_base::openmode __wch = ios_base::in | ios_base::out); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int sync(); + +private: + _LIBCPP_HIDE_FROM_ABI_VIRTUAL bool __read_mode(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __write_mode(); + _LIBCPP_HIDE_FROM_ABI_VIRTUAL wbuffer_convert* __close(); +}; + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +wbuffer_convert<_Codecvt, _Elem, _Tr>::wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state) + : __extbuf_(nullptr), + __extbufnext_(nullptr), + __extbufend_(nullptr), + __ebs_(0), + __intbuf_(0), + __ibs_(0), + __bufptr_(__bytebuf), + __cv_(__pcvt), + __st_(__state), + __cm_(0), + __owns_eb_(false), + __owns_ib_(false), + __always_noconv_(__cv_ ? __cv_->always_noconv() : false) { + setbuf(0, 4096); +} + +template +wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert() { + __close(); + delete __cv_; + if (__owns_eb_) + delete[] __extbuf_; + if (__owns_ib_) + delete[] __intbuf_; +} + +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow() { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ == 0 || __bufptr_ == nullptr) + return traits_type::eof(); + bool __initial = __read_mode(); + char_type __1buf; + if (this->gptr() == 0) + this->setg(std::addressof(__1buf), std::addressof(__1buf) + 1, std::addressof(__1buf) + 1); + const size_t __unget_sz = __initial ? 0 : std::min((this->egptr() - this->eback()) / 2, 4); + int_type __c = traits_type::eof(); + if (this->gptr() == this->egptr()) { + std::memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type)); + if (__always_noconv_) { + streamsize __nmemb = static_cast(this->egptr() - this->eback() - __unget_sz); + __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb); + if (__nmemb != 0) { + this->setg(this->eback(), this->eback() + __unget_sz, this->eback() + __unget_sz + __nmemb); + __c = *this->gptr(); + } + } else { + if (__extbufend_ != __extbufnext_) { + _LIBCPP_ASSERT_NON_NULL(__extbufnext_ != nullptr, "underflow moving from nullptr"); + _LIBCPP_ASSERT_NON_NULL(__extbuf_ != nullptr, "underflow moving into nullptr"); + std::memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_); + } + __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_); + __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_); + streamsize __nmemb = std::min(static_cast(this->egptr() - this->eback() - __unget_sz), + static_cast(__extbufend_ - __extbufnext_)); + codecvt_base::result __r; + // FIXME: Do we ever need to restore the state here? + // state_type __svs = __st_; + streamsize __nr = __bufptr_->sgetn(const_cast(__extbufnext_), __nmemb); + if (__nr != 0) { + __extbufend_ = __extbufnext_ + __nr; + char_type* __inext; + __r = __cv_->in( + __st_, __extbuf_, __extbufend_, __extbufnext_, this->eback() + __unget_sz, this->egptr(), __inext); + if (__r == codecvt_base::noconv) { + this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)const_cast(__extbufend_)); + __c = *this->gptr(); + } else if (__inext != this->eback() + __unget_sz) { + this->setg(this->eback(), this->eback() + __unget_sz, __inext); + __c = *this->gptr(); + } + } + } + } else + __c = *this->gptr(); + if (this->eback() == std::addressof(__1buf)) + this->setg(0, 0, 0); + return __c; +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type +wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ != 0 && __bufptr_ && this->eback() < this->gptr()) { + if (traits_type::eq_int_type(__c, traits_type::eof())) { + this->gbump(-1); + return traits_type::not_eof(__c); + } + if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1])) { + this->gbump(-1); + *this->gptr() = traits_type::to_char_type(__c); + return __c; + } + } + return traits_type::eof(); +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ == 0 || !__bufptr_) + return traits_type::eof(); + __write_mode(); + char_type __1buf; + char_type* __pb_save = this->pbase(); + char_type* __epb_save = this->epptr(); + if (!traits_type::eq_int_type(__c, traits_type::eof())) { + if (this->pptr() == 0) + this->setp(std::addressof(__1buf), std::addressof(__1buf) + 1); + *this->pptr() = traits_type::to_char_type(__c); + this->pbump(1); + } + if (this->pptr() != this->pbase()) { + if (__always_noconv_) { + streamsize __nmemb = static_cast(this->pptr() - this->pbase()); + if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb) + return traits_type::eof(); + } else { + char* __extbe = __extbuf_; + codecvt_base::result __r; + do { + const char_type* __e; + __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e, __extbuf_, __extbuf_ + __ebs_, __extbe); + if (__e == this->pbase()) + return traits_type::eof(); + if (__r == codecvt_base::noconv) { + streamsize __nmemb = static_cast(this->pptr() - this->pbase()); + if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb) + return traits_type::eof(); + } else if (__r == codecvt_base::ok || __r == codecvt_base::partial) { + streamsize __nmemb = static_cast(__extbe - __extbuf_); + if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb) + return traits_type::eof(); + if (__r == codecvt_base::partial) { + this->setp(const_cast(__e), this->pptr()); + this->__pbump(this->epptr() - this->pbase()); + } + } else + return traits_type::eof(); + } while (__r == codecvt_base::partial); + } + this->setp(__pb_save, __epb_save); + } + return traits_type::not_eof(__c); +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +basic_streambuf<_Elem, _Tr>* wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + this->setg(0, 0, 0); + this->setp(0, 0); + if (__owns_eb_) + delete[] __extbuf_; + if (__owns_ib_) + delete[] __intbuf_; + __ebs_ = __n; + if (__ebs_ > sizeof(__extbuf_min_)) { + if (__always_noconv_ && __s) { + __extbuf_ = (char*)__s; + __owns_eb_ = false; + } else { + __extbuf_ = new char[__ebs_]; + __owns_eb_ = true; + } + } else { + __extbuf_ = __extbuf_min_; + __ebs_ = sizeof(__extbuf_min_); + __owns_eb_ = false; + } + if (!__always_noconv_) { + __ibs_ = max(__n, sizeof(__extbuf_min_)); + if (__s && __ibs_ >= sizeof(__extbuf_min_)) { + __intbuf_ = __s; + __owns_ib_ = false; + } else { + __intbuf_ = new char_type[__ibs_]; + __owns_ib_ = true; + } + } else { + __ibs_ = 0; + __intbuf_ = 0; + __owns_ib_ = false; + } + return this; +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type +wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __om) { + int __width = __cv_->encoding(); + if (__cv_ == 0 || !__bufptr_ || (__width <= 0 && __off != 0) || sync()) + return pos_type(off_type(-1)); + // __width > 0 || __off == 0, now check __way + if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end) + return pos_type(off_type(-1)); + pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om); + __r.state(__st_); + return __r; +} + +template +typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type +wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch) { + if (__cv_ == 0 || !__bufptr_ || sync()) + return pos_type(off_type(-1)); + if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1))) + return pos_type(off_type(-1)); + return __sp; +} + +template +int wbuffer_convert<_Codecvt, _Elem, _Tr>::sync() { + _LIBCPP_SUPPRESS_DEPRECATED_POP + if (__cv_ == 0 || !__bufptr_) + return 0; + if (__cm_ & ios_base::out) { + if (this->pptr() != this->pbase()) + if (overflow() == traits_type::eof()) + return -1; + codecvt_base::result __r; + do { + char* __extbe; + __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe); + streamsize __nmemb = static_cast(__extbe - __extbuf_); + if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb) + return -1; + } while (__r == codecvt_base::partial); + if (__r == codecvt_base::error) + return -1; + if (__bufptr_->pubsync()) + return -1; + } else if (__cm_ & ios_base::in) { + off_type __c; + if (__always_noconv_) + __c = this->egptr() - this->gptr(); + else { + int __width = __cv_->encoding(); + __c = __extbufend_ - __extbufnext_; + if (__width > 0) + __c += __width * (this->egptr() - this->gptr()); + else { + if (this->gptr() != this->egptr()) { + std::reverse(this->gptr(), this->egptr()); + codecvt_base::result __r; + const char_type* __e = this->gptr(); + char* __extbe; + do { + __r = __cv_->out(__st_, __e, this->egptr(), __e, __extbuf_, __extbuf_ + __ebs_, __extbe); + switch (__r) { + case codecvt_base::noconv: + __c += this->egptr() - this->gptr(); + break; + case codecvt_base::ok: + case codecvt_base::partial: + __c += __extbe - __extbuf_; + break; + default: + return -1; + } + } while (__r == codecvt_base::partial); + } + } + } + if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1))) + return -1; + this->setg(0, 0, 0); + __cm_ = 0; + } + return 0; +} + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +bool wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode() { + if (!(__cm_ & ios_base::in)) { + this->setp(0, 0); + if (__always_noconv_) + this->setg((char_type*)__extbuf_, (char_type*)__extbuf_ + __ebs_, (char_type*)__extbuf_ + __ebs_); + else + this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_); + __cm_ = ios_base::in; + return true; + } + return false; +} + +template +void wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode() { + if (!(__cm_ & ios_base::out)) { + this->setg(0, 0, 0); + if (__ebs_ > sizeof(__extbuf_min_)) { + if (__always_noconv_) + this->setp((char_type*)__extbuf_, (char_type*)__extbuf_ + (__ebs_ - 1)); + else + this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1)); + } else + this->setp(0, 0); + __cm_ = ios_base::out; + } +} + +template +wbuffer_convert<_Codecvt, _Elem, _Tr>* wbuffer_convert<_Codecvt, _Elem, _Tr>::__close() { + wbuffer_convert* __rt = nullptr; + if (__cv_ != nullptr && __bufptr_ != nullptr) { + __rt = this; + if ((__cm_ & ios_base::out) && sync()) + __rt = nullptr; + } + return __rt; +} + +_LIBCPP_SUPPRESS_DEPRECATED_POP + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +# endif // _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_WBUFFER_CONVERT_H diff --git a/libcxx/include/__locale_dir/wstring_convert.h b/libcxx/include/__locale_dir/wstring_convert.h new file mode 100644 index 0000000000000..42a56eb8573ea --- /dev/null +++ b/libcxx/include/__locale_dir/wstring_convert.h @@ -0,0 +1,254 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___LOCALE_DIR_WSTRING_CONVERT_H +#define _LIBCPP___LOCALE_DIR_WSTRING_CONVERT_H + +#include <__config> +#include <__locale> +#include <__memory/allocator.h> +#include + +#if _LIBCPP_HAS_LOCALIZATION + +# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +# endif + +# if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +_LIBCPP_PUSH_MACROS +# include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template , + class _ByteAlloc = allocator > +class _LIBCPP_DEPRECATED_IN_CXX17 wstring_convert { +public: + typedef basic_string, _ByteAlloc> byte_string; + typedef basic_string<_Elem, char_traits<_Elem>, _WideAlloc> wide_string; + typedef typename _Codecvt::state_type state_type; + typedef typename wide_string::traits_type::int_type int_type; + +private: + byte_string __byte_err_string_; + wide_string __wide_err_string_; + _Codecvt* __cvtptr_; + state_type __cvtstate_; + size_t __cvtcount_; + +public: +# ifndef _LIBCPP_CXX03_LANG + _LIBCPP_HIDE_FROM_ABI wstring_convert() : wstring_convert(new _Codecvt) {} + _LIBCPP_HIDE_FROM_ABI explicit wstring_convert(_Codecvt* __pcvt); +# else + _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXPLICIT_SINCE_CXX14 wstring_convert(_Codecvt* __pcvt = new _Codecvt); +# endif + + _LIBCPP_HIDE_FROM_ABI wstring_convert(_Codecvt* __pcvt, state_type __state); + _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI + wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err = wide_string()); +# ifndef _LIBCPP_CXX03_LANG + _LIBCPP_HIDE_FROM_ABI wstring_convert(wstring_convert&& __wc); +# endif + _LIBCPP_HIDE_FROM_ABI ~wstring_convert(); + + wstring_convert(const wstring_convert& __wc) = delete; + wstring_convert& operator=(const wstring_convert& __wc) = delete; + + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(char __byte) { return from_bytes(&__byte, &__byte + 1); } + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __ptr) { + return from_bytes(__ptr, __ptr + char_traits::length(__ptr)); + } + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const byte_string& __str) { + return from_bytes(__str.data(), __str.data() + __str.size()); + } + _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __first, const char* __last); + + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(_Elem __wchar) { + return to_bytes(std::addressof(__wchar), std::addressof(__wchar) + 1); + } + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __wptr) { + return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr)); + } + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const wide_string& __wstr) { + return to_bytes(__wstr.data(), __wstr.data() + __wstr.size()); + } + _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __first, const _Elem* __last); + + _LIBCPP_HIDE_FROM_ABI size_t converted() const _NOEXCEPT { return __cvtcount_; } + _LIBCPP_HIDE_FROM_ABI state_type state() const { return __cvtstate_; } +}; + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(_Codecvt* __pcvt) + : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0) {} +_LIBCPP_SUPPRESS_DEPRECATED_POP + +template +inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(_Codecvt* __pcvt, state_type __state) + : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0) {} + +template +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert( + const byte_string& __byte_err, const wide_string& __wide_err) + : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err), __cvtstate_(), __cvtcount_(0) { + __cvtptr_ = new _Codecvt; +} + +# ifndef _LIBCPP_CXX03_LANG + +template +inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(wstring_convert&& __wc) + : __byte_err_string_(std::move(__wc.__byte_err_string_)), + __wide_err_string_(std::move(__wc.__wide_err_string_)), + __cvtptr_(__wc.__cvtptr_), + __cvtstate_(__wc.__cvtstate_), + __cvtcount_(__wc.__cvtcount_) { + __wc.__cvtptr_ = nullptr; +} + +# endif // _LIBCPP_CXX03_LANG + +_LIBCPP_SUPPRESS_DEPRECATED_PUSH +template +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::~wstring_convert() { + delete __cvtptr_; +} + +template +typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wide_string +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::from_bytes(const char* __frm, const char* __frm_end) { + _LIBCPP_SUPPRESS_DEPRECATED_POP + __cvtcount_ = 0; + if (__cvtptr_ != nullptr) { + wide_string __ws(2 * (__frm_end - __frm), _Elem()); + if (__frm != __frm_end) + __ws.resize(__ws.capacity()); + codecvt_base::result __r = codecvt_base::ok; + state_type __st = __cvtstate_; + if (__frm != __frm_end) { + _Elem* __to = std::addressof(__ws[0]); + _Elem* __to_end = __to + __ws.size(); + const char* __frm_nxt; + do { + _Elem* __to_nxt; + __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + __cvtcount_ += __frm_nxt - __frm; + if (__frm_nxt == __frm) { + __r = codecvt_base::error; + } else if (__r == codecvt_base::noconv) { + __ws.resize(__to - std::addressof(__ws[0])); + // This only gets executed if _Elem is char + __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end); + __frm = __frm_nxt; + __r = codecvt_base::ok; + } else if (__r == codecvt_base::ok) { + __ws.resize(__to_nxt - std::addressof(__ws[0])); + __frm = __frm_nxt; + } else if (__r == codecvt_base::partial) { + ptrdiff_t __s = __to_nxt - std::addressof(__ws[0]); + __ws.resize(2 * __s); + __to = std::addressof(__ws[0]) + __s; + __to_end = std::addressof(__ws[0]) + __ws.size(); + __frm = __frm_nxt; + } + } while (__r == codecvt_base::partial && __frm_nxt < __frm_end); + } + if (__r == codecvt_base::ok) + return __ws; + } + + if (__wide_err_string_.empty()) + std::__throw_range_error("wstring_convert: from_bytes error"); + + return __wide_err_string_; +} + +template +typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::byte_string +wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::to_bytes(const _Elem* __frm, const _Elem* __frm_end) { + __cvtcount_ = 0; + if (__cvtptr_ != nullptr) { + byte_string __bs(2 * (__frm_end - __frm), char()); + if (__frm != __frm_end) + __bs.resize(__bs.capacity()); + codecvt_base::result __r = codecvt_base::ok; + state_type __st = __cvtstate_; + if (__frm != __frm_end) { + char* __to = std::addressof(__bs[0]); + char* __to_end = __to + __bs.size(); + const _Elem* __frm_nxt; + do { + char* __to_nxt; + __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); + __cvtcount_ += __frm_nxt - __frm; + if (__frm_nxt == __frm) { + __r = codecvt_base::error; + } else if (__r == codecvt_base::noconv) { + __bs.resize(__to - std::addressof(__bs[0])); + // This only gets executed if _Elem is char + __bs.append((const char*)__frm, (const char*)__frm_end); + __frm = __frm_nxt; + __r = codecvt_base::ok; + } else if (__r == codecvt_base::ok) { + __bs.resize(__to_nxt - std::addressof(__bs[0])); + __frm = __frm_nxt; + } else if (__r == codecvt_base::partial) { + ptrdiff_t __s = __to_nxt - std::addressof(__bs[0]); + __bs.resize(2 * __s); + __to = std::addressof(__bs[0]) + __s; + __to_end = std::addressof(__bs[0]) + __bs.size(); + __frm = __frm_nxt; + } + } while (__r == codecvt_base::partial && __frm_nxt < __frm_end); + } + if (__r == codecvt_base::ok) { + size_t __s = __bs.size(); + __bs.resize(__bs.capacity()); + char* __to = std::addressof(__bs[0]) + __s; + char* __to_end = __to + __bs.size(); + do { + char* __to_nxt; + __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt); + if (__r == codecvt_base::noconv) { + __bs.resize(__to - std::addressof(__bs[0])); + __r = codecvt_base::ok; + } else if (__r == codecvt_base::ok) { + __bs.resize(__to_nxt - std::addressof(__bs[0])); + } else if (__r == codecvt_base::partial) { + ptrdiff_t __sp = __to_nxt - std::addressof(__bs[0]); + __bs.resize(2 * __sp); + __to = std::addressof(__bs[0]) + __sp; + __to_end = std::addressof(__bs[0]) + __bs.size(); + } + } while (__r == codecvt_base::partial); + if (__r == codecvt_base::ok) + return __bs; + } + } + + if (__byte_err_string_.empty()) + std::__throw_range_error("wstring_convert: to_bytes error"); + + return __byte_err_string_; +} + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +# endif // _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) + +#endif // _LIBCPP_HAS_LOCALIZATION + +#endif // _LIBCPP___LOCALE_DIR_WSTRING_CONVERT_H diff --git a/libcxx/include/__ostream/basic_ostream.h b/libcxx/include/__ostream/basic_ostream.h index f7473a36d8ccc..effeef491f341 100644 --- a/libcxx/include/__ostream/basic_ostream.h +++ b/libcxx/include/__ostream/basic_ostream.h @@ -15,6 +15,9 @@ # include <__exception/operations.h> # include <__fwd/memory.h> +# include <__iterator/ostreambuf_iterator.h> +# include <__locale_dir/num.h> +# include <__locale_dir/pad_and_output.h> # include <__memory/addressof.h> # include <__memory/unique_ptr.h> # include <__new/exceptions.h> @@ -27,7 +30,6 @@ # include <__utility/declval.h> # include # include -# include # include # include diff --git a/libcxx/include/__ostream/print.h b/libcxx/include/__ostream/print.h index a4d7506cffc48..c5906c41b95b5 100644 --- a/libcxx/include/__ostream/print.h +++ b/libcxx/include/__ostream/print.h @@ -18,8 +18,8 @@ # include <__ostream/basic_ostream.h> # include # include -# include # include +# include # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h index 40ea83096e738..1b51571ce302e 100644 --- a/libcxx/include/__thread/thread.h +++ b/libcxx/include/__thread/thread.h @@ -16,6 +16,7 @@ #include <__exception/terminate.h> #include <__functional/hash.h> #include <__functional/unary_function.h> +#include <__locale> #include <__memory/addressof.h> #include <__memory/unique_ptr.h> #include <__mutex/mutex.h> @@ -30,7 +31,6 @@ #include #if _LIBCPP_HAS_LOCALIZATION -# include # include #endif diff --git a/libcxx/include/experimental/iterator b/libcxx/include/experimental/iterator index 565bb83903ac3..0ed95188d7715 100644 --- a/libcxx/include/experimental/iterator +++ b/libcxx/include/experimental/iterator @@ -130,6 +130,11 @@ _LIBCPP_POP_MACROS # include # include # endif + +# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23 +# include +# endif + #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) #endif // _LIBCPP_EXPERIMENTAL_ITERATOR diff --git a/libcxx/include/iomanip b/libcxx/include/iomanip index a97b4a94d232f..d65d66d716597 100644 --- a/libcxx/include/iomanip +++ b/libcxx/include/iomanip @@ -49,10 +49,12 @@ template # if _LIBCPP_HAS_LOCALIZATION +# include <__iterator/istreambuf_iterator.h> +# include <__locale_dir/money.h> +# include <__locale_dir/time.h> # include <__ostream/put_character_sequence.h> # include # include -# include # include # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -564,6 +566,11 @@ _LIBCPP_END_NAMESPACE_STD # include # include # endif + +# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23 +# include +# endif + #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) #endif // _LIBCPP_IOMANIP diff --git a/libcxx/include/istream b/libcxx/include/istream index 02546902494e3..93def61a8b477 100644 --- a/libcxx/include/istream +++ b/libcxx/include/istream @@ -167,6 +167,7 @@ template # include <__fwd/istream.h> # include <__iterator/istreambuf_iterator.h> +# include <__locale_dir/num.h> # include <__ostream/basic_ostream.h> # include <__type_traits/conjunction.h> # include <__type_traits/enable_if.h> @@ -176,7 +177,7 @@ template # include <__utility/forward.h> # include # include -# include +# include # include # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -1411,6 +1412,10 @@ _LIBCPP_POP_MACROS # include # endif +# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23 +# include +# endif + #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) #endif // _LIBCPP_ISTREAM diff --git a/libcxx/include/locale b/libcxx/include/locale index b206bf8f162f9..b50f9c87c7281 100644 --- a/libcxx/include/locale +++ b/libcxx/include/locale @@ -194,3496 +194,20 @@ template class messages_byname; # if _LIBCPP_HAS_LOCALIZATION -# include <__algorithm/copy.h> -# include <__algorithm/equal.h> -# include <__algorithm/find.h> -# include <__algorithm/max.h> -# include <__algorithm/reverse.h> -# include <__algorithm/unwrap_iter.h> -# include <__assert> -# include <__charconv/to_chars_integral.h> -# include <__charconv/traits.h> -# include <__iterator/access.h> -# include <__iterator/back_insert_iterator.h> -# include <__iterator/istreambuf_iterator.h> -# include <__iterator/ostreambuf_iterator.h> # include <__locale> -# include <__locale_dir/pad_and_output.h> -# include <__memory/addressof.h> -# include <__memory/unique_ptr.h> -# include <__new/exceptions.h> -# include <__system_error/errc.h> -# include <__type_traits/make_unsigned.h> -# include -# include -# include -# include +# include <__locale_dir/messages.h> +# include <__locale_dir/money.h> +# include <__locale_dir/num.h> +# include <__locale_dir/time.h> +# include <__locale_dir/wbuffer_convert.h> +# include <__locale_dir/wstring_convert.h> # include -# include -# include # include -// TODO: Properly qualify calls now that the locale base API defines functions instead of macros -// NOLINTBEGIN(libcpp-robust-against-adl) - -# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -// Most unix variants have catopen. These are the specific ones that don't. -# if !defined(__BIONIC__) && !defined(_NEWLIB_VERSION) && !defined(__EMSCRIPTEN__) -# define _LIBCPP_HAS_CATOPEN 1 -# include -# else -# define _LIBCPP_HAS_CATOPEN 0 -# endif -# else -# define _LIBCPP_HAS_CATOPEN 0 -# endif - # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header # endif -_LIBCPP_PUSH_MACROS -# include <__undef_macros> - -_LIBCPP_BEGIN_NAMESPACE_STD - -# if defined(__APPLE__) || defined(__FreeBSD__) -# define _LIBCPP_GET_C_LOCALE 0 -# elif defined(__NetBSD__) -# define _LIBCPP_GET_C_LOCALE LC_C_LOCALE -# else -# define _LIBCPP_GET_C_LOCALE __cloc() -// Get the C locale object -_LIBCPP_EXPORTED_FROM_ABI __locale::__locale_t __cloc(); -# define __cloc_defined -# endif - -// __scan_keyword -// Scans [__b, __e) until a match is found in the basic_strings range -// [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke). -// __b will be incremented (visibly), consuming CharT until a match is found -// or proved to not exist. A keyword may be "", in which will match anything. -// If one keyword is a prefix of another, and the next CharT in the input -// might match another keyword, the algorithm will attempt to find the longest -// matching keyword. If the longer matching keyword ends up not matching, then -// no keyword match is found. If no keyword match is found, __ke is returned -// and failbit is set in __err. -// Else an iterator pointing to the matching keyword is found. If more than -// one keyword matches, an iterator to the first matching keyword is returned. -// If on exit __b == __e, eofbit is set in __err. If __case_sensitive is false, -// __ct is used to force to lower case before comparing characters. -// Examples: -// Keywords: "a", "abb" -// If the input is "a", the first keyword matches and eofbit is set. -// If the input is "abc", no match is found and "ab" are consumed. -template -_LIBCPP_HIDE_FROM_ABI _ForwardIterator __scan_keyword( - _InputIterator& __b, - _InputIterator __e, - _ForwardIterator __kb, - _ForwardIterator __ke, - const _Ctype& __ct, - ios_base::iostate& __err, - bool __case_sensitive = true) { - typedef typename iterator_traits<_InputIterator>::value_type _CharT; - size_t __nkw = static_cast(std::distance(__kb, __ke)); - const unsigned char __doesnt_match = '\0'; - const unsigned char __might_match = '\1'; - const unsigned char __does_match = '\2'; - unsigned char __statbuf[100]; - unsigned char* __status = __statbuf; - unique_ptr __stat_hold(nullptr, free); - if (__nkw > sizeof(__statbuf)) { - __status = (unsigned char*)malloc(__nkw); - if (__status == nullptr) - std::__throw_bad_alloc(); - __stat_hold.reset(__status); - } - size_t __n_might_match = __nkw; // At this point, any keyword might match - size_t __n_does_match = 0; // but none of them definitely do - // Initialize all statuses to __might_match, except for "" keywords are __does_match - unsigned char* __st = __status; - for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { - if (!__ky->empty()) - *__st = __might_match; - else { - *__st = __does_match; - --__n_might_match; - ++__n_does_match; - } - } - // While there might be a match, test keywords against the next CharT - for (size_t __indx = 0; __b != __e && __n_might_match > 0; ++__indx) { - // Peek at the next CharT but don't consume it - _CharT __c = *__b; - if (!__case_sensitive) - __c = __ct.toupper(__c); - bool __consume = false; - // For each keyword which might match, see if the __indx character is __c - // If a match if found, consume __c - // If a match is found, and that is the last character in the keyword, - // then that keyword matches. - // If the keyword doesn't match this character, then change the keyword - // to doesn't match - __st = __status; - for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { - if (*__st == __might_match) { - _CharT __kc = (*__ky)[__indx]; - if (!__case_sensitive) - __kc = __ct.toupper(__kc); - if (__c == __kc) { - __consume = true; - if (__ky->size() == __indx + 1) { - *__st = __does_match; - --__n_might_match; - ++__n_does_match; - } - } else { - *__st = __doesnt_match; - --__n_might_match; - } - } - } - // consume if we matched a character - if (__consume) { - ++__b; - // If we consumed a character and there might be a matched keyword that - // was marked matched on a previous iteration, then such keywords - // which are now marked as not matching. - if (__n_might_match + __n_does_match > 1) { - __st = __status; - for (_ForwardIterator __ky = __kb; __ky != __ke; ++__ky, (void)++__st) { - if (*__st == __does_match && __ky->size() != __indx + 1) { - *__st = __doesnt_match; - --__n_does_match; - } - } - } - } - } - // We've exited the loop because we hit eof and/or we have no more "might matches". - if (__b == __e) - __err |= ios_base::eofbit; - // Return the first matching result - for (__st = __status; __kb != __ke; ++__kb, (void)++__st) - if (*__st == __does_match) - break; - if (__kb == __ke) - __err |= ios_base::failbit; - return __kb; -} - -struct _LIBCPP_EXPORTED_FROM_ABI __num_get_base { - static const int __num_get_buf_sz = 40; - - static int __get_base(ios_base&); - static const char __src[33]; // "0123456789abcdefABCDEFxX+-pPiInN" - // count of leading characters in __src used for parsing integers ("012..X+-") - static const size_t __int_chr_cnt = 26; - // count of leading characters in __src used for parsing floating-point values ("012..-pP") - static const size_t __fp_chr_cnt = 28; -}; - -_LIBCPP_EXPORTED_FROM_ABI void -__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, ios_base::iostate& __err); - -template -struct __num_get : protected __num_get_base { - static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep); - - static int __stage2_float_loop( - _CharT __ct, - bool& __in_units, - char& __exp, - char* __a, - char*& __a_end, - _CharT __decimal_point, - _CharT __thousands_sep, - const string& __grouping, - unsigned* __g, - unsigned*& __g_end, - unsigned& __dc, - _CharT* __atoms); - - [[__deprecated__("This exists only for ABI compatibility")]] static string - __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep); - static int __stage2_int_loop( - _CharT __ct, - int __base, - char* __a, - char*& __a_end, - unsigned& __dc, - _CharT __thousands_sep, - const string& __grouping, - unsigned* __g, - unsigned*& __g_end, - _CharT* __atoms); - - _LIBCPP_HIDE_FROM_ABI static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) { - locale __loc = __iob.getloc(); - const numpunct<_CharT>& __np = use_facet >(__loc); - __thousands_sep = __np.thousands_sep(); - return __np.grouping(); - } - - _LIBCPP_HIDE_FROM_ABI const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const { - return __do_widen_p(__iob, __atoms); - } - -private: - template - _LIBCPP_HIDE_FROM_ABI const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const { - locale __loc = __iob.getloc(); - use_facet >(__loc).widen(__src, __src + __int_chr_cnt, __atoms); - return __atoms; - } - - _LIBCPP_HIDE_FROM_ABI const char* __do_widen_p(ios_base& __iob, char* __atoms) const { - (void)__iob; - (void)__atoms; - return __src; - } -}; - -template -string __num_get<_CharT>::__stage2_float_prep( - ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep) { - locale __loc = __iob.getloc(); - std::use_facet >(__loc).widen(__src, __src + __fp_chr_cnt, __atoms); - const numpunct<_CharT>& __np = std::use_facet >(__loc); - __decimal_point = __np.decimal_point(); - __thousands_sep = __np.thousands_sep(); - return __np.grouping(); -} - -template -int __num_get<_CharT>::__stage2_int_loop( - _CharT __ct, - int __base, - char* __a, - char*& __a_end, - unsigned& __dc, - _CharT __thousands_sep, - const string& __grouping, - unsigned* __g, - unsigned*& __g_end, - _CharT* __atoms) { - if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25])) { - *__a_end++ = __ct == __atoms[24] ? '+' : '-'; - __dc = 0; - return 0; - } - if (__grouping.size() != 0 && __ct == __thousands_sep) { - if (__g_end - __g < __num_get_buf_sz) { - *__g_end++ = __dc; - __dc = 0; - } - return 0; - } - ptrdiff_t __f = std::find(__atoms, __atoms + __int_chr_cnt, __ct) - __atoms; - if (__f >= 24) - return -1; - switch (__base) { - case 8: - case 10: - if (__f >= __base) - return -1; - break; - case 16: - if (__f < 22) - break; - if (__a_end != __a && __a_end - __a <= 2 && __a_end[-1] == '0') { - __dc = 0; - *__a_end++ = __src[__f]; - return 0; - } - return -1; - } - *__a_end++ = __src[__f]; - ++__dc; - return 0; -} - -template -int __num_get<_CharT>::__stage2_float_loop( - _CharT __ct, - bool& __in_units, - char& __exp, - char* __a, - char*& __a_end, - _CharT __decimal_point, - _CharT __thousands_sep, - const string& __grouping, - unsigned* __g, - unsigned*& __g_end, - unsigned& __dc, - _CharT* __atoms) { - if (__ct == __decimal_point) { - if (!__in_units) - return -1; - __in_units = false; - *__a_end++ = '.'; - if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz) - *__g_end++ = __dc; - return 0; - } - if (__ct == __thousands_sep && __grouping.size() != 0) { - if (!__in_units) - return -1; - if (__g_end - __g < __num_get_buf_sz) { - *__g_end++ = __dc; - __dc = 0; - } - return 0; - } - ptrdiff_t __f = std::find(__atoms, __atoms + __num_get_base::__fp_chr_cnt, __ct) - __atoms; - if (__f >= static_cast(__num_get_base::__fp_chr_cnt)) - return -1; - char __x = __src[__f]; - if (__x == '-' || __x == '+') { - if (__a_end == __a || (std::toupper(__a_end[-1]) == std::toupper(__exp))) { - *__a_end++ = __x; - return 0; - } - return -1; - } - if (__x == 'x' || __x == 'X') - __exp = 'P'; - else if (std::toupper(__x) == __exp) { - __exp = std::tolower(__exp); - if (__in_units) { - __in_units = false; - if (__grouping.size() != 0 && __g_end - __g < __num_get_buf_sz) - *__g_end++ = __dc; - } - } - *__a_end++ = __x; - if (__f >= 22) - return 0; - ++__dc; - return 0; -} - -extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get; -# endif - -template -_LIBCPP_HIDE_FROM_ABI _Tp __do_strtod(const char* __a, char** __p2); - -template <> -inline _LIBCPP_HIDE_FROM_ABI float __do_strtod(const char* __a, char** __p2) { - return __locale::__strtof(__a, __p2, _LIBCPP_GET_C_LOCALE); -} - -template <> -inline _LIBCPP_HIDE_FROM_ABI double __do_strtod(const char* __a, char** __p2) { - return __locale::__strtod(__a, __p2, _LIBCPP_GET_C_LOCALE); -} - -template <> -inline _LIBCPP_HIDE_FROM_ABI long double __do_strtod(const char* __a, char** __p2) { - return __locale::__strtold(__a, __p2, _LIBCPP_GET_C_LOCALE); -} - -template -_LIBCPP_HIDE_FROM_ABI _Tp __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) { - if (__a != __a_end) { - __libcpp_remove_reference_t __save_errno = errno; - errno = 0; - char* __p2; - _Tp __ld = std::__do_strtod<_Tp>(__a, &__p2); - __libcpp_remove_reference_t __current_errno = errno; - if (__current_errno == 0) - errno = __save_errno; - if (__p2 != __a_end) { - __err = ios_base::failbit; - return 0; - } else if (__current_errno == ERANGE) - __err = ios_base::failbit; - return __ld; - } - __err = ios_base::failbit; - return 0; -} - -template -_LIBCPP_HIDE_FROM_ABI _Tp -__num_get_signed_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { - if (__a != __a_end) { - __libcpp_remove_reference_t __save_errno = errno; - errno = 0; - char* __p2; - long long __ll = __locale::__strtoll(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); - __libcpp_remove_reference_t __current_errno = errno; - if (__current_errno == 0) - errno = __save_errno; - if (__p2 != __a_end) { - __err = ios_base::failbit; - return 0; - } else if (__current_errno == ERANGE || __ll < numeric_limits<_Tp>::min() || numeric_limits<_Tp>::max() < __ll) { - __err = ios_base::failbit; - if (__ll > 0) - return numeric_limits<_Tp>::max(); - else - return numeric_limits<_Tp>::min(); - } - return static_cast<_Tp>(__ll); - } - __err = ios_base::failbit; - return 0; -} - -template -_LIBCPP_HIDE_FROM_ABI _Tp -__num_get_unsigned_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { - if (__a != __a_end) { - const bool __negate = *__a == '-'; - if (__negate && ++__a == __a_end) { - __err = ios_base::failbit; - return 0; - } - __libcpp_remove_reference_t __save_errno = errno; - errno = 0; - char* __p2; - unsigned long long __ll = __locale::__strtoull(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); - __libcpp_remove_reference_t __current_errno = errno; - if (__current_errno == 0) - errno = __save_errno; - if (__p2 != __a_end) { - __err = ios_base::failbit; - return 0; - } else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll) { - __err = ios_base::failbit; - return numeric_limits<_Tp>::max(); - } - _Tp __res = static_cast<_Tp>(__ll); - if (__negate) - __res = -__res; - return __res; - } - __err = ios_base::failbit; - return 0; -} - -template > -class num_get : public locale::facet, private __num_get<_CharT> { -public: - typedef _CharT char_type; - typedef _InputIterator iter_type; - - _LIBCPP_HIDE_FROM_ABI explicit num_get(size_t __refs = 0) : locale::facet(__refs) {} - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { - return do_get(__b, __e, __iob, __err, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const { - return do_get(__b, __e, __iob, __err, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const { - return do_get(__b, __e, __iob, __err, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const { - return do_get(__b, __e, __iob, __err, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const { - return do_get(__b, __e, __iob, __err, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const { - return do_get(__b, __e, __iob, __err, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const { - return do_get(__b, __e, __iob, __err, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const { - return do_get(__b, __e, __iob, __err, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const { - return do_get(__b, __e, __iob, __err, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { - return do_get(__b, __e, __iob, __err, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { - return do_get(__b, __e, __iob, __err, __v); - } - - static locale::id id; - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_get() override {} - - template - _LIBCPP_HIDE_FROM_ABI iter_type - __do_get_floating_point(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const { - // Stage 1, nothing to do - // Stage 2 - char_type __atoms[__num_get_base::__fp_chr_cnt]; - char_type __decimal_point; - char_type __thousands_sep; - string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep); - string __buf; - __buf.resize(__buf.capacity()); - char* __a = &__buf[0]; - char* __a_end = __a; - unsigned __g[__num_get_base::__num_get_buf_sz]; - unsigned* __g_end = __g; - unsigned __dc = 0; - bool __in_units = true; - char __exp = 'E'; - bool __is_leading_parsed = false; - for (; __b != __e; ++__b) { - if (__a_end == __a + __buf.size()) { - size_t __tmp = __buf.size(); - __buf.resize(2 * __buf.size()); - __buf.resize(__buf.capacity()); - __a = &__buf[0]; - __a_end = __a + __tmp; - } - if (this->__stage2_float_loop( - *__b, - __in_units, - __exp, - __a, - __a_end, - __decimal_point, - __thousands_sep, - __grouping, - __g, - __g_end, - __dc, - __atoms)) - break; - - // the leading character excluding the sign must be a decimal digit - if (!__is_leading_parsed) { - if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') { - if (('0' <= __a[0] && __a[0] <= '9') || __a[0] == '.') - __is_leading_parsed = true; - else - break; - } else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) { - if (('0' <= __a[1] && __a[1] <= '9') || __a[1] == '.') - __is_leading_parsed = true; - else - break; - } - } - } - if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz) - *__g_end++ = __dc; - // Stage 3 - __v = std::__num_get_float<_Fp>(__a, __a_end, __err); - // Digit grouping checked - __check_grouping(__grouping, __g, __g_end, __err); - // EOF checked - if (__b == __e) - __err |= ios_base::eofbit; - return __b; - } - - template - _LIBCPP_HIDE_FROM_ABI iter_type - __do_get_signed(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const { - // Stage 1 - int __base = this->__get_base(__iob); - // Stage 2 - char_type __thousands_sep; - const int __atoms_size = __num_get_base::__int_chr_cnt; - char_type __atoms1[__atoms_size]; - const char_type* __atoms = this->__do_widen(__iob, __atoms1); - string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); - string __buf; - __buf.resize(__buf.capacity()); - char* __a = &__buf[0]; - char* __a_end = __a; - unsigned __g[__num_get_base::__num_get_buf_sz]; - unsigned* __g_end = __g; - unsigned __dc = 0; - for (; __b != __e; ++__b) { - if (__a_end == __a + __buf.size()) { - size_t __tmp = __buf.size(); - __buf.resize(2 * __buf.size()); - __buf.resize(__buf.capacity()); - __a = &__buf[0]; - __a_end = __a + __tmp; - } - if (this->__stage2_int_loop( - *__b, - __base, - __a, - __a_end, - __dc, - __thousands_sep, - __grouping, - __g, - __g_end, - const_cast(__atoms))) - break; - } - if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) - *__g_end++ = __dc; - // Stage 3 - __v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base); - // Digit grouping checked - __check_grouping(__grouping, __g, __g_end, __err); - // EOF checked - if (__b == __e) - __err |= ios_base::eofbit; - return __b; - } - - template - _LIBCPP_HIDE_FROM_ABI iter_type - __do_get_unsigned(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const { - // Stage 1 - int __base = this->__get_base(__iob); - // Stage 2 - char_type __thousands_sep; - const int __atoms_size = __num_get_base::__int_chr_cnt; - char_type __atoms1[__atoms_size]; - const char_type* __atoms = this->__do_widen(__iob, __atoms1); - string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); - string __buf; - __buf.resize(__buf.capacity()); - char* __a = &__buf[0]; - char* __a_end = __a; - unsigned __g[__num_get_base::__num_get_buf_sz]; - unsigned* __g_end = __g; - unsigned __dc = 0; - for (; __b != __e; ++__b) { - if (__a_end == __a + __buf.size()) { - size_t __tmp = __buf.size(); - __buf.resize(2 * __buf.size()); - __buf.resize(__buf.capacity()); - __a = &__buf[0]; - __a_end = __a + __tmp; - } - if (this->__stage2_int_loop( - *__b, - __base, - __a, - __a_end, - __dc, - __thousands_sep, - __grouping, - __g, - __g_end, - const_cast(__atoms))) - break; - } - if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) - *__g_end++ = __dc; - // Stage 3 - __v = std::__num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base); - // Digit grouping checked - __check_grouping(__grouping, __g, __g_end, __err); - // EOF checked - if (__b == __e) - __err |= ios_base::eofbit; - return __b; - } - - virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const; - - virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const { - return this->__do_get_signed(__b, __e, __iob, __err, __v); - } - - virtual iter_type - do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const { - return this->__do_get_signed(__b, __e, __iob, __err, __v); - } - - virtual iter_type - do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const { - return this->__do_get_unsigned(__b, __e, __iob, __err, __v); - } - - virtual iter_type - do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const { - return this->__do_get_unsigned(__b, __e, __iob, __err, __v); - } - - virtual iter_type - do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const { - return this->__do_get_unsigned(__b, __e, __iob, __err, __v); - } - - virtual iter_type - do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const { - return this->__do_get_unsigned(__b, __e, __iob, __err, __v); - } - - virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const { - return this->__do_get_floating_point(__b, __e, __iob, __err, __v); - } - - virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const { - return this->__do_get_floating_point(__b, __e, __iob, __err, __v); - } - - virtual iter_type - do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { - return this->__do_get_floating_point(__b, __e, __iob, __err, __v); - } - - virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const; -}; - -template -locale::id num_get<_CharT, _InputIterator>::id; - -template -_InputIterator num_get<_CharT, _InputIterator>::do_get( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { - if ((__iob.flags() & ios_base::boolalpha) == 0) { - long __lv = -1; - __b = do_get(__b, __e, __iob, __err, __lv); - switch (__lv) { - case 0: - __v = false; - break; - case 1: - __v = true; - break; - default: - __v = true; - __err = ios_base::failbit; - break; - } - return __b; - } - const ctype<_CharT>& __ct = std::use_facet >(__iob.getloc()); - const numpunct<_CharT>& __np = std::use_facet >(__iob.getloc()); - typedef typename numpunct<_CharT>::string_type string_type; - const string_type __names[2] = {__np.truename(), __np.falsename()}; - const string_type* __i = std::__scan_keyword(__b, __e, __names, __names + 2, __ct, __err); - __v = __i == __names; - return __b; -} - -template -_InputIterator num_get<_CharT, _InputIterator>::do_get( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { - // Stage 1 - int __base = 16; - // Stage 2 - char_type __atoms[__num_get_base::__int_chr_cnt]; - char_type __thousands_sep = char_type(); - string __grouping; - std::use_facet >(__iob.getloc()) - .widen(__num_get_base::__src, __num_get_base::__src + __num_get_base::__int_chr_cnt, __atoms); - string __buf; - __buf.resize(__buf.capacity()); - char* __a = &__buf[0]; - char* __a_end = __a; - unsigned __g[__num_get_base::__num_get_buf_sz]; - unsigned* __g_end = __g; - unsigned __dc = 0; - for (; __b != __e; ++__b) { - if (__a_end == __a + __buf.size()) { - size_t __tmp = __buf.size(); - __buf.resize(2 * __buf.size()); - __buf.resize(__buf.capacity()); - __a = &__buf[0]; - __a_end = __a + __tmp; - } - if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, __thousands_sep, __grouping, __g, __g_end, __atoms)) - break; - } - // Stage 3 - __buf.resize(__a_end - __a); - if (__locale::__sscanf(__buf.c_str(), _LIBCPP_GET_C_LOCALE, "%p", &__v) != 1) - __err = ios_base::failbit; - // EOF checked - if (__b == __e) - __err |= ios_base::eofbit; - return __b; -} - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_get; -# endif - -struct _LIBCPP_EXPORTED_FROM_ABI __num_put_base { -protected: - static void __format_int(char* __fmt, const char* __len, bool __signd, ios_base::fmtflags __flags); - static bool __format_float(char* __fmt, const char* __len, ios_base::fmtflags __flags); - static char* __identify_padding(char* __nb, char* __ne, const ios_base& __iob); -}; - -template -struct __num_put : protected __num_put_base { - static void __widen_and_group_int( - char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc); - static void __widen_and_group_float( - char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc); -}; - -template -void __num_put<_CharT>::__widen_and_group_int( - char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) { - const ctype<_CharT>& __ct = std::use_facet >(__loc); - const numpunct<_CharT>& __npt = std::use_facet >(__loc); - string __grouping = __npt.grouping(); - if (__grouping.empty()) { - __ct.widen(__nb, __ne, __ob); - __oe = __ob + (__ne - __nb); - } else { - __oe = __ob; - char* __nf = __nb; - if (*__nf == '-' || *__nf == '+') - *__oe++ = __ct.widen(*__nf++); - if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) { - *__oe++ = __ct.widen(*__nf++); - *__oe++ = __ct.widen(*__nf++); - } - std::reverse(__nf, __ne); - _CharT __thousands_sep = __npt.thousands_sep(); - unsigned __dc = 0; - unsigned __dg = 0; - for (char* __p = __nf; __p < __ne; ++__p) { - if (static_cast(__grouping[__dg]) > 0 && __dc == static_cast(__grouping[__dg])) { - *__oe++ = __thousands_sep; - __dc = 0; - if (__dg < __grouping.size() - 1) - ++__dg; - } - *__oe++ = __ct.widen(*__p); - ++__dc; - } - std::reverse(__ob + (__nf - __nb), __oe); - } - if (__np == __ne) - __op = __oe; - else - __op = __ob + (__np - __nb); -} - -template -void __num_put<_CharT>::__widen_and_group_float( - char* __nb, char* __np, char* __ne, _CharT* __ob, _CharT*& __op, _CharT*& __oe, const locale& __loc) { - const ctype<_CharT>& __ct = std::use_facet >(__loc); - const numpunct<_CharT>& __npt = std::use_facet >(__loc); - string __grouping = __npt.grouping(); - __oe = __ob; - char* __nf = __nb; - if (*__nf == '-' || *__nf == '+') - *__oe++ = __ct.widen(*__nf++); - char* __ns; - if (__ne - __nf >= 2 && __nf[0] == '0' && (__nf[1] == 'x' || __nf[1] == 'X')) { - *__oe++ = __ct.widen(*__nf++); - *__oe++ = __ct.widen(*__nf++); - for (__ns = __nf; __ns < __ne; ++__ns) - if (!__locale::__isxdigit(*__ns, _LIBCPP_GET_C_LOCALE)) - break; - } else { - for (__ns = __nf; __ns < __ne; ++__ns) - if (!__locale::__isdigit(*__ns, _LIBCPP_GET_C_LOCALE)) - break; - } - if (__grouping.empty()) { - __ct.widen(__nf, __ns, __oe); - __oe += __ns - __nf; - } else { - std::reverse(__nf, __ns); - _CharT __thousands_sep = __npt.thousands_sep(); - unsigned __dc = 0; - unsigned __dg = 0; - for (char* __p = __nf; __p < __ns; ++__p) { - if (__grouping[__dg] > 0 && __dc == static_cast(__grouping[__dg])) { - *__oe++ = __thousands_sep; - __dc = 0; - if (__dg < __grouping.size() - 1) - ++__dg; - } - *__oe++ = __ct.widen(*__p); - ++__dc; - } - std::reverse(__ob + (__nf - __nb), __oe); - } - for (__nf = __ns; __nf < __ne; ++__nf) { - if (*__nf == '.') { - *__oe++ = __npt.decimal_point(); - ++__nf; - break; - } else - *__oe++ = __ct.widen(*__nf); - } - __ct.widen(__nf, __ne, __oe); - __oe += __ne - __nf; - if (__np == __ne) - __op = __oe; - else - __op = __ob + (__np - __nb); -} - -extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_put; -# endif - -template > -class num_put : public locale::facet, private __num_put<_CharT> { -public: - typedef _CharT char_type; - typedef _OutputIterator iter_type; - - _LIBCPP_HIDE_FROM_ABI explicit num_put(size_t __refs = 0) : locale::facet(__refs) {} - - _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { - return do_put(__s, __iob, __fl, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const { - return do_put(__s, __iob, __fl, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { - return do_put(__s, __iob, __fl, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { - return do_put(__s, __iob, __fl, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { - return do_put(__s, __iob, __fl, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const { - return do_put(__s, __iob, __fl, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { - return do_put(__s, __iob, __fl, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const { - return do_put(__s, __iob, __fl, __v); - } - - static locale::id id; - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_put() override {} - - virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const; - virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const; - virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const; - virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long) const; - virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long) const; - virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const; - virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const; - virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const; - - template - _LIBCPP_HIDE_FROM_ABI inline _OutputIterator - __do_put_integral(iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const; - - template - _LIBCPP_HIDE_FROM_ABI inline _OutputIterator - __do_put_floating_point(iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const; -}; - -template -locale::id num_put<_CharT, _OutputIterator>::id; - -template -_OutputIterator -num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { - if ((__iob.flags() & ios_base::boolalpha) == 0) - return do_put(__s, __iob, __fl, (unsigned long)__v); - const numpunct& __np = std::use_facet >(__iob.getloc()); - typedef typename numpunct::string_type string_type; - string_type __nm = __v ? __np.truename() : __np.falsename(); - for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s) - *__s = *__i; - return __s; -} - -template -template -_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_integral( - iter_type __s, ios_base& __iob, char_type __fl, _Integral __v) const { - // Stage 1 - Get number in narrow char - - // Worst case is octal, with showbase enabled. Note that octal is always - // printed as an unsigned value. - using _Unsigned = typename make_unsigned<_Integral>::type; - _LIBCPP_CONSTEXPR const unsigned __buffer_size = - (numeric_limits<_Unsigned>::digits / 3) // 1 char per 3 bits - + ((numeric_limits<_Unsigned>::digits % 3) != 0) // round up - + 2; // base prefix + terminating null character - - char __char_buffer[__buffer_size]; - char* __buffer_ptr = __char_buffer; - - auto __flags = __iob.flags(); - - auto __basefield = (__flags & ios_base::basefield); - - // Extract base - int __base = 10; - if (__basefield == ios_base::oct) - __base = 8; - else if (__basefield == ios_base::hex) - __base = 16; - - // Print '-' and make the argument unsigned - auto __uval = std::__to_unsigned_like(__v); - if (__basefield != ios_base::oct && __basefield != ios_base::hex && __v < 0) { - *__buffer_ptr++ = '-'; - __uval = std::__complement(__uval); - } - - // Maybe add '+' prefix - if (std::is_signed<_Integral>::value && (__flags & ios_base::showpos) && __basefield != ios_base::oct && - __basefield != ios_base::hex && __v >= 0) - *__buffer_ptr++ = '+'; - - // Add base prefix - if (__v != 0 && __flags & ios_base::showbase) { - if (__basefield == ios_base::oct) { - *__buffer_ptr++ = '0'; - } else if (__basefield == ios_base::hex) { - *__buffer_ptr++ = '0'; - *__buffer_ptr++ = (__flags & ios_base::uppercase ? 'X' : 'x'); - } - } - - auto __res = std::__to_chars_integral(__buffer_ptr, __char_buffer + __buffer_size, __uval, __base); - _LIBCPP_ASSERT_INTERNAL(__res.__ec == std::errc(0), "to_chars: invalid maximum buffer size computed?"); - - // Make letters uppercase - if (__flags & ios_base::hex && __flags & ios_base::uppercase) { - for (; __buffer_ptr != __res.__ptr; ++__buffer_ptr) - *__buffer_ptr = std::__hex_to_upper(*__buffer_ptr); - } - - char* __np = this->__identify_padding(__char_buffer, __res.__ptr, __iob); - // Stage 2 - Widen __nar while adding thousands separators - char_type __o[2 * (__buffer_size - 1) - 1]; - char_type* __op; // pad here - char_type* __oe; // end of output - this->__widen_and_group_int(__char_buffer, __np, __res.__ptr, __o, __op, __oe, __iob.getloc()); - // [__o, __oe) contains thousands_sep'd wide number - // Stage 3 & 4 - return std::__pad_and_output(__s, __o, __op, __oe, __iob, __fl); -} - -template -_OutputIterator -num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const { - return this->__do_put_integral(__s, __iob, __fl, __v); -} - -template -_OutputIterator -num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { - return this->__do_put_integral(__s, __iob, __fl, __v); -} - -template -_OutputIterator -num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { - return this->__do_put_integral(__s, __iob, __fl, __v); -} - -template -_OutputIterator -num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { - return this->__do_put_integral(__s, __iob, __fl, __v); -} - -template -template -_LIBCPP_HIDE_FROM_ABI inline _OutputIterator num_put<_CharT, _OutputIterator>::__do_put_floating_point( - iter_type __s, ios_base& __iob, char_type __fl, _Float __v, char const* __len) const { - // Stage 1 - Get number in narrow char - char __fmt[8] = {'%', 0}; - bool __specify_precision = this->__format_float(__fmt + 1, __len, __iob.flags()); - const unsigned __nbuf = 30; - char __nar[__nbuf]; - char* __nb = __nar; - int __nc; - _LIBCPP_DIAGNOSTIC_PUSH - _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") - _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") - if (__specify_precision) - __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v); - else - __nc = __locale::__snprintf(__nb, __nbuf, _LIBCPP_GET_C_LOCALE, __fmt, __v); - unique_ptr __nbh(nullptr, free); - if (__nc > static_cast(__nbuf - 1)) { - if (__specify_precision) - __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, (int)__iob.precision(), __v); - else - __nc = __locale::__asprintf(&__nb, _LIBCPP_GET_C_LOCALE, __fmt, __v); - if (__nc == -1) - std::__throw_bad_alloc(); - __nbh.reset(__nb); - } - _LIBCPP_DIAGNOSTIC_POP - char* __ne = __nb + __nc; - char* __np = this->__identify_padding(__nb, __ne, __iob); - // Stage 2 - Widen __nar while adding thousands separators - char_type __o[2 * (__nbuf - 1) - 1]; - char_type* __ob = __o; - unique_ptr __obh(0, free); - if (__nb != __nar) { - __ob = (char_type*)malloc(2 * static_cast(__nc) * sizeof(char_type)); - if (__ob == 0) - std::__throw_bad_alloc(); - __obh.reset(__ob); - } - char_type* __op; // pad here - char_type* __oe; // end of output - this->__widen_and_group_float(__nb, __np, __ne, __ob, __op, __oe, __iob.getloc()); - // [__o, __oe) contains thousands_sep'd wide number - // Stage 3 & 4 - __s = std::__pad_and_output(__s, __ob, __op, __oe, __iob, __fl); - return __s; -} - -template -_OutputIterator -num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const { - return this->__do_put_floating_point(__s, __iob, __fl, __v, ""); -} - -template -_OutputIterator -num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { - return this->__do_put_floating_point(__s, __iob, __fl, __v, "L"); -} - -template -_OutputIterator -num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const { - auto __flags = __iob.flags(); - __iob.flags((__flags & ~ios_base::basefield & ~ios_base::uppercase) | ios_base::hex | ios_base::showbase); - auto __res = __do_put_integral(__s, __iob, __fl, reinterpret_cast(__v)); - __iob.flags(__flags); - return __res; -} - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS num_put; -# endif - -template -_LIBCPP_HIDE_FROM_ABI int __get_up_to_n_digits( - _InputIterator& __b, _InputIterator __e, ios_base::iostate& __err, const ctype<_CharT>& __ct, int __n) { - // Precondition: __n >= 1 - if (__b == __e) { - __err |= ios_base::eofbit | ios_base::failbit; - return 0; - } - // get first digit - _CharT __c = *__b; - if (!__ct.is(ctype_base::digit, __c)) { - __err |= ios_base::failbit; - return 0; - } - int __r = __ct.narrow(__c, 0) - '0'; - for (++__b, (void)--__n; __b != __e && __n > 0; ++__b, (void)--__n) { - // get next digit - __c = *__b; - if (!__ct.is(ctype_base::digit, __c)) - return __r; - __r = __r * 10 + __ct.narrow(__c, 0) - '0'; - } - if (__b == __e) - __err |= ios_base::eofbit; - return __r; -} - -class _LIBCPP_EXPORTED_FROM_ABI time_base { -public: - enum dateorder { no_order, dmy, mdy, ymd, ydm }; -}; - -template -class __time_get_c_storage { -protected: - typedef basic_string<_CharT> string_type; - - virtual const string_type* __weeks() const; - virtual const string_type* __months() const; - virtual const string_type* __am_pm() const; - virtual const string_type& __c() const; - virtual const string_type& __r() const; - virtual const string_type& __x() const; - virtual const string_type& __X() const; - - _LIBCPP_HIDE_FROM_ABI ~__time_get_c_storage() {} -}; - -template <> -_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__weeks() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__months() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const string* __time_get_c_storage::__am_pm() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__c() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__r() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__x() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const string& __time_get_c_storage::__X() const; - -# if _LIBCPP_HAS_WIDE_CHARACTERS -template <> -_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__weeks() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__months() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const wstring* __time_get_c_storage::__am_pm() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__c() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__r() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__x() const; -template <> -_LIBCPP_EXPORTED_FROM_ABI const wstring& __time_get_c_storage::__X() const; -# endif - -template > -class time_get : public locale::facet, public time_base, private __time_get_c_storage<_CharT> { -public: - typedef _CharT char_type; - typedef _InputIterator iter_type; - typedef time_base::dateorder dateorder; - typedef basic_string string_type; - - _LIBCPP_HIDE_FROM_ABI explicit time_get(size_t __refs = 0) : locale::facet(__refs) {} - - _LIBCPP_HIDE_FROM_ABI dateorder date_order() const { return this->do_date_order(); } - - _LIBCPP_HIDE_FROM_ABI iter_type - get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { - return do_get_time(__b, __e, __iob, __err, __tm); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { - return do_get_date(__b, __e, __iob, __err, __tm); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { - return do_get_weekday(__b, __e, __iob, __err, __tm); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { - return do_get_monthname(__b, __e, __iob, __err, __tm); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { - return do_get_year(__b, __e, __iob, __err, __tm); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod = 0) - const { - return do_get(__b, __e, __iob, __err, __tm, __fmt, __mod); - } - - iter_type - get(iter_type __b, - iter_type __e, - ios_base& __iob, - ios_base::iostate& __err, - tm* __tm, - const char_type* __fmtb, - const char_type* __fmte) const; - - static locale::id id; - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get() override {} - - virtual dateorder do_date_order() const; - virtual iter_type - do_get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; - virtual iter_type - do_get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; - virtual iter_type - do_get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; - virtual iter_type - do_get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; - virtual iter_type - do_get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const; - virtual iter_type do_get( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char __mod) const; - -private: - void __get_white_space(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void __get_percent(iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - - void __get_weekdayname( - int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void __get_monthname( - int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void __get_day(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void - __get_month(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void - __get_year(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void - __get_year4(int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void - __get_hour(int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void - __get_12_hour(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void - __get_am_pm(int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void - __get_minute(int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void - __get_second(int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void - __get_weekday(int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; - void __get_day_year_num( - int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const; -}; - -template -locale::id time_get<_CharT, _InputIterator>::id; - -// time_get primitives - -template -void time_get<_CharT, _InputIterator>::__get_weekdayname( - int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - // Note: ignoring case comes from the POSIX strptime spec - const string_type* __wk = this->__weeks(); - ptrdiff_t __i = std::__scan_keyword(__b, __e, __wk, __wk + 14, __ct, __err, false) - __wk; - if (__i < 14) - __w = __i % 7; -} - -template -void time_get<_CharT, _InputIterator>::__get_monthname( - int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - // Note: ignoring case comes from the POSIX strptime spec - const string_type* __month = this->__months(); - ptrdiff_t __i = std::__scan_keyword(__b, __e, __month, __month + 24, __ct, __err, false) - __month; - if (__i < 24) - __m = __i % 12; -} - -template -void time_get<_CharT, _InputIterator>::__get_day( - int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); - if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 31) - __d = __t; - else - __err |= ios_base::failbit; -} - -template -void time_get<_CharT, _InputIterator>::__get_month( - int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2) - 1; - if (!(__err & ios_base::failbit) && 0 <= __t && __t <= 11) - __m = __t; - else - __err |= ios_base::failbit; -} - -template -void time_get<_CharT, _InputIterator>::__get_year( - int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4); - if (!(__err & ios_base::failbit)) { - if (__t < 69) - __t += 2000; - else if (69 <= __t && __t <= 99) - __t += 1900; - __y = __t - 1900; - } -} - -template -void time_get<_CharT, _InputIterator>::__get_year4( - int& __y, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 4); - if (!(__err & ios_base::failbit)) - __y = __t - 1900; -} - -template -void time_get<_CharT, _InputIterator>::__get_hour( - int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); - if (!(__err & ios_base::failbit) && __t <= 23) - __h = __t; - else - __err |= ios_base::failbit; -} - -template -void time_get<_CharT, _InputIterator>::__get_12_hour( - int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); - if (!(__err & ios_base::failbit) && 1 <= __t && __t <= 12) - __h = __t; - else - __err |= ios_base::failbit; -} - -template -void time_get<_CharT, _InputIterator>::__get_minute( - int& __m, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); - if (!(__err & ios_base::failbit) && __t <= 59) - __m = __t; - else - __err |= ios_base::failbit; -} - -template -void time_get<_CharT, _InputIterator>::__get_second( - int& __s, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 2); - if (!(__err & ios_base::failbit) && __t <= 60) - __s = __t; - else - __err |= ios_base::failbit; -} - -template -void time_get<_CharT, _InputIterator>::__get_weekday( - int& __w, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 1); - if (!(__err & ios_base::failbit) && __t <= 6) - __w = __t; - else - __err |= ios_base::failbit; -} - -template -void time_get<_CharT, _InputIterator>::__get_day_year_num( - int& __d, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - int __t = std::__get_up_to_n_digits(__b, __e, __err, __ct, 3); - if (!(__err & ios_base::failbit) && __t <= 365) - __d = __t; - else - __err |= ios_base::failbit; -} - -template -void time_get<_CharT, _InputIterator>::__get_white_space( - iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b) - ; - if (__b == __e) - __err |= ios_base::eofbit; -} - -template -void time_get<_CharT, _InputIterator>::__get_am_pm( - int& __h, iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - const string_type* __ap = this->__am_pm(); - if (__ap[0].size() + __ap[1].size() == 0) { - __err |= ios_base::failbit; - return; - } - ptrdiff_t __i = std::__scan_keyword(__b, __e, __ap, __ap + 2, __ct, __err, false) - __ap; - if (__i == 0 && __h == 12) - __h = 0; - else if (__i == 1 && __h < 12) - __h += 12; -} - -template -void time_get<_CharT, _InputIterator>::__get_percent( - iter_type& __b, iter_type __e, ios_base::iostate& __err, const ctype& __ct) const { - if (__b == __e) { - __err |= ios_base::eofbit | ios_base::failbit; - return; - } - if (__ct.narrow(*__b, 0) != '%') - __err |= ios_base::failbit; - else if (++__b == __e) - __err |= ios_base::eofbit; -} - -// time_get end primitives - -template -_InputIterator time_get<_CharT, _InputIterator>::get( - iter_type __b, - iter_type __e, - ios_base& __iob, - ios_base::iostate& __err, - tm* __tm, - const char_type* __fmtb, - const char_type* __fmte) const { - const ctype& __ct = std::use_facet >(__iob.getloc()); - __err = ios_base::goodbit; - while (__fmtb != __fmte && __err == ios_base::goodbit) { - if (__b == __e) { - __err = ios_base::failbit; - break; - } - if (__ct.narrow(*__fmtb, 0) == '%') { - if (++__fmtb == __fmte) { - __err = ios_base::failbit; - break; - } - char __cmd = __ct.narrow(*__fmtb, 0); - char __opt = '\0'; - if (__cmd == 'E' || __cmd == '0') { - if (++__fmtb == __fmte) { - __err = ios_base::failbit; - break; - } - __opt = __cmd; - __cmd = __ct.narrow(*__fmtb, 0); - } - __b = do_get(__b, __e, __iob, __err, __tm, __cmd, __opt); - ++__fmtb; - } else if (__ct.is(ctype_base::space, *__fmtb)) { - for (++__fmtb; __fmtb != __fmte && __ct.is(ctype_base::space, *__fmtb); ++__fmtb) - ; - for (; __b != __e && __ct.is(ctype_base::space, *__b); ++__b) - ; - } else if (__ct.toupper(*__b) == __ct.toupper(*__fmtb)) { - ++__b; - ++__fmtb; - } else - __err = ios_base::failbit; - } - if (__b == __e) - __err |= ios_base::eofbit; - return __b; -} - -template -typename time_get<_CharT, _InputIterator>::dateorder time_get<_CharT, _InputIterator>::do_date_order() const { - return mdy; -} - -template -_InputIterator time_get<_CharT, _InputIterator>::do_get_time( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { - const char_type __fmt[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; - return get(__b, __e, __iob, __err, __tm, __fmt, __fmt + sizeof(__fmt) / sizeof(__fmt[0])); -} - -template -_InputIterator time_get<_CharT, _InputIterator>::do_get_date( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { - const string_type& __fmt = this->__x(); - return get(__b, __e, __iob, __err, __tm, __fmt.data(), __fmt.data() + __fmt.size()); -} - -template -_InputIterator time_get<_CharT, _InputIterator>::do_get_weekday( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { - const ctype& __ct = std::use_facet >(__iob.getloc()); - __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct); - return __b; -} - -template -_InputIterator time_get<_CharT, _InputIterator>::do_get_monthname( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { - const ctype& __ct = std::use_facet >(__iob.getloc()); - __get_monthname(__tm->tm_mon, __b, __e, __err, __ct); - return __b; -} - -template -_InputIterator time_get<_CharT, _InputIterator>::do_get_year( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { - const ctype& __ct = std::use_facet >(__iob.getloc()); - __get_year(__tm->tm_year, __b, __e, __err, __ct); - return __b; -} - -template -_InputIterator time_get<_CharT, _InputIterator>::do_get( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm, char __fmt, char) const { - __err = ios_base::goodbit; - const ctype& __ct = std::use_facet >(__iob.getloc()); - switch (__fmt) { - case 'a': - case 'A': - __get_weekdayname(__tm->tm_wday, __b, __e, __err, __ct); - break; - case 'b': - case 'B': - case 'h': - __get_monthname(__tm->tm_mon, __b, __e, __err, __ct); - break; - case 'c': { - const string_type& __fm = this->__c(); - __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size()); - } break; - case 'd': - case 'e': - __get_day(__tm->tm_mday, __b, __e, __err, __ct); - break; - case 'D': { - const char_type __fm[] = {'%', 'm', '/', '%', 'd', '/', '%', 'y'}; - __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); - } break; - case 'F': { - const char_type __fm[] = {'%', 'Y', '-', '%', 'm', '-', '%', 'd'}; - __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); - } break; - case 'H': - __get_hour(__tm->tm_hour, __b, __e, __err, __ct); - break; - case 'I': - __get_12_hour(__tm->tm_hour, __b, __e, __err, __ct); - break; - case 'j': - __get_day_year_num(__tm->tm_yday, __b, __e, __err, __ct); - break; - case 'm': - __get_month(__tm->tm_mon, __b, __e, __err, __ct); - break; - case 'M': - __get_minute(__tm->tm_min, __b, __e, __err, __ct); - break; - case 'n': - case 't': - __get_white_space(__b, __e, __err, __ct); - break; - case 'p': - __get_am_pm(__tm->tm_hour, __b, __e, __err, __ct); - break; - case 'r': { - const char_type __fm[] = {'%', 'I', ':', '%', 'M', ':', '%', 'S', ' ', '%', 'p'}; - __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); - } break; - case 'R': { - const char_type __fm[] = {'%', 'H', ':', '%', 'M'}; - __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); - } break; - case 'S': - __get_second(__tm->tm_sec, __b, __e, __err, __ct); - break; - case 'T': { - const char_type __fm[] = {'%', 'H', ':', '%', 'M', ':', '%', 'S'}; - __b = get(__b, __e, __iob, __err, __tm, __fm, __fm + sizeof(__fm) / sizeof(__fm[0])); - } break; - case 'w': - __get_weekday(__tm->tm_wday, __b, __e, __err, __ct); - break; - case 'x': - return do_get_date(__b, __e, __iob, __err, __tm); - case 'X': { - const string_type& __fm = this->__X(); - __b = get(__b, __e, __iob, __err, __tm, __fm.data(), __fm.data() + __fm.size()); - } break; - case 'y': - __get_year(__tm->tm_year, __b, __e, __err, __ct); - break; - case 'Y': - __get_year4(__tm->tm_year, __b, __e, __err, __ct); - break; - case '%': - __get_percent(__b, __e, __err, __ct); - break; - default: - __err |= ios_base::failbit; - } - return __b; -} - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get; -# endif - -class _LIBCPP_EXPORTED_FROM_ABI __time_get { -protected: - __locale::__locale_t __loc_; - - __time_get(const char* __nm); - __time_get(const string& __nm); - ~__time_get(); -}; - -template -class __time_get_storage : public __time_get { -protected: - typedef basic_string<_CharT> string_type; - - string_type __weeks_[14]; - string_type __months_[24]; - string_type __am_pm_[2]; - string_type __c_; - string_type __r_; - string_type __x_; - string_type __X_; - - explicit __time_get_storage(const char* __nm); - explicit __time_get_storage(const string& __nm); - - _LIBCPP_HIDE_FROM_ABI ~__time_get_storage() {} - - time_base::dateorder __do_date_order() const; - -private: - void init(const ctype<_CharT>&); - string_type __analyze(char __fmt, const ctype<_CharT>&); -}; - -# define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \ - template <> \ - _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \ - template <> \ - _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \ - template <> \ - _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \ - template <> \ - _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ - template <> \ - _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze( \ - char, const ctype<_CharT>&); \ - extern template _LIBCPP_EXPORTED_FROM_ABI time_base::dateorder __time_get_storage<_CharT>::__do_date_order() \ - const; \ - extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const char*); \ - extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::__time_get_storage(const string&); \ - extern template _LIBCPP_EXPORTED_FROM_ABI void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \ - extern template _LIBCPP_EXPORTED_FROM_ABI __time_get_storage<_CharT>::string_type \ - __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \ - /**/ - -_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char) -# if _LIBCPP_HAS_WIDE_CHARACTERS -_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t) -# endif -# undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION - -template > -class time_get_byname : public time_get<_CharT, _InputIterator>, private __time_get_storage<_CharT> { -public: - typedef time_base::dateorder dateorder; - typedef _InputIterator iter_type; - typedef _CharT char_type; - typedef basic_string string_type; - - _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const char* __nm, size_t __refs = 0) - : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {} - _LIBCPP_HIDE_FROM_ABI explicit time_get_byname(const string& __nm, size_t __refs = 0) - : time_get<_CharT, _InputIterator>(__refs), __time_get_storage<_CharT>(__nm) {} - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_get_byname() override {} - - _LIBCPP_HIDE_FROM_ABI_VIRTUAL dateorder do_date_order() const override { return this->__do_date_order(); } - -private: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __weeks() const override { return this->__weeks_; } - _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __months() const override { return this->__months_; } - _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type* __am_pm() const override { return this->__am_pm_; } - _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __c() const override { return this->__c_; } - _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __r() const override { return this->__r_; } - _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __x() const override { return this->__x_; } - _LIBCPP_HIDE_FROM_ABI_VIRTUAL const string_type& __X() const override { return this->__X_; } -}; - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_get_byname; -# endif - -class _LIBCPP_EXPORTED_FROM_ABI __time_put { - __locale::__locale_t __loc_; - -protected: - _LIBCPP_HIDE_FROM_ABI __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {} - __time_put(const char* __nm); - __time_put(const string& __nm); - ~__time_put(); - void __do_put(char* __nb, char*& __ne, const tm* __tm, char __fmt, char __mod) const; -# if _LIBCPP_HAS_WIDE_CHARACTERS - void __do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, char __fmt, char __mod) const; -# endif -}; - -template > -class time_put : public locale::facet, private __time_put { -public: - typedef _CharT char_type; - typedef _OutputIterator iter_type; - - _LIBCPP_HIDE_FROM_ABI explicit time_put(size_t __refs = 0) : locale::facet(__refs) {} - - iter_type - put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe) - const; - - _LIBCPP_HIDE_FROM_ABI iter_type - put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, char __fmt, char __mod = 0) const { - return do_put(__s, __iob, __fl, __tm, __fmt, __mod); - } - - static locale::id id; - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put() override {} - virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const; - - _LIBCPP_HIDE_FROM_ABI explicit time_put(const char* __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {} - _LIBCPP_HIDE_FROM_ABI explicit time_put(const string& __nm, size_t __refs) - : locale::facet(__refs), __time_put(__nm) {} -}; - -template -locale::id time_put<_CharT, _OutputIterator>::id; - -template -_OutputIterator time_put<_CharT, _OutputIterator>::put( - iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe) - const { - const ctype& __ct = std::use_facet >(__iob.getloc()); - for (; __pb != __pe; ++__pb) { - if (__ct.narrow(*__pb, 0) == '%') { - if (++__pb == __pe) { - *__s++ = __pb[-1]; - break; - } - char __mod = 0; - char __fmt = __ct.narrow(*__pb, 0); - if (__fmt == 'E' || __fmt == 'O') { - if (++__pb == __pe) { - *__s++ = __pb[-2]; - *__s++ = __pb[-1]; - break; - } - __mod = __fmt; - __fmt = __ct.narrow(*__pb, 0); - } - __s = do_put(__s, __iob, __fl, __tm, __fmt, __mod); - } else - *__s++ = *__pb; - } - return __s; -} - -template -_OutputIterator time_put<_CharT, _OutputIterator>::do_put( - iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const { - char_type __nar[100]; - char_type* __nb = __nar; - char_type* __ne = __nb + 100; - __do_put(__nb, __ne, __tm, __fmt, __mod); - return std::copy(__nb, __ne, __s); -} - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put; -# endif - -template > -class time_put_byname : public time_put<_CharT, _OutputIterator> { -public: - _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const char* __nm, size_t __refs = 0) - : time_put<_CharT, _OutputIterator>(__nm, __refs) {} - - _LIBCPP_HIDE_FROM_ABI explicit time_put_byname(const string& __nm, size_t __refs = 0) - : time_put<_CharT, _OutputIterator>(__nm, __refs) {} - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~time_put_byname() override {} -}; - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS time_put_byname; -# endif - -// money_base - -class _LIBCPP_EXPORTED_FROM_ABI money_base { -public: - enum part { none, space, symbol, sign, value }; - struct pattern { - char field[4]; - }; - - _LIBCPP_HIDE_FROM_ABI money_base() {} -}; - -// moneypunct - -template -class moneypunct : public locale::facet, public money_base { -public: - typedef _CharT char_type; - typedef basic_string string_type; - - _LIBCPP_HIDE_FROM_ABI explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {} - - _LIBCPP_HIDE_FROM_ABI char_type decimal_point() const { return do_decimal_point(); } - _LIBCPP_HIDE_FROM_ABI char_type thousands_sep() const { return do_thousands_sep(); } - _LIBCPP_HIDE_FROM_ABI string grouping() const { return do_grouping(); } - _LIBCPP_HIDE_FROM_ABI string_type curr_symbol() const { return do_curr_symbol(); } - _LIBCPP_HIDE_FROM_ABI string_type positive_sign() const { return do_positive_sign(); } - _LIBCPP_HIDE_FROM_ABI string_type negative_sign() const { return do_negative_sign(); } - _LIBCPP_HIDE_FROM_ABI int frac_digits() const { return do_frac_digits(); } - _LIBCPP_HIDE_FROM_ABI pattern pos_format() const { return do_pos_format(); } - _LIBCPP_HIDE_FROM_ABI pattern neg_format() const { return do_neg_format(); } - - static locale::id id; - static const bool intl = _International; - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct() override {} - - virtual char_type do_decimal_point() const { return numeric_limits::max(); } - virtual char_type do_thousands_sep() const { return numeric_limits::max(); } - virtual string do_grouping() const { return string(); } - virtual string_type do_curr_symbol() const { return string_type(); } - virtual string_type do_positive_sign() const { return string_type(); } - virtual string_type do_negative_sign() const { return string_type(1, '-'); } - virtual int do_frac_digits() const { return 0; } - virtual pattern do_pos_format() const { - pattern __p = {{symbol, sign, none, value}}; - return __p; - } - virtual pattern do_neg_format() const { - pattern __p = {{symbol, sign, none, value}}; - return __p; - } -}; - -template -locale::id moneypunct<_CharT, _International>::id; - -template -const bool moneypunct<_CharT, _International>::intl; - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct; -# endif - -// moneypunct_byname - -template -class moneypunct_byname : public moneypunct<_CharT, _International> { -public: - typedef money_base::pattern pattern; - typedef _CharT char_type; - typedef basic_string string_type; - - _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const char* __nm, size_t __refs = 0) - : moneypunct<_CharT, _International>(__refs) { - init(__nm); - } - - _LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const string& __nm, size_t __refs = 0) - : moneypunct<_CharT, _International>(__refs) { - init(__nm.c_str()); - } - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct_byname() override {} - - char_type do_decimal_point() const override { return __decimal_point_; } - char_type do_thousands_sep() const override { return __thousands_sep_; } - string do_grouping() const override { return __grouping_; } - string_type do_curr_symbol() const override { return __curr_symbol_; } - string_type do_positive_sign() const override { return __positive_sign_; } - string_type do_negative_sign() const override { return __negative_sign_; } - int do_frac_digits() const override { return __frac_digits_; } - pattern do_pos_format() const override { return __pos_format_; } - pattern do_neg_format() const override { return __neg_format_; } - -private: - char_type __decimal_point_; - char_type __thousands_sep_; - string __grouping_; - string_type __curr_symbol_; - string_type __positive_sign_; - string_type __negative_sign_; - int __frac_digits_; - pattern __pos_format_; - pattern __neg_format_; - - void init(const char*); -}; - -template <> -_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); -template <> -_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; - -# if _LIBCPP_HAS_WIDE_CHARACTERS -template <> -_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); -template <> -_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname::init(const char*); -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname; -# endif - -// money_get - -template -class __money_get { -protected: - typedef _CharT char_type; - typedef basic_string string_type; - - _LIBCPP_HIDE_FROM_ABI __money_get() {} - - static void __gather_info( - bool __intl, - const locale& __loc, - money_base::pattern& __pat, - char_type& __dp, - char_type& __ts, - string& __grp, - string_type& __sym, - string_type& __psn, - string_type& __nsn, - int& __fd); -}; - -template -void __money_get<_CharT>::__gather_info( - bool __intl, - const locale& __loc, - money_base::pattern& __pat, - char_type& __dp, - char_type& __ts, - string& __grp, - string_type& __sym, - string_type& __psn, - string_type& __nsn, - int& __fd) { - if (__intl) { - const moneypunct& __mp = std::use_facet >(__loc); - __pat = __mp.neg_format(); - __nsn = __mp.negative_sign(); - __psn = __mp.positive_sign(); - __dp = __mp.decimal_point(); - __ts = __mp.thousands_sep(); - __grp = __mp.grouping(); - __sym = __mp.curr_symbol(); - __fd = __mp.frac_digits(); - } else { - const moneypunct& __mp = std::use_facet >(__loc); - __pat = __mp.neg_format(); - __nsn = __mp.negative_sign(); - __psn = __mp.positive_sign(); - __dp = __mp.decimal_point(); - __ts = __mp.thousands_sep(); - __grp = __mp.grouping(); - __sym = __mp.curr_symbol(); - __fd = __mp.frac_digits(); - } -} - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get; -# endif - -template > -class money_get : public locale::facet, private __money_get<_CharT> { -public: - typedef _CharT char_type; - typedef _InputIterator iter_type; - typedef basic_string string_type; - - _LIBCPP_HIDE_FROM_ABI explicit money_get(size_t __refs = 0) : locale::facet(__refs) {} - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { - return do_get(__b, __e, __intl, __iob, __err, __v); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const { - return do_get(__b, __e, __intl, __iob, __err, __v); - } - - static locale::id id; - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_get() override {} - - virtual iter_type - do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const; - virtual iter_type - do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const; - -private: - static bool __do_get( - iter_type& __b, - iter_type __e, - bool __intl, - const locale& __loc, - ios_base::fmtflags __flags, - ios_base::iostate& __err, - bool& __neg, - const ctype& __ct, - unique_ptr& __wb, - char_type*& __wn, - char_type* __we); -}; - -template -locale::id money_get<_CharT, _InputIterator>::id; - -_LIBCPP_EXPORTED_FROM_ABI void __do_nothing(void*); - -template -_LIBCPP_HIDE_FROM_ABI void __double_or_nothing(unique_ptr<_Tp, void (*)(void*)>& __b, _Tp*& __n, _Tp*& __e) { - bool __owns = __b.get_deleter() != __do_nothing; - size_t __cur_cap = static_cast(__e - __b.get()) * sizeof(_Tp); - size_t __new_cap = __cur_cap < numeric_limits::max() / 2 ? 2 * __cur_cap : numeric_limits::max(); - if (__new_cap == 0) - __new_cap = sizeof(_Tp); - size_t __n_off = static_cast(__n - __b.get()); - _Tp* __t = (_Tp*)std::realloc(__owns ? __b.get() : 0, __new_cap); - if (__t == 0) - std::__throw_bad_alloc(); - if (__owns) - __b.release(); - else - std::memcpy(__t, __b.get(), __cur_cap); - __b = unique_ptr<_Tp, void (*)(void*)>(__t, free); - __new_cap /= sizeof(_Tp); - __n = __b.get() + __n_off; - __e = __b.get() + __new_cap; -} - -// true == success -template -bool money_get<_CharT, _InputIterator>::__do_get( - iter_type& __b, - iter_type __e, - bool __intl, - const locale& __loc, - ios_base::fmtflags __flags, - ios_base::iostate& __err, - bool& __neg, - const ctype& __ct, - unique_ptr& __wb, - char_type*& __wn, - char_type* __we) { - if (__b == __e) { - __err |= ios_base::failbit; - return false; - } - const unsigned __bz = 100; - unsigned __gbuf[__bz]; - unique_ptr __gb(__gbuf, __do_nothing); - unsigned* __gn = __gb.get(); - unsigned* __ge = __gn + __bz; - money_base::pattern __pat; - char_type __dp; - char_type __ts; - string __grp; - string_type __sym; - string_type __psn; - string_type __nsn; - // Capture the spaces read into money_base::{space,none} so they - // can be compared to initial spaces in __sym. - string_type __spaces; - int __fd; - __money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp, __sym, __psn, __nsn, __fd); - const string_type* __trailing_sign = 0; - __wn = __wb.get(); - for (unsigned __p = 0; __p < 4 && __b != __e; ++__p) { - switch (__pat.field[__p]) { - case money_base::space: - if (__p != 3) { - if (__ct.is(ctype_base::space, *__b)) - __spaces.push_back(*__b++); - else { - __err |= ios_base::failbit; - return false; - } - } - [[__fallthrough__]]; - case money_base::none: - if (__p != 3) { - while (__b != __e && __ct.is(ctype_base::space, *__b)) - __spaces.push_back(*__b++); - } - break; - case money_base::sign: - if (__psn.size() > 0 && *__b == __psn[0]) { - ++__b; - __neg = false; - if (__psn.size() > 1) - __trailing_sign = std::addressof(__psn); - break; - } - if (__nsn.size() > 0 && *__b == __nsn[0]) { - ++__b; - __neg = true; - if (__nsn.size() > 1) - __trailing_sign = std::addressof(__nsn); - break; - } - if (__psn.size() > 0 && __nsn.size() > 0) { // sign is required - __err |= ios_base::failbit; - return false; - } - if (__psn.size() == 0 && __nsn.size() == 0) - // locale has no way of specifying a sign. Use the initial value of __neg as a default - break; - __neg = (__nsn.size() == 0); - break; - case money_base::symbol: { - bool __more_needed = - __trailing_sign || (__p < 2) || (__p == 2 && __pat.field[3] != static_cast(money_base::none)); - bool __sb = (__flags & ios_base::showbase) != 0; - if (__sb || __more_needed) { - typename string_type::const_iterator __sym_space_end = __sym.begin(); - if (__p > 0 && (__pat.field[__p - 1] == money_base::none || __pat.field[__p - 1] == money_base::space)) { - // Match spaces we've already read against spaces at - // the beginning of __sym. - while (__sym_space_end != __sym.end() && __ct.is(ctype_base::space, *__sym_space_end)) - ++__sym_space_end; - const size_t __num_spaces = __sym_space_end - __sym.begin(); - if (__num_spaces > __spaces.size() || - !std::equal(__spaces.end() - __num_spaces, __spaces.end(), __sym.begin())) { - // No match. Put __sym_space_end back at the - // beginning of __sym, which will prevent a - // match in the next loop. - __sym_space_end = __sym.begin(); - } - } - typename string_type::const_iterator __sym_curr_char = __sym_space_end; - while (__sym_curr_char != __sym.end() && __b != __e && *__b == *__sym_curr_char) { - ++__b; - ++__sym_curr_char; - } - if (__sb && __sym_curr_char != __sym.end()) { - __err |= ios_base::failbit; - return false; - } - } - } break; - case money_base::value: { - unsigned __ng = 0; - for (; __b != __e; ++__b) { - char_type __c = *__b; - if (__ct.is(ctype_base::digit, __c)) { - if (__wn == __we) - std::__double_or_nothing(__wb, __wn, __we); - *__wn++ = __c; - ++__ng; - } else if (__grp.size() > 0 && __ng > 0 && __c == __ts) { - if (__gn == __ge) - std::__double_or_nothing(__gb, __gn, __ge); - *__gn++ = __ng; - __ng = 0; - } else - break; - } - if (__gb.get() != __gn && __ng > 0) { - if (__gn == __ge) - std::__double_or_nothing(__gb, __gn, __ge); - *__gn++ = __ng; - } - if (__fd > 0) { - if (__b == __e || *__b != __dp) { - __err |= ios_base::failbit; - return false; - } - for (++__b; __fd > 0; --__fd, ++__b) { - if (__b == __e || !__ct.is(ctype_base::digit, *__b)) { - __err |= ios_base::failbit; - return false; - } - if (__wn == __we) - std::__double_or_nothing(__wb, __wn, __we); - *__wn++ = *__b; - } - } - if (__wn == __wb.get()) { - __err |= ios_base::failbit; - return false; - } - } break; - } - } - if (__trailing_sign) { - for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b) { - if (__b == __e || *__b != (*__trailing_sign)[__i]) { - __err |= ios_base::failbit; - return false; - } - } - } - if (__gb.get() != __gn) { - ios_base::iostate __et = ios_base::goodbit; - __check_grouping(__grp, __gb.get(), __gn, __et); - if (__et) { - __err |= ios_base::failbit; - return false; - } - } - return true; -} - -template -_InputIterator money_get<_CharT, _InputIterator>::do_get( - iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { - const int __bz = 100; - char_type __wbuf[__bz]; - unique_ptr __wb(__wbuf, __do_nothing); - char_type* __wn; - char_type* __we = __wbuf + __bz; - locale __loc = __iob.getloc(); - const ctype& __ct = std::use_facet >(__loc); - bool __neg = false; - if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) { - const char __src[] = "0123456789"; - char_type __atoms[sizeof(__src) - 1]; - __ct.widen(__src, __src + (sizeof(__src) - 1), __atoms); - char __nbuf[__bz]; - char* __nc = __nbuf; - const char* __nc_in = __nc; - unique_ptr __h(nullptr, free); - if (__wn - __wb.get() > __bz - 2) { - __h.reset((char*)malloc(static_cast(__wn - __wb.get() + 2))); - if (__h.get() == nullptr) - std::__throw_bad_alloc(); - __nc = __h.get(); - __nc_in = __nc; - } - if (__neg) - *__nc++ = '-'; - for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc) - *__nc = __src[std::find(__atoms, std::end(__atoms), *__w) - __atoms]; - *__nc = char(); - if (sscanf(__nc_in, "%Lf", &__v) != 1) - std::__throw_runtime_error("money_get error"); - } - if (__b == __e) - __err |= ios_base::eofbit; - return __b; -} - -template -_InputIterator money_get<_CharT, _InputIterator>::do_get( - iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const { - const int __bz = 100; - char_type __wbuf[__bz]; - unique_ptr __wb(__wbuf, __do_nothing); - char_type* __wn; - char_type* __we = __wbuf + __bz; - locale __loc = __iob.getloc(); - const ctype& __ct = std::use_facet >(__loc); - bool __neg = false; - if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) { - __v.clear(); - if (__neg) - __v.push_back(__ct.widen('-')); - char_type __z = __ct.widen('0'); - char_type* __w; - for (__w = __wb.get(); __w < __wn - 1; ++__w) - if (*__w != __z) - break; - __v.append(__w, __wn); - } - if (__b == __e) - __err |= ios_base::eofbit; - return __b; -} - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get; -# endif - -// money_put - -template -class __money_put { -protected: - typedef _CharT char_type; - typedef basic_string string_type; - - _LIBCPP_HIDE_FROM_ABI __money_put() {} - - static void __gather_info( - bool __intl, - bool __neg, - const locale& __loc, - money_base::pattern& __pat, - char_type& __dp, - char_type& __ts, - string& __grp, - string_type& __sym, - string_type& __sn, - int& __fd); - static void __format( - char_type* __mb, - char_type*& __mi, - char_type*& __me, - ios_base::fmtflags __flags, - const char_type* __db, - const char_type* __de, - const ctype& __ct, - bool __neg, - const money_base::pattern& __pat, - char_type __dp, - char_type __ts, - const string& __grp, - const string_type& __sym, - const string_type& __sn, - int __fd); -}; - -template -void __money_put<_CharT>::__gather_info( - bool __intl, - bool __neg, - const locale& __loc, - money_base::pattern& __pat, - char_type& __dp, - char_type& __ts, - string& __grp, - string_type& __sym, - string_type& __sn, - int& __fd) { - if (__intl) { - const moneypunct& __mp = std::use_facet >(__loc); - if (__neg) { - __pat = __mp.neg_format(); - __sn = __mp.negative_sign(); - } else { - __pat = __mp.pos_format(); - __sn = __mp.positive_sign(); - } - __dp = __mp.decimal_point(); - __ts = __mp.thousands_sep(); - __grp = __mp.grouping(); - __sym = __mp.curr_symbol(); - __fd = __mp.frac_digits(); - } else { - const moneypunct& __mp = std::use_facet >(__loc); - if (__neg) { - __pat = __mp.neg_format(); - __sn = __mp.negative_sign(); - } else { - __pat = __mp.pos_format(); - __sn = __mp.positive_sign(); - } - __dp = __mp.decimal_point(); - __ts = __mp.thousands_sep(); - __grp = __mp.grouping(); - __sym = __mp.curr_symbol(); - __fd = __mp.frac_digits(); - } -} - -template -void __money_put<_CharT>::__format( - char_type* __mb, - char_type*& __mi, - char_type*& __me, - ios_base::fmtflags __flags, - const char_type* __db, - const char_type* __de, - const ctype& __ct, - bool __neg, - const money_base::pattern& __pat, - char_type __dp, - char_type __ts, - const string& __grp, - const string_type& __sym, - const string_type& __sn, - int __fd) { - __me = __mb; - for (char __p : __pat.field) { - switch (__p) { - case money_base::none: - __mi = __me; - break; - case money_base::space: - __mi = __me; - *__me++ = __ct.widen(' '); - break; - case money_base::sign: - if (!__sn.empty()) - *__me++ = __sn[0]; - break; - case money_base::symbol: - if (!__sym.empty() && (__flags & ios_base::showbase)) - __me = std::copy(__sym.begin(), __sym.end(), __me); - break; - case money_base::value: { - // remember start of value so we can reverse it - char_type* __t = __me; - // find beginning of digits - if (__neg) - ++__db; - // find end of digits - const char_type* __d; - for (__d = __db; __d < __de; ++__d) - if (!__ct.is(ctype_base::digit, *__d)) - break; - // print fractional part - if (__fd > 0) { - int __f; - for (__f = __fd; __d > __db && __f > 0; --__f) - *__me++ = *--__d; - char_type __z = __f > 0 ? __ct.widen('0') : char_type(); - for (; __f > 0; --__f) - *__me++ = __z; - *__me++ = __dp; - } - // print units part - if (__d == __db) { - *__me++ = __ct.widen('0'); - } else { - unsigned __ng = 0; - unsigned __ig = 0; - unsigned __gl = __grp.empty() ? numeric_limits::max() : static_cast(__grp[__ig]); - while (__d != __db) { - if (__ng == __gl) { - *__me++ = __ts; - __ng = 0; - if (++__ig < __grp.size()) - __gl = __grp[__ig] == numeric_limits::max() - ? numeric_limits::max() - : static_cast(__grp[__ig]); - } - *__me++ = *--__d; - ++__ng; - } - } - // reverse it - std::reverse(__t, __me); - } break; - } - } - // print rest of sign, if any - if (__sn.size() > 1) - __me = std::copy(__sn.begin() + 1, __sn.end(), __me); - // set alignment - if ((__flags & ios_base::adjustfield) == ios_base::left) - __mi = __me; - else if ((__flags & ios_base::adjustfield) != ios_base::internal) - __mi = __mb; -} - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put; -# endif - -template > -class money_put : public locale::facet, private __money_put<_CharT> { -public: - typedef _CharT char_type; - typedef _OutputIterator iter_type; - typedef basic_string string_type; - - _LIBCPP_HIDE_FROM_ABI explicit money_put(size_t __refs = 0) : locale::facet(__refs) {} - - _LIBCPP_HIDE_FROM_ABI iter_type - put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const { - return do_put(__s, __intl, __iob, __fl, __units); - } - - _LIBCPP_HIDE_FROM_ABI iter_type - put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const { - return do_put(__s, __intl, __iob, __fl, __digits); - } - - static locale::id id; - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_put() override {} - - virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const; - virtual iter_type - do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const; -}; - -template -locale::id money_put<_CharT, _OutputIterator>::id; - -template -_OutputIterator money_put<_CharT, _OutputIterator>::do_put( - iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const { - // convert to char - const size_t __bs = 100; - char __buf[__bs]; - char* __bb = __buf; - char_type __digits[__bs]; - char_type* __db = __digits; - int __n = snprintf(__bb, __bs, "%.0Lf", __units); - unique_ptr __hn(nullptr, free); - unique_ptr __hd(0, free); - // secure memory for digit storage - if (static_cast(__n) > __bs - 1) { - __n = __locale::__asprintf(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units); - if (__n == -1) - std::__throw_bad_alloc(); - __hn.reset(__bb); - __hd.reset((char_type*)malloc(static_cast(__n) * sizeof(char_type))); - if (__hd == nullptr) - std::__throw_bad_alloc(); - __db = __hd.get(); - } - // gather info - locale __loc = __iob.getloc(); - const ctype& __ct = std::use_facet >(__loc); - __ct.widen(__bb, __bb + __n, __db); - bool __neg = __n > 0 && __bb[0] == '-'; - money_base::pattern __pat; - char_type __dp; - char_type __ts; - string __grp; - string_type __sym; - string_type __sn; - int __fd; - this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd); - // secure memory for formatting - char_type __mbuf[__bs]; - char_type* __mb = __mbuf; - unique_ptr __hw(0, free); - size_t __exn = __n > __fd ? (static_cast(__n) - static_cast(__fd)) * 2 + __sn.size() + __sym.size() + - static_cast(__fd) + 1 - : __sn.size() + __sym.size() + static_cast(__fd) + 2; - if (__exn > __bs) { - __hw.reset((char_type*)malloc(__exn * sizeof(char_type))); - __mb = __hw.get(); - if (__mb == 0) - std::__throw_bad_alloc(); - } - // format - char_type* __mi; - char_type* __me; - this->__format( - __mb, __mi, __me, __iob.flags(), __db, __db + __n, __ct, __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd); - return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl); -} - -template -_OutputIterator money_put<_CharT, _OutputIterator>::do_put( - iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const { - // gather info - locale __loc = __iob.getloc(); - const ctype& __ct = std::use_facet >(__loc); - bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-'); - money_base::pattern __pat; - char_type __dp; - char_type __ts; - string __grp; - string_type __sym; - string_type __sn; - int __fd; - this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd); - // secure memory for formatting - char_type __mbuf[100]; - char_type* __mb = __mbuf; - unique_ptr __h(0, free); - size_t __exn = - static_cast(__digits.size()) > __fd - ? (__digits.size() - static_cast(__fd)) * 2 + __sn.size() + __sym.size() + static_cast(__fd) + - 1 - : __sn.size() + __sym.size() + static_cast(__fd) + 2; - if (__exn > 100) { - __h.reset((char_type*)malloc(__exn * sizeof(char_type))); - __mb = __h.get(); - if (__mb == 0) - std::__throw_bad_alloc(); - } - // format - char_type* __mi; - char_type* __me; - this->__format( - __mb, - __mi, - __me, - __iob.flags(), - __digits.data(), - __digits.data() + __digits.size(), - __ct, - __neg, - __pat, - __dp, - __ts, - __grp, - __sym, - __sn, - __fd); - return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl); -} - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put; -# endif - -// messages - -class _LIBCPP_EXPORTED_FROM_ABI messages_base { -public: - typedef intptr_t catalog; - - _LIBCPP_HIDE_FROM_ABI messages_base() {} -}; - -template -class messages : public locale::facet, public messages_base { -public: - typedef _CharT char_type; - typedef basic_string<_CharT> string_type; - - _LIBCPP_HIDE_FROM_ABI explicit messages(size_t __refs = 0) : locale::facet(__refs) {} - - _LIBCPP_HIDE_FROM_ABI catalog open(const basic_string& __nm, const locale& __loc) const { - return do_open(__nm, __loc); - } - - _LIBCPP_HIDE_FROM_ABI string_type get(catalog __c, int __set, int __msgid, const string_type& __dflt) const { - return do_get(__c, __set, __msgid, __dflt); - } - - _LIBCPP_HIDE_FROM_ABI void close(catalog __c) const { do_close(__c); } - - static locale::id id; - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages() override {} - - virtual catalog do_open(const basic_string&, const locale&) const; - virtual string_type do_get(catalog, int __set, int __msgid, const string_type& __dflt) const; - virtual void do_close(catalog) const; -}; - -template -locale::id messages<_CharT>::id; - -template -typename messages<_CharT>::catalog messages<_CharT>::do_open(const basic_string& __nm, const locale&) const { -# if _LIBCPP_HAS_CATOPEN - return (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE); -# else // !_LIBCPP_HAS_CATOPEN - (void)__nm; - return -1; -# endif // _LIBCPP_HAS_CATOPEN -} - -template -typename messages<_CharT>::string_type -messages<_CharT>::do_get(catalog __c, int __set, int __msgid, const string_type& __dflt) const { -# if _LIBCPP_HAS_CATOPEN - string __ndflt; - __narrow_to_utf8()( - std::back_inserter(__ndflt), __dflt.c_str(), __dflt.c_str() + __dflt.size()); - nl_catd __cat = (nl_catd)__c; - static_assert(sizeof(catalog) >= sizeof(nl_catd), "Unexpected nl_catd type"); - char* __n = catgets(__cat, __set, __msgid, __ndflt.c_str()); - string_type __w; - __widen_from_utf8()(std::back_inserter(__w), __n, __n + std::strlen(__n)); - return __w; -# else // !_LIBCPP_HAS_CATOPEN - (void)__c; - (void)__set; - (void)__msgid; - return __dflt; -# endif // _LIBCPP_HAS_CATOPEN -} - -template -void messages<_CharT>::do_close(catalog __c) const { -# if _LIBCPP_HAS_CATOPEN - catclose((nl_catd)__c); -# else // !_LIBCPP_HAS_CATOPEN - (void)__c; -# endif // _LIBCPP_HAS_CATOPEN -} - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages; -# endif - -template -class messages_byname : public messages<_CharT> { -public: - typedef messages_base::catalog catalog; - typedef basic_string<_CharT> string_type; - - _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const char*, size_t __refs = 0) : messages<_CharT>(__refs) {} - - _LIBCPP_HIDE_FROM_ABI explicit messages_byname(const string&, size_t __refs = 0) : messages<_CharT>(__refs) {} - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~messages_byname() override {} -}; - -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname; -# if _LIBCPP_HAS_WIDE_CHARACTERS -extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS messages_byname; -# endif - -# if _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) - -template , - class _ByteAlloc = allocator > -class _LIBCPP_DEPRECATED_IN_CXX17 wstring_convert { -public: - typedef basic_string, _ByteAlloc> byte_string; - typedef basic_string<_Elem, char_traits<_Elem>, _WideAlloc> wide_string; - typedef typename _Codecvt::state_type state_type; - typedef typename wide_string::traits_type::int_type int_type; - -private: - byte_string __byte_err_string_; - wide_string __wide_err_string_; - _Codecvt* __cvtptr_; - state_type __cvtstate_; - size_t __cvtcount_; - -public: -# ifndef _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI wstring_convert() : wstring_convert(new _Codecvt) {} - _LIBCPP_HIDE_FROM_ABI explicit wstring_convert(_Codecvt* __pcvt); -# else - _LIBCPP_HIDE_FROM_ABI _LIBCPP_EXPLICIT_SINCE_CXX14 wstring_convert(_Codecvt* __pcvt = new _Codecvt); -# endif - - _LIBCPP_HIDE_FROM_ABI wstring_convert(_Codecvt* __pcvt, state_type __state); - _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI - wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err = wide_string()); -# ifndef _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI wstring_convert(wstring_convert&& __wc); -# endif - _LIBCPP_HIDE_FROM_ABI ~wstring_convert(); - - wstring_convert(const wstring_convert& __wc) = delete; - wstring_convert& operator=(const wstring_convert& __wc) = delete; - - _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(char __byte) { return from_bytes(&__byte, &__byte + 1); } - _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __ptr) { - return from_bytes(__ptr, __ptr + char_traits::length(__ptr)); - } - _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const byte_string& __str) { - return from_bytes(__str.data(), __str.data() + __str.size()); - } - _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __first, const char* __last); - - _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(_Elem __wchar) { return to_bytes(std::addressof(__wchar), std::addressof(__wchar) + 1); } - _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __wptr) { - return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr)); - } - _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const wide_string& __wstr) { - return to_bytes(__wstr.data(), __wstr.data() + __wstr.size()); - } - _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __first, const _Elem* __last); - - _LIBCPP_HIDE_FROM_ABI size_t converted() const _NOEXCEPT { return __cvtcount_; } - _LIBCPP_HIDE_FROM_ABI state_type state() const { return __cvtstate_; } -}; - -_LIBCPP_SUPPRESS_DEPRECATED_PUSH -template -inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(_Codecvt* __pcvt) - : __cvtptr_(__pcvt), __cvtstate_(), __cvtcount_(0) {} -_LIBCPP_SUPPRESS_DEPRECATED_POP - -template -inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(_Codecvt* __pcvt, state_type __state) - : __cvtptr_(__pcvt), __cvtstate_(__state), __cvtcount_(0) {} - -template -wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert( - const byte_string& __byte_err, const wide_string& __wide_err) - : __byte_err_string_(__byte_err), __wide_err_string_(__wide_err), __cvtstate_(), __cvtcount_(0) { - __cvtptr_ = new _Codecvt; -} - -# ifndef _LIBCPP_CXX03_LANG - -template -inline wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wstring_convert(wstring_convert&& __wc) - : __byte_err_string_(std::move(__wc.__byte_err_string_)), - __wide_err_string_(std::move(__wc.__wide_err_string_)), - __cvtptr_(__wc.__cvtptr_), - __cvtstate_(__wc.__cvtstate_), - __cvtcount_(__wc.__cvtcount_) { - __wc.__cvtptr_ = nullptr; -} - -# endif // _LIBCPP_CXX03_LANG - -_LIBCPP_SUPPRESS_DEPRECATED_PUSH -template -wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::~wstring_convert() { - delete __cvtptr_; -} - -template -typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::wide_string -wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::from_bytes(const char* __frm, const char* __frm_end) { - _LIBCPP_SUPPRESS_DEPRECATED_POP - __cvtcount_ = 0; - if (__cvtptr_ != nullptr) { - wide_string __ws(2 * (__frm_end - __frm), _Elem()); - if (__frm != __frm_end) - __ws.resize(__ws.capacity()); - codecvt_base::result __r = codecvt_base::ok; - state_type __st = __cvtstate_; - if (__frm != __frm_end) { - _Elem* __to = std::addressof(__ws[0]); - _Elem* __to_end = __to + __ws.size(); - const char* __frm_nxt; - do { - _Elem* __to_nxt; - __r = __cvtptr_->in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); - __cvtcount_ += __frm_nxt - __frm; - if (__frm_nxt == __frm) { - __r = codecvt_base::error; - } else if (__r == codecvt_base::noconv) { - __ws.resize(__to - std::addressof(__ws[0])); - // This only gets executed if _Elem is char - __ws.append((const _Elem*)__frm, (const _Elem*)__frm_end); - __frm = __frm_nxt; - __r = codecvt_base::ok; - } else if (__r == codecvt_base::ok) { - __ws.resize(__to_nxt - std::addressof(__ws[0])); - __frm = __frm_nxt; - } else if (__r == codecvt_base::partial) { - ptrdiff_t __s = __to_nxt - std::addressof(__ws[0]); - __ws.resize(2 * __s); - __to = std::addressof(__ws[0]) + __s; - __to_end = std::addressof(__ws[0]) + __ws.size(); - __frm = __frm_nxt; - } - } while (__r == codecvt_base::partial && __frm_nxt < __frm_end); - } - if (__r == codecvt_base::ok) - return __ws; - } - - if (__wide_err_string_.empty()) - std::__throw_range_error("wstring_convert: from_bytes error"); - - return __wide_err_string_; -} - -template -typename wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::byte_string -wstring_convert<_Codecvt, _Elem, _WideAlloc, _ByteAlloc>::to_bytes(const _Elem* __frm, const _Elem* __frm_end) { - __cvtcount_ = 0; - if (__cvtptr_ != nullptr) { - byte_string __bs(2 * (__frm_end - __frm), char()); - if (__frm != __frm_end) - __bs.resize(__bs.capacity()); - codecvt_base::result __r = codecvt_base::ok; - state_type __st = __cvtstate_; - if (__frm != __frm_end) { - char* __to = std::addressof(__bs[0]); - char* __to_end = __to + __bs.size(); - const _Elem* __frm_nxt; - do { - char* __to_nxt; - __r = __cvtptr_->out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); - __cvtcount_ += __frm_nxt - __frm; - if (__frm_nxt == __frm) { - __r = codecvt_base::error; - } else if (__r == codecvt_base::noconv) { - __bs.resize(__to - std::addressof(__bs[0])); - // This only gets executed if _Elem is char - __bs.append((const char*)__frm, (const char*)__frm_end); - __frm = __frm_nxt; - __r = codecvt_base::ok; - } else if (__r == codecvt_base::ok) { - __bs.resize(__to_nxt - std::addressof(__bs[0])); - __frm = __frm_nxt; - } else if (__r == codecvt_base::partial) { - ptrdiff_t __s = __to_nxt - std::addressof(__bs[0]); - __bs.resize(2 * __s); - __to = std::addressof(__bs[0]) + __s; - __to_end = std::addressof(__bs[0]) + __bs.size(); - __frm = __frm_nxt; - } - } while (__r == codecvt_base::partial && __frm_nxt < __frm_end); - } - if (__r == codecvt_base::ok) { - size_t __s = __bs.size(); - __bs.resize(__bs.capacity()); - char* __to = std::addressof(__bs[0]) + __s; - char* __to_end = __to + __bs.size(); - do { - char* __to_nxt; - __r = __cvtptr_->unshift(__st, __to, __to_end, __to_nxt); - if (__r == codecvt_base::noconv) { - __bs.resize(__to - std::addressof(__bs[0])); - __r = codecvt_base::ok; - } else if (__r == codecvt_base::ok) { - __bs.resize(__to_nxt - std::addressof(__bs[0])); - } else if (__r == codecvt_base::partial) { - ptrdiff_t __sp = __to_nxt - std::addressof(__bs[0]); - __bs.resize(2 * __sp); - __to = std::addressof(__bs[0]) + __sp; - __to_end = std::addressof(__bs[0]) + __bs.size(); - } - } while (__r == codecvt_base::partial); - if (__r == codecvt_base::ok) - return __bs; - } - } - - if (__byte_err_string_.empty()) - std::__throw_range_error("wstring_convert: to_bytes error"); - - return __byte_err_string_; -} - -template > -class _LIBCPP_DEPRECATED_IN_CXX17 wbuffer_convert : public basic_streambuf<_Elem, _Tr> { -public: - // types: - typedef _Elem char_type; - typedef _Tr traits_type; - typedef typename traits_type::int_type int_type; - typedef typename traits_type::pos_type pos_type; - typedef typename traits_type::off_type off_type; - typedef typename _Codecvt::state_type state_type; - -private: - char* __extbuf_; - const char* __extbufnext_; - const char* __extbufend_; - char __extbuf_min_[8]; - size_t __ebs_; - char_type* __intbuf_; - size_t __ibs_; - streambuf* __bufptr_; - _Codecvt* __cv_; - state_type __st_; - ios_base::openmode __cm_; - bool __owns_eb_; - bool __owns_ib_; - bool __always_noconv_; - -public: -# ifndef _LIBCPP_CXX03_LANG - _LIBCPP_HIDE_FROM_ABI wbuffer_convert() : wbuffer_convert(nullptr) {} - explicit _LIBCPP_HIDE_FROM_ABI - wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type()); -# else - _LIBCPP_EXPLICIT_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI - wbuffer_convert(streambuf* __bytebuf = nullptr, _Codecvt* __pcvt = new _Codecvt, state_type __state = state_type()); -# endif - - _LIBCPP_HIDE_FROM_ABI ~wbuffer_convert(); - - _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf() const { return __bufptr_; } - _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf(streambuf* __bytebuf) { - streambuf* __r = __bufptr_; - __bufptr_ = __bytebuf; - return __r; - } - - wbuffer_convert(const wbuffer_convert&) = delete; - wbuffer_convert& operator=(const wbuffer_convert&) = delete; - - _LIBCPP_HIDE_FROM_ABI state_type state() const { return __st_; } - -protected: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type underflow(); - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type pbackfail(int_type __c = traits_type::eof()); - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type overflow(int_type __c = traits_type::eof()); - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual basic_streambuf* setbuf(char_type* __s, streamsize __n); - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type - seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __wch = ios_base::in | ios_base::out); - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual pos_type - seekpos(pos_type __sp, ios_base::openmode __wch = ios_base::in | ios_base::out); - _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int sync(); - -private: - _LIBCPP_HIDE_FROM_ABI_VIRTUAL bool __read_mode(); - _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __write_mode(); - _LIBCPP_HIDE_FROM_ABI_VIRTUAL wbuffer_convert* __close(); -}; - -_LIBCPP_SUPPRESS_DEPRECATED_PUSH -template -wbuffer_convert<_Codecvt, _Elem, _Tr>::wbuffer_convert(streambuf* __bytebuf, _Codecvt* __pcvt, state_type __state) - : __extbuf_(nullptr), - __extbufnext_(nullptr), - __extbufend_(nullptr), - __ebs_(0), - __intbuf_(0), - __ibs_(0), - __bufptr_(__bytebuf), - __cv_(__pcvt), - __st_(__state), - __cm_(0), - __owns_eb_(false), - __owns_ib_(false), - __always_noconv_(__cv_ ? __cv_->always_noconv() : false) { - setbuf(0, 4096); -} - -template -wbuffer_convert<_Codecvt, _Elem, _Tr>::~wbuffer_convert() { - __close(); - delete __cv_; - if (__owns_eb_) - delete[] __extbuf_; - if (__owns_ib_) - delete[] __intbuf_; -} - -template -typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow() { - _LIBCPP_SUPPRESS_DEPRECATED_POP - if (__cv_ == 0 || __bufptr_ == nullptr) - return traits_type::eof(); - bool __initial = __read_mode(); - char_type __1buf; - if (this->gptr() == 0) - this->setg(std::addressof(__1buf), std::addressof(__1buf) + 1, std::addressof(__1buf) + 1); - const size_t __unget_sz = __initial ? 0 : std::min((this->egptr() - this->eback()) / 2, 4); - int_type __c = traits_type::eof(); - if (this->gptr() == this->egptr()) { - std::memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type)); - if (__always_noconv_) { - streamsize __nmemb = static_cast(this->egptr() - this->eback() - __unget_sz); - __nmemb = __bufptr_->sgetn((char*)this->eback() + __unget_sz, __nmemb); - if (__nmemb != 0) { - this->setg(this->eback(), this->eback() + __unget_sz, this->eback() + __unget_sz + __nmemb); - __c = *this->gptr(); - } - } else { - if (__extbufend_ != __extbufnext_) { - _LIBCPP_ASSERT_NON_NULL(__extbufnext_ != nullptr, "underflow moving from nullptr"); - _LIBCPP_ASSERT_NON_NULL(__extbuf_ != nullptr, "underflow moving into nullptr"); - std::memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_); - } - __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_); - __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_); - streamsize __nmemb = std::min(static_cast(this->egptr() - this->eback() - __unget_sz), - static_cast(__extbufend_ - __extbufnext_)); - codecvt_base::result __r; - // FIXME: Do we ever need to restore the state here? - // state_type __svs = __st_; - streamsize __nr = __bufptr_->sgetn(const_cast(__extbufnext_), __nmemb); - if (__nr != 0) { - __extbufend_ = __extbufnext_ + __nr; - char_type* __inext; - __r = __cv_->in( - __st_, __extbuf_, __extbufend_, __extbufnext_, this->eback() + __unget_sz, this->egptr(), __inext); - if (__r == codecvt_base::noconv) { - this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)const_cast(__extbufend_)); - __c = *this->gptr(); - } else if (__inext != this->eback() + __unget_sz) { - this->setg(this->eback(), this->eback() + __unget_sz, __inext); - __c = *this->gptr(); - } - } - } - } else - __c = *this->gptr(); - if (this->eback() == std::addressof(__1buf)) - this->setg(0, 0, 0); - return __c; -} - -_LIBCPP_SUPPRESS_DEPRECATED_PUSH -template -typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type -wbuffer_convert<_Codecvt, _Elem, _Tr>::pbackfail(int_type __c) { - _LIBCPP_SUPPRESS_DEPRECATED_POP - if (__cv_ != 0 && __bufptr_ && this->eback() < this->gptr()) { - if (traits_type::eq_int_type(__c, traits_type::eof())) { - this->gbump(-1); - return traits_type::not_eof(__c); - } - if (traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1])) { - this->gbump(-1); - *this->gptr() = traits_type::to_char_type(__c); - return __c; - } - } - return traits_type::eof(); -} - -_LIBCPP_SUPPRESS_DEPRECATED_PUSH -template -typename wbuffer_convert<_Codecvt, _Elem, _Tr>::int_type wbuffer_convert<_Codecvt, _Elem, _Tr>::overflow(int_type __c) { - _LIBCPP_SUPPRESS_DEPRECATED_POP - if (__cv_ == 0 || !__bufptr_) - return traits_type::eof(); - __write_mode(); - char_type __1buf; - char_type* __pb_save = this->pbase(); - char_type* __epb_save = this->epptr(); - if (!traits_type::eq_int_type(__c, traits_type::eof())) { - if (this->pptr() == 0) - this->setp(std::addressof(__1buf), std::addressof(__1buf) + 1); - *this->pptr() = traits_type::to_char_type(__c); - this->pbump(1); - } - if (this->pptr() != this->pbase()) { - if (__always_noconv_) { - streamsize __nmemb = static_cast(this->pptr() - this->pbase()); - if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb) - return traits_type::eof(); - } else { - char* __extbe = __extbuf_; - codecvt_base::result __r; - do { - const char_type* __e; - __r = __cv_->out(__st_, this->pbase(), this->pptr(), __e, __extbuf_, __extbuf_ + __ebs_, __extbe); - if (__e == this->pbase()) - return traits_type::eof(); - if (__r == codecvt_base::noconv) { - streamsize __nmemb = static_cast(this->pptr() - this->pbase()); - if (__bufptr_->sputn((const char*)this->pbase(), __nmemb) != __nmemb) - return traits_type::eof(); - } else if (__r == codecvt_base::ok || __r == codecvt_base::partial) { - streamsize __nmemb = static_cast(__extbe - __extbuf_); - if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb) - return traits_type::eof(); - if (__r == codecvt_base::partial) { - this->setp(const_cast(__e), this->pptr()); - this->__pbump(this->epptr() - this->pbase()); - } - } else - return traits_type::eof(); - } while (__r == codecvt_base::partial); - } - this->setp(__pb_save, __epb_save); - } - return traits_type::not_eof(__c); -} - -_LIBCPP_SUPPRESS_DEPRECATED_PUSH -template -basic_streambuf<_Elem, _Tr>* wbuffer_convert<_Codecvt, _Elem, _Tr>::setbuf(char_type* __s, streamsize __n) { - _LIBCPP_SUPPRESS_DEPRECATED_POP - this->setg(0, 0, 0); - this->setp(0, 0); - if (__owns_eb_) - delete[] __extbuf_; - if (__owns_ib_) - delete[] __intbuf_; - __ebs_ = __n; - if (__ebs_ > sizeof(__extbuf_min_)) { - if (__always_noconv_ && __s) { - __extbuf_ = (char*)__s; - __owns_eb_ = false; - } else { - __extbuf_ = new char[__ebs_]; - __owns_eb_ = true; - } - } else { - __extbuf_ = __extbuf_min_; - __ebs_ = sizeof(__extbuf_min_); - __owns_eb_ = false; - } - if (!__always_noconv_) { - __ibs_ = max(__n, sizeof(__extbuf_min_)); - if (__s && __ibs_ >= sizeof(__extbuf_min_)) { - __intbuf_ = __s; - __owns_ib_ = false; - } else { - __intbuf_ = new char_type[__ibs_]; - __owns_ib_ = true; - } - } else { - __ibs_ = 0; - __intbuf_ = 0; - __owns_ib_ = false; - } - return this; -} - -_LIBCPP_SUPPRESS_DEPRECATED_PUSH -template -typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type -wbuffer_convert<_Codecvt, _Elem, _Tr>::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __om) { - int __width = __cv_->encoding(); - if (__cv_ == 0 || !__bufptr_ || (__width <= 0 && __off != 0) || sync()) - return pos_type(off_type(-1)); - // __width > 0 || __off == 0, now check __way - if (__way != ios_base::beg && __way != ios_base::cur && __way != ios_base::end) - return pos_type(off_type(-1)); - pos_type __r = __bufptr_->pubseekoff(__width * __off, __way, __om); - __r.state(__st_); - return __r; -} - -template -typename wbuffer_convert<_Codecvt, _Elem, _Tr>::pos_type -wbuffer_convert<_Codecvt, _Elem, _Tr>::seekpos(pos_type __sp, ios_base::openmode __wch) { - if (__cv_ == 0 || !__bufptr_ || sync()) - return pos_type(off_type(-1)); - if (__bufptr_->pubseekpos(__sp, __wch) == pos_type(off_type(-1))) - return pos_type(off_type(-1)); - return __sp; -} - -template -int wbuffer_convert<_Codecvt, _Elem, _Tr>::sync() { - _LIBCPP_SUPPRESS_DEPRECATED_POP - if (__cv_ == 0 || !__bufptr_) - return 0; - if (__cm_ & ios_base::out) { - if (this->pptr() != this->pbase()) - if (overflow() == traits_type::eof()) - return -1; - codecvt_base::result __r; - do { - char* __extbe; - __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe); - streamsize __nmemb = static_cast(__extbe - __extbuf_); - if (__bufptr_->sputn(__extbuf_, __nmemb) != __nmemb) - return -1; - } while (__r == codecvt_base::partial); - if (__r == codecvt_base::error) - return -1; - if (__bufptr_->pubsync()) - return -1; - } else if (__cm_ & ios_base::in) { - off_type __c; - if (__always_noconv_) - __c = this->egptr() - this->gptr(); - else { - int __width = __cv_->encoding(); - __c = __extbufend_ - __extbufnext_; - if (__width > 0) - __c += __width * (this->egptr() - this->gptr()); - else { - if (this->gptr() != this->egptr()) { - std::reverse(this->gptr(), this->egptr()); - codecvt_base::result __r; - const char_type* __e = this->gptr(); - char* __extbe; - do { - __r = __cv_->out(__st_, __e, this->egptr(), __e, __extbuf_, __extbuf_ + __ebs_, __extbe); - switch (__r) { - case codecvt_base::noconv: - __c += this->egptr() - this->gptr(); - break; - case codecvt_base::ok: - case codecvt_base::partial: - __c += __extbe - __extbuf_; - break; - default: - return -1; - } - } while (__r == codecvt_base::partial); - } - } - } - if (__bufptr_->pubseekoff(-__c, ios_base::cur, __cm_) == pos_type(off_type(-1))) - return -1; - this->setg(0, 0, 0); - __cm_ = 0; - } - return 0; -} - -_LIBCPP_SUPPRESS_DEPRECATED_PUSH -template -bool wbuffer_convert<_Codecvt, _Elem, _Tr>::__read_mode() { - if (!(__cm_ & ios_base::in)) { - this->setp(0, 0); - if (__always_noconv_) - this->setg((char_type*)__extbuf_, (char_type*)__extbuf_ + __ebs_, (char_type*)__extbuf_ + __ebs_); - else - this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_); - __cm_ = ios_base::in; - return true; - } - return false; -} - -template -void wbuffer_convert<_Codecvt, _Elem, _Tr>::__write_mode() { - if (!(__cm_ & ios_base::out)) { - this->setg(0, 0, 0); - if (__ebs_ > sizeof(__extbuf_min_)) { - if (__always_noconv_) - this->setp((char_type*)__extbuf_, (char_type*)__extbuf_ + (__ebs_ - 1)); - else - this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1)); - } else - this->setp(0, 0); - __cm_ = ios_base::out; - } -} - -template -wbuffer_convert<_Codecvt, _Elem, _Tr>* wbuffer_convert<_Codecvt, _Elem, _Tr>::__close() { - wbuffer_convert* __rt = nullptr; - if (__cv_ != nullptr && __bufptr_ != nullptr) { - __rt = this; - if ((__cm_ & ios_base::out) && sync()) - __rt = nullptr; - } - return __rt; -} - -_LIBCPP_SUPPRESS_DEPRECATED_POP - -# endif // _LIBCPP_STD_VER < 26 || defined(_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT) - -_LIBCPP_END_NAMESPACE_STD - -_LIBCPP_POP_MACROS - -// NOLINTEND(libcpp-robust-against-adl) - # endif // _LIBCPP_HAS_LOCALIZATION # if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index b00a8ebd54623..ea15b4dcb59b6 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1554,7 +1554,16 @@ module std [system] { module locale { header "locale" - module pad_and_output { header "__locale_dir/pad_and_output.h" } + module check_grouping { header "__locale_dir/check_grouping.h" } + module get_c_locale { header "__locale_dir/get_c_locale.h" } + module messages { header "__locale_dir/messages.h" } + module money { header "__locale_dir/money.h" } + module num { header "__locale_dir/num.h" } + module pad_and_output { header "__locale_dir/pad_and_output.h" } + module scan_keyword { header "__locale_dir/scan_keyword.h" } + module time { header "__locale_dir/time.h" } + module wbuffer_convert { header "__locale_dir/wbuffer_convert.h" } + module wstring_convert { header "__locale_dir/wstring_convert.h" } module support { header "__locale_dir/locale_base_api.h" diff --git a/libcxx/include/ostream b/libcxx/include/ostream index 4a627a07a4a2f..8ec17b68503f8 100644 --- a/libcxx/include/ostream +++ b/libcxx/include/ostream @@ -205,6 +205,11 @@ void vprint_nonunicode(ostream& os, string_view fmt, format_args args); # include # include # endif + +# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 23 +# include +# endif + #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) #endif // _LIBCPP_OSTREAM diff --git a/libcxx/include/sstream b/libcxx/include/sstream index 8462f75853408..682a28fd4dbb8 100644 --- a/libcxx/include/sstream +++ b/libcxx/include/sstream @@ -325,7 +325,7 @@ typedef basic_stringstream wstringstream; # include <__utility/swap.h> # include # include -# include +# include # include # include # include diff --git a/libcxx/test/libcxx/localization/locale.categories/__scan_keyword.pass.cpp b/libcxx/test/libcxx/localization/locale.categories/__scan_keyword.pass.cpp index 1ecf378de5b61..5f618e92375ae 100644 --- a/libcxx/test/libcxx/localization/locale.categories/__scan_keyword.pass.cpp +++ b/libcxx/test/libcxx/localization/locale.categories/__scan_keyword.pass.cpp @@ -35,8 +35,11 @@ // const _Ctype& __ct, ios_base::iostate& __err, // bool __case_sensitive = true); -#include +// XFAIL: FROZEN-CXX03-HEADERS-FIXME + +#include <__locale_dir/scan_keyword.h> #include +#include #include "test_macros.h" diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv index ce8f0261f2b27..5f906338f4b7c 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx26.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv @@ -82,7 +82,6 @@ ccomplex ios ccomplex iosfwd ccomplex istream ccomplex limits -ccomplex locale ccomplex ratio ccomplex sstream ccomplex stdexcept @@ -120,7 +119,6 @@ chrono ios chrono iosfwd chrono istream chrono limits -chrono locale chrono optional chrono ratio chrono sstream @@ -177,7 +175,6 @@ complex ios complex iosfwd complex istream complex limits -complex locale complex ratio complex sstream complex stdexcept @@ -226,7 +223,6 @@ ctgmath ios ctgmath iosfwd ctgmath istream ctgmath limits -ctgmath locale ctgmath ratio ctgmath sstream ctgmath stdexcept @@ -278,7 +274,6 @@ experimental/iterator ios experimental/iterator iosfwd experimental/iterator iterator experimental/iterator limits -experimental/iterator locale experimental/iterator ratio experimental/iterator stdexcept experimental/iterator streambuf @@ -324,10 +319,8 @@ filesystem iomanip filesystem ios filesystem iosfwd filesystem limits -filesystem locale filesystem ratio filesystem stdexcept -filesystem streambuf filesystem string filesystem string_view filesystem tuple @@ -412,7 +405,6 @@ fstream ios fstream iosfwd fstream istream fstream limits -fstream locale fstream ratio fstream stdexcept fstream streambuf @@ -455,7 +447,6 @@ future ios future iosfwd future istream future limits -future locale future ratio future sstream future stdexcept @@ -483,10 +474,8 @@ iomanip initializer_list iomanip ios iomanip iosfwd iomanip limits -iomanip locale iomanip ratio iomanip stdexcept -iomanip streambuf iomanip string iomanip string_view iomanip tuple @@ -538,7 +527,6 @@ iostream ios iostream iosfwd iostream istream iostream limits -iostream locale iostream optional iostream ostream iostream print @@ -568,7 +556,6 @@ istream initializer_list istream ios istream iosfwd istream limits -istream locale istream ratio istream stdexcept istream streambuf @@ -724,7 +711,6 @@ ostream initializer_list ostream ios ostream iosfwd ostream limits -ostream locale ostream optional ostream print ostream ratio @@ -905,7 +891,6 @@ sstream ios sstream iosfwd sstream istream sstream limits -sstream locale sstream ratio sstream stdexcept sstream streambuf @@ -1004,7 +989,6 @@ strstream ios strstream iosfwd strstream istream strstream limits -strstream locale strstream ratio strstream stdexcept strstream streambuf @@ -1034,7 +1018,6 @@ syncstream initializer_list syncstream ios syncstream iosfwd syncstream limits -syncstream locale syncstream map syncstream optional syncstream ostream @@ -1086,7 +1069,6 @@ thread ios thread iosfwd thread istream thread limits -thread locale thread ratio thread sstream thread stdexcept diff --git a/libcxx/test/std/input.output/iostream.format/ext.manip/get_money.pass.cpp b/libcxx/test/std/input.output/iostream.format/ext.manip/get_money.pass.cpp index d468d7154dad5..88672851f7b6b 100644 --- a/libcxx/test/std/input.output/iostream.format/ext.manip/get_money.pass.cpp +++ b/libcxx/test/std/input.output/iostream.format/ext.manip/get_money.pass.cpp @@ -15,9 +15,10 @@ // REQUIRES: locale.en_US.UTF-8 +#include #include #include -#include +#include #include "test_macros.h" #include "platform_support.h" // locale name macros diff --git a/libcxx/test/std/input.output/iostream.format/ext.manip/get_time.pass.cpp b/libcxx/test/std/input.output/iostream.format/ext.manip/get_time.pass.cpp index addf53fcdeb30..c6e3e43109a2f 100644 --- a/libcxx/test/std/input.output/iostream.format/ext.manip/get_time.pass.cpp +++ b/libcxx/test/std/input.output/iostream.format/ext.manip/get_time.pass.cpp @@ -12,9 +12,11 @@ // template T9 get_time(struct tm* tmb, const charT* fmt); +#include +#include #include #include -#include +#include #include "test_macros.h" #include "platform_support.h" // locale name macros diff --git a/libcxx/test/std/input.output/iostream.format/ext.manip/put_time.pass.cpp b/libcxx/test/std/input.output/iostream.format/ext.manip/put_time.pass.cpp index 7de93bef0f7b8..5b35b7d1cc81b 100644 --- a/libcxx/test/std/input.output/iostream.format/ext.manip/put_time.pass.cpp +++ b/libcxx/test/std/input.output/iostream.format/ext.manip/put_time.pass.cpp @@ -12,9 +12,10 @@ // template T10 put_time(const struct tm* tmb, const charT* fmt); +#include +#include #include #include -#include #include "test_macros.h" #include "platform_support.h" // locale name macros diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_date.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_date.pass.cpp index 0749617d056ab..3f53490c1baee 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_date.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_date.pass.cpp @@ -22,8 +22,10 @@ // get_date(iter_type s, iter_type end, ios_base& str, // ios_base::iostate& err, tm* t) const; -#include #include +#include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_monthname.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_monthname.pass.cpp index 1b19f5c944999..fbffafc5bcee7 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_monthname.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_monthname.pass.cpp @@ -20,8 +20,10 @@ // get_monthname(iter_type s, iter_type end, ios_base& str, // ios_base::iostate& err, tm* t) const; -#include #include +#include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_one.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_one.pass.cpp index 35dba465917e3..513f92bc3fafd 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_one.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_one.pass.cpp @@ -23,8 +23,10 @@ // iter_type get(iter_type s, iter_type end, ios_base& f, // ios_base::iostate& err, tm *t, char format, char modifier = 0) const; -#include #include +#include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_time.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_time.pass.cpp index aa5b0d04caa1f..651c1e16092e4 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_time.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_time.pass.cpp @@ -19,9 +19,11 @@ // get_time(iter_type s, iter_type end, ios_base& str, // ios_base::iostate& err, tm* t) const; -#include #include +#include #include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_weekday.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_weekday.pass.cpp index da64b573a41cd..0df0b10c9d7ca 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_weekday.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_weekday.pass.cpp @@ -19,8 +19,10 @@ // get_weekday(iter_type s, iter_type end, ios_base& str, // ios_base::iostate& err, tm* t) const; -#include #include +#include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_year.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_year.pass.cpp index ec846093583db..ef0d9230e78ba 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_year.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get.byname/get_year.pass.cpp @@ -18,9 +18,11 @@ // iter_type get_year(iter_type s, iter_type end, ios_base& str, // ios_base::iostate& err, tm* t) const; -#include #include +#include #include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_date.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_date.pass.cpp index a6c7f7816fdc4..1eac586d413ff 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_date.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_date.pass.cpp @@ -14,9 +14,11 @@ // get_date(iter_type s, iter_type end, ios_base& str, // ios_base::iostate& err, tm* t) const; -#include #include +#include #include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_many.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_many.pass.cpp index e8ca74ee4aa04..4a4443d38be32 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_many.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_many.pass.cpp @@ -14,9 +14,11 @@ // get(iter_type s, iter_type end, ios_base& f, ios_base::iostate& err, tm *t, // const char_type *fmt, const char_type *fmtend) const; -#include #include +#include #include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_monthname.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_monthname.pass.cpp index 10769f92c50db..10d91715991b2 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_monthname.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_monthname.pass.cpp @@ -14,8 +14,10 @@ // get_monthname(iter_type s, iter_type end, ios_base& str, // ios_base::iostate& err, tm* t) const; -#include #include +#include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_one.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_one.pass.cpp index a4ef9bd9f12c4..16a8eaa20b24d 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_one.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_one.pass.cpp @@ -13,8 +13,10 @@ // iter_type get(iter_type s, iter_type end, ios_base& f, // ios_base::iostate& err, tm *t, char format, char modifier = 0) const; -#include #include +#include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_time.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_time.pass.cpp index 009f94d26ee53..4d5b5edcdb693 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_time.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_time.pass.cpp @@ -14,8 +14,10 @@ // get_time(iter_type s, iter_type end, ios_base& str, // ios_base::iostate& err, tm* t) const; -#include #include +#include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_weekday.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_weekday.pass.cpp index 23d53e32ef0d6..21780e59081db 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_weekday.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_weekday.pass.cpp @@ -14,8 +14,10 @@ // get_weekday(iter_type s, iter_type end, ios_base& str, // ios_base::iostate& err, tm* t) const; -#include #include +#include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_year.pass.cpp b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_year.pass.cpp index 663f7647d5ac7..c59dca140bfea 100644 --- a/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_year.pass.cpp +++ b/libcxx/test/std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_year.pass.cpp @@ -13,9 +13,11 @@ // iter_type get_year(iter_type s, iter_type end, ios_base& str, // ios_base::iostate& err, tm* t) const; -#include #include +#include #include +#include + #include "test_macros.h" #include "test_iterators.h" diff --git a/libcxx/test/support/concat_macros.h b/libcxx/test/support/concat_macros.h index 50b6562197392..efec4029f4025 100644 --- a/libcxx/test/support/concat_macros.h +++ b/libcxx/test/support/concat_macros.h @@ -9,6 +9,7 @@ #ifndef TEST_SUPPORT_CONCAT_MACROS_H #define TEST_SUPPORT_CONCAT_MACROS_H +#include #include #include #include diff --git a/libcxx/test/tools/clang_tidy_checks/header_exportable_declarations.cpp b/libcxx/test/tools/clang_tidy_checks/header_exportable_declarations.cpp index 897da8b769e6a..8ec029f7dba2d 100644 --- a/libcxx/test/tools/clang_tidy_checks/header_exportable_declarations.cpp +++ b/libcxx/test/tools/clang_tidy_checks/header_exportable_declarations.cpp @@ -101,8 +101,10 @@ void header_exportable_declarations::registerMatchers(clang::ast_matchers::Match // Looks at the common locations where headers store their data // * header // * __header/*.h + // * __header_dir/*.h // Used for transitioning from __header // * __fwd/header.h anyOf(isExpansionInFileMatching(("v1/__" + filename_ + "/").str()), + isExpansionInFileMatching(("v1/__" + filename_ + "_dir/").str()), isExpansionInFileMatching(extra_header_), isExpansionInFileMatching(("v1/__fwd/" + filename_ + "\\.h$").str()), isExpansionInFileMatching(("v1/" + filename_ + "$").str())),