diff options
author | Andrey Khalyavin <halyavin@gmail.com> | 2022-02-10 16:46:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:46:30 +0300 |
commit | 4b839d0704ee9be1dabb0310a1f03af24963637b (patch) | |
tree | 1a2c5ffcf89eb53ecd79dbc9bc0a195c27404d0c /contrib/libs/cxxsupp/libcxx/src | |
parent | f773626848a7c7456803654292e716b83d69cc12 (diff) | |
download | ydb-4b839d0704ee9be1dabb0310a1f03af24963637b.tar.gz |
Restoring authorship annotation for Andrey Khalyavin <halyavin@gmail.com>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/cxxsupp/libcxx/src')
73 files changed, 18839 insertions, 18839 deletions
diff --git a/contrib/libs/cxxsupp/libcxx/src/algorithm.cpp b/contrib/libs/cxxsupp/libcxx/src/algorithm.cpp index 59b7d47243..16221f4b75 100644 --- a/contrib/libs/cxxsupp/libcxx/src/algorithm.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/algorithm.cpp @@ -1,51 +1,51 @@ -//===----------------------- algorithm.cpp --------------------------------===// -// +//===----------------------- algorithm.cpp --------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "algorithm" - -_LIBCPP_BEGIN_NAMESPACE_STD - -template void __sort<__less<char>&, char*>(char*, char*, __less<char>&); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template void __sort<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&); -#endif -template void __sort<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&); -template void __sort<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&); -template void __sort<__less<short>&, short*>(short*, short*, __less<short>&); -template void __sort<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&); -template void __sort<__less<int>&, int*>(int*, int*, __less<int>&); -template void __sort<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&); -template void __sort<__less<long>&, long*>(long*, long*, __less<long>&); -template void __sort<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&); -template void __sort<__less<long long>&, long long*>(long long*, long long*, __less<long long>&); -template void __sort<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&); -template void __sort<__less<float>&, float*>(float*, float*, __less<float>&); -template void __sort<__less<double>&, double*>(double*, double*, __less<double>&); -template void __sort<__less<long double>&, long double*>(long double*, long double*, __less<long double>&); - -template bool __insertion_sort_incomplete<__less<char>&, char*>(char*, char*, __less<char>&); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template bool __insertion_sort_incomplete<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&); -#endif -template bool __insertion_sort_incomplete<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&); -template bool __insertion_sort_incomplete<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&); -template bool __insertion_sort_incomplete<__less<short>&, short*>(short*, short*, __less<short>&); -template bool __insertion_sort_incomplete<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&); -template bool __insertion_sort_incomplete<__less<int>&, int*>(int*, int*, __less<int>&); -template bool __insertion_sort_incomplete<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&); -template bool __insertion_sort_incomplete<__less<long>&, long*>(long*, long*, __less<long>&); -template bool __insertion_sort_incomplete<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&); -template bool __insertion_sort_incomplete<__less<long long>&, long long*>(long long*, long long*, __less<long long>&); -template bool __insertion_sort_incomplete<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&); -template bool __insertion_sort_incomplete<__less<float>&, float*>(float*, float*, __less<float>&); -template bool __insertion_sort_incomplete<__less<double>&, double*>(double*, double*, __less<double>&); -template bool __insertion_sort_incomplete<__less<long double>&, long double*>(long double*, long double*, __less<long double>&); - -template unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&); - -_LIBCPP_END_NAMESPACE_STD +// +//===----------------------------------------------------------------------===// + +#include "algorithm" + +_LIBCPP_BEGIN_NAMESPACE_STD + +template void __sort<__less<char>&, char*>(char*, char*, __less<char>&); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template void __sort<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&); +#endif +template void __sort<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&); +template void __sort<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&); +template void __sort<__less<short>&, short*>(short*, short*, __less<short>&); +template void __sort<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&); +template void __sort<__less<int>&, int*>(int*, int*, __less<int>&); +template void __sort<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&); +template void __sort<__less<long>&, long*>(long*, long*, __less<long>&); +template void __sort<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&); +template void __sort<__less<long long>&, long long*>(long long*, long long*, __less<long long>&); +template void __sort<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&); +template void __sort<__less<float>&, float*>(float*, float*, __less<float>&); +template void __sort<__less<double>&, double*>(double*, double*, __less<double>&); +template void __sort<__less<long double>&, long double*>(long double*, long double*, __less<long double>&); + +template bool __insertion_sort_incomplete<__less<char>&, char*>(char*, char*, __less<char>&); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template bool __insertion_sort_incomplete<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&); +#endif +template bool __insertion_sort_incomplete<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&); +template bool __insertion_sort_incomplete<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&); +template bool __insertion_sort_incomplete<__less<short>&, short*>(short*, short*, __less<short>&); +template bool __insertion_sort_incomplete<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&); +template bool __insertion_sort_incomplete<__less<int>&, int*>(int*, int*, __less<int>&); +template bool __insertion_sort_incomplete<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&); +template bool __insertion_sort_incomplete<__less<long>&, long*>(long*, long*, __less<long>&); +template bool __insertion_sort_incomplete<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&); +template bool __insertion_sort_incomplete<__less<long long>&, long long*>(long long*, long long*, __less<long long>&); +template bool __insertion_sort_incomplete<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&); +template bool __insertion_sort_incomplete<__less<float>&, float*>(float*, float*, __less<float>&); +template bool __insertion_sort_incomplete<__less<double>&, double*>(double*, double*, __less<double>&); +template bool __insertion_sort_incomplete<__less<long double>&, long double*>(long double*, long double*, __less<long double>&); + +template unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&); + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/any.cpp b/contrib/libs/cxxsupp/libcxx/src/any.cpp index 6bb110ad74..415d23b0c9 100644 --- a/contrib/libs/cxxsupp/libcxx/src/any.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/any.cpp @@ -1,34 +1,34 @@ -//===---------------------------- any.cpp ---------------------------------===// -// +//===---------------------------- any.cpp ---------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "any" - -namespace std { -const char* bad_any_cast::what() const noexcept { - return "bad any cast"; -} -} - - -#include <experimental/__config> - -// Preserve std::experimental::any_bad_cast for ABI compatibility -// Even though it no longer exists in a header file -_LIBCPP_BEGIN_NAMESPACE_LFTS - -class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast -{ -public: - virtual const char* what() const noexcept; -}; - -const char* bad_any_cast::what() const noexcept { - return "bad any cast"; -} - -_LIBCPP_END_NAMESPACE_LFTS +// +//===----------------------------------------------------------------------===// + +#include "any" + +namespace std { +const char* bad_any_cast::what() const noexcept { + return "bad any cast"; +} +} + + +#include <experimental/__config> + +// Preserve std::experimental::any_bad_cast for ABI compatibility +// Even though it no longer exists in a header file +_LIBCPP_BEGIN_NAMESPACE_LFTS + +class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast +{ +public: + virtual const char* what() const noexcept; +}; + +const char* bad_any_cast::what() const noexcept { + return "bad any cast"; +} + +_LIBCPP_END_NAMESPACE_LFTS diff --git a/contrib/libs/cxxsupp/libcxx/src/atomic.cpp b/contrib/libs/cxxsupp/libcxx/src/atomic.cpp index a494940a75..9ae1fb5199 100644 --- a/contrib/libs/cxxsupp/libcxx/src/atomic.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/atomic.cpp @@ -1,193 +1,193 @@ -//===------------------------- atomic.cpp ---------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include <__config> -#ifndef _LIBCPP_HAS_NO_THREADS - -#include <climits> -#include <atomic> -#include <functional> - -#ifdef __linux__ - -#include <unistd.h> -#include <linux/futex.h> -#include <sys/syscall.h> - -// libc++ uses SYS_futex as a universal syscall name. However, on 32 bit architectures -// with a 64 bit time_t, we need to specify SYS_futex_time64. -#if !defined(SYS_futex) && defined(SYS_futex_time64) -# define SYS_futex SYS_futex_time64 -#endif - -#else // <- Add other operating systems here - -// Baseline needs no new headers - -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -#ifdef __linux__ - -static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, - __cxx_contention_t __val) -{ - static constexpr timespec __timeout = { 2, 0 }; - syscall(SYS_futex, __ptr, FUTEX_WAIT_PRIVATE, __val, &__timeout, 0, 0); -} - -static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, - bool __notify_one) -{ - syscall(SYS_futex, __ptr, FUTEX_WAKE_PRIVATE, __notify_one ? 1 : INT_MAX, 0, 0, 0); -} - -#elif defined(__APPLE__) && defined(_LIBCPP_USE_ULOCK) - -extern "C" int __ulock_wait(uint32_t operation, void *addr, uint64_t value, +//===------------------------- atomic.cpp ---------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <__config> +#ifndef _LIBCPP_HAS_NO_THREADS + +#include <climits> +#include <atomic> +#include <functional> + +#ifdef __linux__ + +#include <unistd.h> +#include <linux/futex.h> +#include <sys/syscall.h> + +// libc++ uses SYS_futex as a universal syscall name. However, on 32 bit architectures +// with a 64 bit time_t, we need to specify SYS_futex_time64. +#if !defined(SYS_futex) && defined(SYS_futex_time64) +# define SYS_futex SYS_futex_time64 +#endif + +#else // <- Add other operating systems here + +// Baseline needs no new headers + +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifdef __linux__ + +static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, + __cxx_contention_t __val) +{ + static constexpr timespec __timeout = { 2, 0 }; + syscall(SYS_futex, __ptr, FUTEX_WAIT_PRIVATE, __val, &__timeout, 0, 0); +} + +static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, + bool __notify_one) +{ + syscall(SYS_futex, __ptr, FUTEX_WAKE_PRIVATE, __notify_one ? 1 : INT_MAX, 0, 0, 0); +} + +#elif defined(__APPLE__) && defined(_LIBCPP_USE_ULOCK) + +extern "C" int __ulock_wait(uint32_t operation, void *addr, uint64_t value, uint32_t timeout); /* timeout is specified in microseconds */ -extern "C" int __ulock_wake(uint32_t operation, void *addr, uint64_t wake_value); - +extern "C" int __ulock_wake(uint32_t operation, void *addr, uint64_t wake_value); + #define UL_COMPARE_AND_WAIT 1 #define ULF_WAKE_ALL 0x00000100 - -static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, - __cxx_contention_t __val) -{ - __ulock_wait(UL_COMPARE_AND_WAIT, - const_cast<__cxx_atomic_contention_t*>(__ptr), __val, 0); -} - -static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, - bool __notify_one) -{ - __ulock_wake(UL_COMPARE_AND_WAIT | (__notify_one ? 0 : ULF_WAKE_ALL), - const_cast<__cxx_atomic_contention_t*>(__ptr), 0); -} - -#else // <- Add other operating systems here - -// Baseline is just a timed backoff - -static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, - __cxx_contention_t __val) -{ - __libcpp_thread_poll_with_backoff([=]() -> bool { - return !__cxx_nonatomic_compare_equal(__cxx_atomic_load(__ptr, memory_order_relaxed), __val); - }, __libcpp_timed_backoff_policy()); -} - -static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile*, bool) { } - -#endif // __linux__ - -static constexpr size_t __libcpp_contention_table_size = (1 << 8); /* < there's no magic in this number */ - -struct alignas(64) /* aim to avoid false sharing */ __libcpp_contention_table_entry -{ - __cxx_atomic_contention_t __contention_state; - __cxx_atomic_contention_t __platform_state; - inline constexpr __libcpp_contention_table_entry() : - __contention_state(0), __platform_state(0) { } -}; - -static __libcpp_contention_table_entry __libcpp_contention_table[ __libcpp_contention_table_size ]; - -static hash<void const volatile*> __libcpp_contention_hasher; - -static __libcpp_contention_table_entry* __libcpp_contention_state(void const volatile * p) -{ - return &__libcpp_contention_table[__libcpp_contention_hasher(p) & (__libcpp_contention_table_size - 1)]; -} - -/* Given an atomic to track contention and an atomic to actually wait on, which may be - the same atomic, we try to detect contention to avoid spuriously calling the platform. */ - -static void __libcpp_contention_notify(__cxx_atomic_contention_t volatile* __contention_state, - __cxx_atomic_contention_t const volatile* __platform_state, - bool __notify_one) -{ - if(0 != __cxx_atomic_load(__contention_state, memory_order_seq_cst)) - // We only call 'wake' if we consumed a contention bit here. - __libcpp_platform_wake_by_address(__platform_state, __notify_one); -} -static __cxx_contention_t __libcpp_contention_monitor_for_wait(__cxx_atomic_contention_t volatile* __contention_state, - __cxx_atomic_contention_t const volatile* __platform_state) -{ - // We will monitor this value. - return __cxx_atomic_load(__platform_state, memory_order_acquire); -} -static void __libcpp_contention_wait(__cxx_atomic_contention_t volatile* __contention_state, - __cxx_atomic_contention_t const volatile* __platform_state, - __cxx_contention_t __old_value) -{ - __cxx_atomic_fetch_add(__contention_state, __cxx_contention_t(1), memory_order_seq_cst); - // We sleep as long as the monitored value hasn't changed. - __libcpp_platform_wait_on_address(__platform_state, __old_value); - __cxx_atomic_fetch_sub(__contention_state, __cxx_contention_t(1), memory_order_release); -} - -/* When the incoming atomic is the wrong size for the platform wait size, need to - launder the value sequence through an atomic from our table. */ - -static void __libcpp_atomic_notify(void const volatile* __location) -{ - auto const __entry = __libcpp_contention_state(__location); - // The value sequence laundering happens on the next line below. - __cxx_atomic_fetch_add(&__entry->__platform_state, __cxx_contention_t(1), memory_order_release); - __libcpp_contention_notify(&__entry->__contention_state, - &__entry->__platform_state, - false /* when laundering, we can't handle notify_one */); -} -_LIBCPP_EXPORTED_FROM_ABI -void __cxx_atomic_notify_one(void const volatile* __location) - { __libcpp_atomic_notify(__location); } -_LIBCPP_EXPORTED_FROM_ABI -void __cxx_atomic_notify_all(void const volatile* __location) - { __libcpp_atomic_notify(__location); } -_LIBCPP_EXPORTED_FROM_ABI -__cxx_contention_t __libcpp_atomic_monitor(void const volatile* __location) -{ - auto const __entry = __libcpp_contention_state(__location); - return __libcpp_contention_monitor_for_wait(&__entry->__contention_state, &__entry->__platform_state); -} -_LIBCPP_EXPORTED_FROM_ABI -void __libcpp_atomic_wait(void const volatile* __location, __cxx_contention_t __old_value) -{ - auto const __entry = __libcpp_contention_state(__location); - __libcpp_contention_wait(&__entry->__contention_state, &__entry->__platform_state, __old_value); -} - -/* When the incoming atomic happens to be the platform wait size, we still need to use the - table for the contention detection, but we can use the atomic directly for the wait. */ - -_LIBCPP_EXPORTED_FROM_ABI -void __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile* __location) -{ - __libcpp_contention_notify(&__libcpp_contention_state(__location)->__contention_state, __location, true); -} -_LIBCPP_EXPORTED_FROM_ABI -void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile* __location) -{ - __libcpp_contention_notify(&__libcpp_contention_state(__location)->__contention_state, __location, false); -} -_LIBCPP_EXPORTED_FROM_ABI -__cxx_contention_t __libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile* __location) -{ - return __libcpp_contention_monitor_for_wait(&__libcpp_contention_state(__location)->__contention_state, __location); -} -_LIBCPP_EXPORTED_FROM_ABI -void __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile* __location, __cxx_contention_t __old_value) -{ - __libcpp_contention_wait(&__libcpp_contention_state(__location)->__contention_state, __location, __old_value); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif //_LIBCPP_HAS_NO_THREADS + +static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, + __cxx_contention_t __val) +{ + __ulock_wait(UL_COMPARE_AND_WAIT, + const_cast<__cxx_atomic_contention_t*>(__ptr), __val, 0); +} + +static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, + bool __notify_one) +{ + __ulock_wake(UL_COMPARE_AND_WAIT | (__notify_one ? 0 : ULF_WAKE_ALL), + const_cast<__cxx_atomic_contention_t*>(__ptr), 0); +} + +#else // <- Add other operating systems here + +// Baseline is just a timed backoff + +static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, + __cxx_contention_t __val) +{ + __libcpp_thread_poll_with_backoff([=]() -> bool { + return !__cxx_nonatomic_compare_equal(__cxx_atomic_load(__ptr, memory_order_relaxed), __val); + }, __libcpp_timed_backoff_policy()); +} + +static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile*, bool) { } + +#endif // __linux__ + +static constexpr size_t __libcpp_contention_table_size = (1 << 8); /* < there's no magic in this number */ + +struct alignas(64) /* aim to avoid false sharing */ __libcpp_contention_table_entry +{ + __cxx_atomic_contention_t __contention_state; + __cxx_atomic_contention_t __platform_state; + inline constexpr __libcpp_contention_table_entry() : + __contention_state(0), __platform_state(0) { } +}; + +static __libcpp_contention_table_entry __libcpp_contention_table[ __libcpp_contention_table_size ]; + +static hash<void const volatile*> __libcpp_contention_hasher; + +static __libcpp_contention_table_entry* __libcpp_contention_state(void const volatile * p) +{ + return &__libcpp_contention_table[__libcpp_contention_hasher(p) & (__libcpp_contention_table_size - 1)]; +} + +/* Given an atomic to track contention and an atomic to actually wait on, which may be + the same atomic, we try to detect contention to avoid spuriously calling the platform. */ + +static void __libcpp_contention_notify(__cxx_atomic_contention_t volatile* __contention_state, + __cxx_atomic_contention_t const volatile* __platform_state, + bool __notify_one) +{ + if(0 != __cxx_atomic_load(__contention_state, memory_order_seq_cst)) + // We only call 'wake' if we consumed a contention bit here. + __libcpp_platform_wake_by_address(__platform_state, __notify_one); +} +static __cxx_contention_t __libcpp_contention_monitor_for_wait(__cxx_atomic_contention_t volatile* __contention_state, + __cxx_atomic_contention_t const volatile* __platform_state) +{ + // We will monitor this value. + return __cxx_atomic_load(__platform_state, memory_order_acquire); +} +static void __libcpp_contention_wait(__cxx_atomic_contention_t volatile* __contention_state, + __cxx_atomic_contention_t const volatile* __platform_state, + __cxx_contention_t __old_value) +{ + __cxx_atomic_fetch_add(__contention_state, __cxx_contention_t(1), memory_order_seq_cst); + // We sleep as long as the monitored value hasn't changed. + __libcpp_platform_wait_on_address(__platform_state, __old_value); + __cxx_atomic_fetch_sub(__contention_state, __cxx_contention_t(1), memory_order_release); +} + +/* When the incoming atomic is the wrong size for the platform wait size, need to + launder the value sequence through an atomic from our table. */ + +static void __libcpp_atomic_notify(void const volatile* __location) +{ + auto const __entry = __libcpp_contention_state(__location); + // The value sequence laundering happens on the next line below. + __cxx_atomic_fetch_add(&__entry->__platform_state, __cxx_contention_t(1), memory_order_release); + __libcpp_contention_notify(&__entry->__contention_state, + &__entry->__platform_state, + false /* when laundering, we can't handle notify_one */); +} +_LIBCPP_EXPORTED_FROM_ABI +void __cxx_atomic_notify_one(void const volatile* __location) + { __libcpp_atomic_notify(__location); } +_LIBCPP_EXPORTED_FROM_ABI +void __cxx_atomic_notify_all(void const volatile* __location) + { __libcpp_atomic_notify(__location); } +_LIBCPP_EXPORTED_FROM_ABI +__cxx_contention_t __libcpp_atomic_monitor(void const volatile* __location) +{ + auto const __entry = __libcpp_contention_state(__location); + return __libcpp_contention_monitor_for_wait(&__entry->__contention_state, &__entry->__platform_state); +} +_LIBCPP_EXPORTED_FROM_ABI +void __libcpp_atomic_wait(void const volatile* __location, __cxx_contention_t __old_value) +{ + auto const __entry = __libcpp_contention_state(__location); + __libcpp_contention_wait(&__entry->__contention_state, &__entry->__platform_state, __old_value); +} + +/* When the incoming atomic happens to be the platform wait size, we still need to use the + table for the contention detection, but we can use the atomic directly for the wait. */ + +_LIBCPP_EXPORTED_FROM_ABI +void __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile* __location) +{ + __libcpp_contention_notify(&__libcpp_contention_state(__location)->__contention_state, __location, true); +} +_LIBCPP_EXPORTED_FROM_ABI +void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile* __location) +{ + __libcpp_contention_notify(&__libcpp_contention_state(__location)->__contention_state, __location, false); +} +_LIBCPP_EXPORTED_FROM_ABI +__cxx_contention_t __libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile* __location) +{ + return __libcpp_contention_monitor_for_wait(&__libcpp_contention_state(__location)->__contention_state, __location); +} +_LIBCPP_EXPORTED_FROM_ABI +void __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile* __location, __cxx_contention_t __old_value) +{ + __libcpp_contention_wait(&__libcpp_contention_state(__location)->__contention_state, __location, __old_value); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif //_LIBCPP_HAS_NO_THREADS diff --git a/contrib/libs/cxxsupp/libcxx/src/barrier.cpp b/contrib/libs/cxxsupp/libcxx/src/barrier.cpp index af68041511..9ee476993b 100644 --- a/contrib/libs/cxxsupp/libcxx/src/barrier.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/barrier.cpp @@ -1,97 +1,97 @@ -//===------------------------- barrier.cpp ---------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include <__config> - -#ifndef _LIBCPP_HAS_NO_THREADS - -#include <barrier> -#include <thread> - -_LIBCPP_BEGIN_NAMESPACE_STD - -#if !defined(_LIBCPP_HAS_NO_TREE_BARRIER) && (_LIBCPP_STD_VER > 11) - -class __barrier_algorithm_base { -public: - struct alignas(64) /* naturally-align the heap state */ __state_t - { - struct { - __atomic_base<__barrier_phase_t> __phase = ATOMIC_VAR_INIT(0); - } __tickets[64]; - }; - - ptrdiff_t& __expected; - unique_ptr<__state_t[]> __state; - - _LIBCPP_HIDDEN - __barrier_algorithm_base(ptrdiff_t& __expected) - : __expected(__expected) - { - size_t const __count = (__expected + 1) >> 1; - __state = unique_ptr<__state_t[]>(new __state_t[__count]); - } - _LIBCPP_HIDDEN - bool __arrive(__barrier_phase_t __old_phase) - { - __barrier_phase_t const __half_step = __old_phase + 1, - __full_step = __old_phase + 2; - size_t __current_expected = __expected, - __current = hash<thread::id>()(this_thread::get_id()) % ((__expected + 1) >> 1); - for(int __round = 0;; ++__round) { - if(__current_expected <= 1) - return true; - size_t const __end_node = ((__current_expected + 1) >> 1), - __last_node = __end_node - 1; - for(;;++__current) { - if(__current == __end_node) - __current = 0; - __barrier_phase_t expect = __old_phase; - if(__current == __last_node && (__current_expected & 1)) - { - if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __full_step, memory_order_acq_rel)) - break; // I'm 1 in 1, go to next __round - } - else if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __half_step, memory_order_acq_rel)) - { - return false; // I'm 1 in 2, done with arrival - } - else if(expect == __half_step) - { - if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __full_step, memory_order_acq_rel)) - break; // I'm 2 in 2, go to next __round - } - } - __current_expected = __last_node + 1; - __current >>= 1; - } - } -}; - -_LIBCPP_EXPORTED_FROM_ABI -__barrier_algorithm_base * __construct_barrier_algorithm_base(ptrdiff_t& __expected) -{ - return new __barrier_algorithm_base(__expected); -} -_LIBCPP_EXPORTED_FROM_ABI -bool __arrive_barrier_algorithm_base(__barrier_algorithm_base* __barrier, - __barrier_phase_t __old_phase) -{ - return __barrier->__arrive(__old_phase); -} -_LIBCPP_EXPORTED_FROM_ABI -void __destroy_barrier_algorithm_base(__barrier_algorithm_base* __barrier) -{ - delete __barrier; -} - -#endif //!defined(_LIBCPP_HAS_NO_TREE_BARRIER) && (_LIBCPP_STD_VER >= 11) - -_LIBCPP_END_NAMESPACE_STD - -#endif //_LIBCPP_HAS_NO_THREADS +//===------------------------- barrier.cpp ---------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <__config> + +#ifndef _LIBCPP_HAS_NO_THREADS + +#include <barrier> +#include <thread> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_TREE_BARRIER) && (_LIBCPP_STD_VER > 11) + +class __barrier_algorithm_base { +public: + struct alignas(64) /* naturally-align the heap state */ __state_t + { + struct { + __atomic_base<__barrier_phase_t> __phase = ATOMIC_VAR_INIT(0); + } __tickets[64]; + }; + + ptrdiff_t& __expected; + unique_ptr<__state_t[]> __state; + + _LIBCPP_HIDDEN + __barrier_algorithm_base(ptrdiff_t& __expected) + : __expected(__expected) + { + size_t const __count = (__expected + 1) >> 1; + __state = unique_ptr<__state_t[]>(new __state_t[__count]); + } + _LIBCPP_HIDDEN + bool __arrive(__barrier_phase_t __old_phase) + { + __barrier_phase_t const __half_step = __old_phase + 1, + __full_step = __old_phase + 2; + size_t __current_expected = __expected, + __current = hash<thread::id>()(this_thread::get_id()) % ((__expected + 1) >> 1); + for(int __round = 0;; ++__round) { + if(__current_expected <= 1) + return true; + size_t const __end_node = ((__current_expected + 1) >> 1), + __last_node = __end_node - 1; + for(;;++__current) { + if(__current == __end_node) + __current = 0; + __barrier_phase_t expect = __old_phase; + if(__current == __last_node && (__current_expected & 1)) + { + if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __full_step, memory_order_acq_rel)) + break; // I'm 1 in 1, go to next __round + } + else if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __half_step, memory_order_acq_rel)) + { + return false; // I'm 1 in 2, done with arrival + } + else if(expect == __half_step) + { + if(__state[__current].__tickets[__round].__phase.compare_exchange_strong(expect, __full_step, memory_order_acq_rel)) + break; // I'm 2 in 2, go to next __round + } + } + __current_expected = __last_node + 1; + __current >>= 1; + } + } +}; + +_LIBCPP_EXPORTED_FROM_ABI +__barrier_algorithm_base * __construct_barrier_algorithm_base(ptrdiff_t& __expected) +{ + return new __barrier_algorithm_base(__expected); +} +_LIBCPP_EXPORTED_FROM_ABI +bool __arrive_barrier_algorithm_base(__barrier_algorithm_base* __barrier, + __barrier_phase_t __old_phase) +{ + return __barrier->__arrive(__old_phase); +} +_LIBCPP_EXPORTED_FROM_ABI +void __destroy_barrier_algorithm_base(__barrier_algorithm_base* __barrier) +{ + delete __barrier; +} + +#endif //!defined(_LIBCPP_HAS_NO_TREE_BARRIER) && (_LIBCPP_STD_VER >= 11) + +_LIBCPP_END_NAMESPACE_STD + +#endif //_LIBCPP_HAS_NO_THREADS diff --git a/contrib/libs/cxxsupp/libcxx/src/bind.cpp b/contrib/libs/cxxsupp/libcxx/src/bind.cpp index ed96a33d0a..53efdf9df3 100644 --- a/contrib/libs/cxxsupp/libcxx/src/bind.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/bind.cpp @@ -1,29 +1,29 @@ -//===-------------------------- bind.cpp ----------------------------------===// -// +//===-------------------------- bind.cpp ----------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "functional" - -_LIBCPP_BEGIN_NAMESPACE_STD - -namespace placeholders -{ - -const __ph<1> _1{}; -const __ph<2> _2{}; -const __ph<3> _3{}; -const __ph<4> _4{}; -const __ph<5> _5{}; -const __ph<6> _6{}; -const __ph<7> _7{}; -const __ph<8> _8{}; -const __ph<9> _9{}; -const __ph<10> _10{}; - -} // placeholders - -_LIBCPP_END_NAMESPACE_STD +// +//===----------------------------------------------------------------------===// + +#include "functional" + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace placeholders +{ + +const __ph<1> _1{}; +const __ph<2> _2{}; +const __ph<3> _3{}; +const __ph<4> _4{}; +const __ph<5> _5{}; +const __ph<6> _6{}; +const __ph<7> _7{}; +const __ph<8> _8{}; +const __ph<9> _9{}; +const __ph<10> _10{}; + +} // placeholders + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/charconv.cpp b/contrib/libs/cxxsupp/libcxx/src/charconv.cpp index 3477aa6836..78439f9683 100644 --- a/contrib/libs/cxxsupp/libcxx/src/charconv.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/charconv.cpp @@ -32,7 +32,7 @@ static constexpr char cDigitsLut[200] = { template <typename T> inline _LIBCPP_INLINE_VISIBILITY char* -append1(char* buffer, T i) noexcept +append1(char* buffer, T i) noexcept { *buffer = '0' + static_cast<char>(i); return buffer + 1; @@ -40,7 +40,7 @@ append1(char* buffer, T i) noexcept template <typename T> inline _LIBCPP_INLINE_VISIBILITY char* -append2(char* buffer, T i) noexcept +append2(char* buffer, T i) noexcept { memcpy(buffer, &cDigitsLut[(i)*2], 2); return buffer + 2; @@ -48,62 +48,62 @@ append2(char* buffer, T i) noexcept template <typename T> inline _LIBCPP_INLINE_VISIBILITY char* -append3(char* buffer, T i) noexcept +append3(char* buffer, T i) noexcept { return append2(append1(buffer, (i) / 100), (i) % 100); } template <typename T> inline _LIBCPP_INLINE_VISIBILITY char* -append4(char* buffer, T i) noexcept +append4(char* buffer, T i) noexcept { return append2(append2(buffer, (i) / 100), (i) % 100); } -template <typename T> -inline _LIBCPP_INLINE_VISIBILITY char* -append2_no_zeros(char* buffer, T v) noexcept -{ - if (v < 10) - return append1(buffer, v); - else - return append2(buffer, v); -} - -template <typename T> -inline _LIBCPP_INLINE_VISIBILITY char* -append4_no_zeros(char* buffer, T v) noexcept -{ - if (v < 100) - return append2_no_zeros(buffer, v); - else if (v < 1000) - return append3(buffer, v); - else - return append4(buffer, v); -} - -template <typename T> -inline _LIBCPP_INLINE_VISIBILITY char* -append8_no_zeros(char* buffer, T v) noexcept -{ - if (v < 10000) - { - buffer = append4_no_zeros(buffer, v); - } - else - { - buffer = append4_no_zeros(buffer, v / 10000); - buffer = append4(buffer, v % 10000); - } - return buffer; -} - -char* -__u32toa(uint32_t value, char* buffer) noexcept -{ - if (value < 100000000) - { - buffer = append8_no_zeros(buffer, value); +template <typename T> +inline _LIBCPP_INLINE_VISIBILITY char* +append2_no_zeros(char* buffer, T v) noexcept +{ + if (v < 10) + return append1(buffer, v); + else + return append2(buffer, v); +} + +template <typename T> +inline _LIBCPP_INLINE_VISIBILITY char* +append4_no_zeros(char* buffer, T v) noexcept +{ + if (v < 100) + return append2_no_zeros(buffer, v); + else if (v < 1000) + return append3(buffer, v); + else + return append4(buffer, v); +} + +template <typename T> +inline _LIBCPP_INLINE_VISIBILITY char* +append8_no_zeros(char* buffer, T v) noexcept +{ + if (v < 10000) + { + buffer = append4_no_zeros(buffer, v); + } + else + { + buffer = append4_no_zeros(buffer, v / 10000); + buffer = append4(buffer, v % 10000); + } + return buffer; +} + +char* +__u32toa(uint32_t value, char* buffer) noexcept +{ + if (value < 100000000) + { + buffer = append8_no_zeros(buffer, value); } else { @@ -111,7 +111,7 @@ __u32toa(uint32_t value, char* buffer) noexcept const uint32_t a = value / 100000000; // 1 to 42 value %= 100000000; - buffer = append2_no_zeros(buffer, a); + buffer = append2_no_zeros(buffer, a); buffer = append4(buffer, value / 10000); buffer = append4(buffer, value % 10000); } @@ -120,19 +120,19 @@ __u32toa(uint32_t value, char* buffer) noexcept } char* -__u64toa(uint64_t value, char* buffer) noexcept +__u64toa(uint64_t value, char* buffer) noexcept { if (value < 100000000) { uint32_t v = static_cast<uint32_t>(value); - buffer = append8_no_zeros(buffer, v); + buffer = append8_no_zeros(buffer, v); } else if (value < 10000000000000000) { const uint32_t v0 = static_cast<uint32_t>(value / 100000000); const uint32_t v1 = static_cast<uint32_t>(value % 100000000); - buffer = append8_no_zeros(buffer, v0); + buffer = append8_no_zeros(buffer, v0); buffer = append4(buffer, v1 / 10000); buffer = append4(buffer, v1 % 10000); } @@ -142,7 +142,7 @@ __u64toa(uint64_t value, char* buffer) noexcept static_cast<uint32_t>(value / 10000000000000000); // 1 to 1844 value %= 10000000000000000; - buffer = append4_no_zeros(buffer, a); + buffer = append4_no_zeros(buffer, a); const uint32_t v0 = static_cast<uint32_t>(value / 100000000); const uint32_t v1 = static_cast<uint32_t>(value % 100000000); diff --git a/contrib/libs/cxxsupp/libcxx/src/chrono.cpp b/contrib/libs/cxxsupp/libcxx/src/chrono.cpp index c2858529f2..b18e4f7cb9 100644 --- a/contrib/libs/cxxsupp/libcxx/src/chrono.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/chrono.cpp @@ -1,298 +1,298 @@ -//===------------------------- chrono.cpp ---------------------------------===// -// +//===------------------------- chrono.cpp ---------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#if defined(__MVS__) -// As part of monotonic clock support on z/OS we need macro _LARGE_TIME_API -// to be defined before any system header to include definition of struct timespec64. -#define _LARGE_TIME_API -#endif - -#include "chrono" -#include "cerrno" // errno -#include "system_error" // __throw_system_error - -#if defined(__MVS__) -#include <__support/ibm/gettod_zos.h> // gettimeofdayMonotonic -#endif - -#include <time.h> // clock_gettime and CLOCK_{MONOTONIC,REALTIME,MONOTONIC_RAW} -#include "include/apple_availability.h" - -#if __has_include(<unistd.h>) -# include <unistd.h> -#endif - -#if __has_include(<sys/time.h>) -# include <sys/time.h> // for gettimeofday and timeval -#endif - -#if !defined(__APPLE__) && defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 -# define _LIBCPP_USE_CLOCK_GETTIME -#endif - -#if defined(_LIBCPP_WIN32API) -# define WIN32_LEAN_AND_MEAN -# define VC_EXTRA_LEAN -# include <windows.h> -# if _WIN32_WINNT >= _WIN32_WINNT_WIN8 -# include <winapifamily.h> -# endif -#endif // defined(_LIBCPP_WIN32API) - -#if __has_include(<mach/mach_time.h>) -# include <mach/mach_time.h> -#endif - -#if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) -# pragma comment(lib, "rt") -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -namespace chrono -{ - -// -// system_clock -// - -#if defined(_LIBCPP_WIN32API) - -#if _WIN32_WINNT < _WIN32_WINNT_WIN8 - -namespace { - -typedef void(WINAPI *GetSystemTimeAsFileTimePtr)(LPFILETIME); - -class GetSystemTimeInit { -public: - GetSystemTimeInit() { - fp = (GetSystemTimeAsFileTimePtr)GetProcAddress( - GetModuleHandleW(L"kernel32.dll"), "GetSystemTimePreciseAsFileTime"); - if (fp == nullptr) - fp = GetSystemTimeAsFileTime; - } - GetSystemTimeAsFileTimePtr fp; -}; - -#ifndef _LIBCPP_COMPILER_MSVC -# 83 "chrono.cpp" 1 3 -#endif -GetSystemTimeInit GetSystemTimeAsFileTimeFunc _LIBCPP_INIT_PRIORITY_MAX; -#ifndef _LIBCPP_COMPILER_MSVC -# 85 "chrono.cpp" 2 -#endif -} // namespace - -#endif - -static system_clock::time_point __libcpp_system_clock_now() { - // FILETIME is in 100ns units - using filetime_duration = - _VSTD::chrono::duration<__int64, - _VSTD::ratio_multiply<_VSTD::ratio<100, 1>, - nanoseconds::period>>; - - // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970. - static _LIBCPP_CONSTEXPR const seconds nt_to_unix_epoch{11644473600}; - - FILETIME ft; -#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8 && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) || \ - (_WIN32_WINNT >= _WIN32_WINNT_WIN10) - GetSystemTimePreciseAsFileTime(&ft); -#elif !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - GetSystemTimeAsFileTime(&ft); -#else - GetSystemTimeAsFileTimeFunc.fp(&ft); -#endif - - filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) | - static_cast<__int64>(ft.dwLowDateTime)}; - return system_clock::time_point(duration_cast<system_clock::duration>(d - nt_to_unix_epoch)); -} - -#elif defined(CLOCK_REALTIME) && defined(_LIBCPP_USE_CLOCK_GETTIME) - -static system_clock::time_point __libcpp_system_clock_now() { +// +//===----------------------------------------------------------------------===// + +#if defined(__MVS__) +// As part of monotonic clock support on z/OS we need macro _LARGE_TIME_API +// to be defined before any system header to include definition of struct timespec64. +#define _LARGE_TIME_API +#endif + +#include "chrono" +#include "cerrno" // errno +#include "system_error" // __throw_system_error + +#if defined(__MVS__) +#include <__support/ibm/gettod_zos.h> // gettimeofdayMonotonic +#endif + +#include <time.h> // clock_gettime and CLOCK_{MONOTONIC,REALTIME,MONOTONIC_RAW} +#include "include/apple_availability.h" + +#if __has_include(<unistd.h>) +# include <unistd.h> +#endif + +#if __has_include(<sys/time.h>) +# include <sys/time.h> // for gettimeofday and timeval +#endif + +#if !defined(__APPLE__) && defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 +# define _LIBCPP_USE_CLOCK_GETTIME +#endif + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define VC_EXTRA_LEAN +# include <windows.h> +# if _WIN32_WINNT >= _WIN32_WINNT_WIN8 +# include <winapifamily.h> +# endif +#endif // defined(_LIBCPP_WIN32API) + +#if __has_include(<mach/mach_time.h>) +# include <mach/mach_time.h> +#endif + +#if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) +# pragma comment(lib, "rt") +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +// +// system_clock +// + +#if defined(_LIBCPP_WIN32API) + +#if _WIN32_WINNT < _WIN32_WINNT_WIN8 + +namespace { + +typedef void(WINAPI *GetSystemTimeAsFileTimePtr)(LPFILETIME); + +class GetSystemTimeInit { +public: + GetSystemTimeInit() { + fp = (GetSystemTimeAsFileTimePtr)GetProcAddress( + GetModuleHandleW(L"kernel32.dll"), "GetSystemTimePreciseAsFileTime"); + if (fp == nullptr) + fp = GetSystemTimeAsFileTime; + } + GetSystemTimeAsFileTimePtr fp; +}; + +#ifndef _LIBCPP_COMPILER_MSVC +# 83 "chrono.cpp" 1 3 +#endif +GetSystemTimeInit GetSystemTimeAsFileTimeFunc _LIBCPP_INIT_PRIORITY_MAX; +#ifndef _LIBCPP_COMPILER_MSVC +# 85 "chrono.cpp" 2 +#endif +} // namespace + +#endif + +static system_clock::time_point __libcpp_system_clock_now() { + // FILETIME is in 100ns units + using filetime_duration = + _VSTD::chrono::duration<__int64, + _VSTD::ratio_multiply<_VSTD::ratio<100, 1>, + nanoseconds::period>>; + + // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970. + static _LIBCPP_CONSTEXPR const seconds nt_to_unix_epoch{11644473600}; + + FILETIME ft; +#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8 && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) || \ + (_WIN32_WINNT >= _WIN32_WINNT_WIN10) + GetSystemTimePreciseAsFileTime(&ft); +#elif !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + GetSystemTimeAsFileTime(&ft); +#else + GetSystemTimeAsFileTimeFunc.fp(&ft); +#endif + + filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) | + static_cast<__int64>(ft.dwLowDateTime)}; + return system_clock::time_point(duration_cast<system_clock::duration>(d - nt_to_unix_epoch)); +} + +#elif defined(CLOCK_REALTIME) && defined(_LIBCPP_USE_CLOCK_GETTIME) + +static system_clock::time_point __libcpp_system_clock_now() { struct timespec tp; if (0 != clock_gettime(CLOCK_REALTIME, &tp)) __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); - return system_clock::time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000)); -} - -#else - -static system_clock::time_point __libcpp_system_clock_now() { - timeval tv; - gettimeofday(&tv, 0); - return system_clock::time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); -} - -#endif - -const bool system_clock::is_steady; - -system_clock::time_point -system_clock::now() noexcept -{ - return __libcpp_system_clock_now(); -} - -time_t -system_clock::to_time_t(const time_point& t) noexcept -{ - return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); -} - -system_clock::time_point -system_clock::from_time_t(time_t t) noexcept -{ - return system_clock::time_point(seconds(t)); -} - -// -// steady_clock -// -// Warning: If this is not truly steady, then it is non-conforming. It is -// better for it to not exist and have the rest of libc++ use system_clock -// instead. -// - -#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK - -#if defined(__APPLE__) - -// TODO(ldionne): -// This old implementation of steady_clock is retained until Chrome drops supports -// for macOS < 10.12. The issue is that they link libc++ statically into their -// application, which means that libc++ must support being built for such deployment -// targets. See https://llvm.org/D74489 for details. -#if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ - (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ - (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ - (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) -# define _LIBCPP_USE_OLD_MACH_ABSOLUTE_TIME -#endif - -#if defined(_LIBCPP_USE_OLD_MACH_ABSOLUTE_TIME) - -// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of -// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom -// are run time constants supplied by the OS. This clock has no relationship -// to the Gregorian calendar. It's main use is as a high resolution timer. - -// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize -// for that case as an optimization. - -static steady_clock::rep steady_simplified() { - return static_cast<steady_clock::rep>(mach_absolute_time()); -} -static double compute_steady_factor() { - mach_timebase_info_data_t MachInfo; - mach_timebase_info(&MachInfo); - return static_cast<double>(MachInfo.numer) / MachInfo.denom; -} - -static steady_clock::rep steady_full() { - static const double factor = compute_steady_factor(); - return static_cast<steady_clock::rep>(mach_absolute_time() * factor); -} - -typedef steady_clock::rep (*FP)(); - -static FP init_steady_clock() { - mach_timebase_info_data_t MachInfo; - mach_timebase_info(&MachInfo); - if (MachInfo.numer == MachInfo.denom) - return &steady_simplified; - return &steady_full; -} - -static steady_clock::time_point __libcpp_steady_clock_now() { - static FP fp = init_steady_clock(); - return steady_clock::time_point(steady_clock::duration(fp())); -} - -#else // vvvvv default behavior for Apple platforms vvvvv - -// On Apple platforms, only CLOCK_UPTIME_RAW, CLOCK_MONOTONIC_RAW or -// mach_absolute_time are able to time functions in the nanosecond range. -// Furthermore, only CLOCK_MONOTONIC_RAW is truly monotonic, because it -// also counts cycles when the system is asleep. Thus, it is the only -// acceptable implementation of steady_clock. -static steady_clock::time_point __libcpp_steady_clock_now() { - struct timespec tp; - if (0 != clock_gettime(CLOCK_MONOTONIC_RAW, &tp)) - __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC_RAW) failed"); - return steady_clock::time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); -} - -#endif - -#elif defined(_LIBCPP_WIN32API) - -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx says: -// If the function fails, the return value is zero. <snip> -// On systems that run Windows XP or later, the function will always succeed -// and will thus never return zero. - -static LARGE_INTEGER -__QueryPerformanceFrequency() -{ + return system_clock::time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000)); +} + +#else + +static system_clock::time_point __libcpp_system_clock_now() { + timeval tv; + gettimeofday(&tv, 0); + return system_clock::time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); +} + +#endif + +const bool system_clock::is_steady; + +system_clock::time_point +system_clock::now() noexcept +{ + return __libcpp_system_clock_now(); +} + +time_t +system_clock::to_time_t(const time_point& t) noexcept +{ + return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); +} + +system_clock::time_point +system_clock::from_time_t(time_t t) noexcept +{ + return system_clock::time_point(seconds(t)); +} + +// +// steady_clock +// +// Warning: If this is not truly steady, then it is non-conforming. It is +// better for it to not exist and have the rest of libc++ use system_clock +// instead. +// + +#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK + +#if defined(__APPLE__) + +// TODO(ldionne): +// This old implementation of steady_clock is retained until Chrome drops supports +// for macOS < 10.12. The issue is that they link libc++ statically into their +// application, which means that libc++ must support being built for such deployment +// targets. See https://llvm.org/D74489 for details. +#if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101200) || \ + (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 100000) || \ + (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 30000) +# define _LIBCPP_USE_OLD_MACH_ABSOLUTE_TIME +#endif + +#if defined(_LIBCPP_USE_OLD_MACH_ABSOLUTE_TIME) + +// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of +// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom +// are run time constants supplied by the OS. This clock has no relationship +// to the Gregorian calendar. It's main use is as a high resolution timer. + +// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize +// for that case as an optimization. + +static steady_clock::rep steady_simplified() { + return static_cast<steady_clock::rep>(mach_absolute_time()); +} +static double compute_steady_factor() { + mach_timebase_info_data_t MachInfo; + mach_timebase_info(&MachInfo); + return static_cast<double>(MachInfo.numer) / MachInfo.denom; +} + +static steady_clock::rep steady_full() { + static const double factor = compute_steady_factor(); + return static_cast<steady_clock::rep>(mach_absolute_time() * factor); +} + +typedef steady_clock::rep (*FP)(); + +static FP init_steady_clock() { + mach_timebase_info_data_t MachInfo; + mach_timebase_info(&MachInfo); + if (MachInfo.numer == MachInfo.denom) + return &steady_simplified; + return &steady_full; +} + +static steady_clock::time_point __libcpp_steady_clock_now() { + static FP fp = init_steady_clock(); + return steady_clock::time_point(steady_clock::duration(fp())); +} + +#else // vvvvv default behavior for Apple platforms vvvvv + +// On Apple platforms, only CLOCK_UPTIME_RAW, CLOCK_MONOTONIC_RAW or +// mach_absolute_time are able to time functions in the nanosecond range. +// Furthermore, only CLOCK_MONOTONIC_RAW is truly monotonic, because it +// also counts cycles when the system is asleep. Thus, it is the only +// acceptable implementation of steady_clock. +static steady_clock::time_point __libcpp_steady_clock_now() { + struct timespec tp; + if (0 != clock_gettime(CLOCK_MONOTONIC_RAW, &tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC_RAW) failed"); + return steady_clock::time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); +} + +#endif + +#elif defined(_LIBCPP_WIN32API) + +// https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx says: +// If the function fails, the return value is zero. <snip> +// On systems that run Windows XP or later, the function will always succeed +// and will thus never return zero. + +static LARGE_INTEGER +__QueryPerformanceFrequency() +{ LARGE_INTEGER val; (void) QueryPerformanceFrequency(&val); return val; -} - -static steady_clock::time_point __libcpp_steady_clock_now() { - static const LARGE_INTEGER freq = __QueryPerformanceFrequency(); - - LARGE_INTEGER counter; - (void) QueryPerformanceCounter(&counter); - auto seconds = counter.QuadPart / freq.QuadPart; - auto fractions = counter.QuadPart % freq.QuadPart; - auto dur = seconds * nano::den + fractions * nano::den / freq.QuadPart; - return steady_clock::time_point(steady_clock::duration(dur)); -} - -#elif defined(__MVS__) - -static steady_clock::time_point __libcpp_steady_clock_now() { - struct timespec64 ts; - if (0 != gettimeofdayMonotonic(&ts)) - __throw_system_error(errno, "failed to obtain time of day"); - - return steady_clock::time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec)); -} - -#elif defined(CLOCK_MONOTONIC) - -static steady_clock::time_point __libcpp_steady_clock_now() { - struct timespec tp; - if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) - __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); - return steady_clock::time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); -} - -#else -# error "Monotonic clock not implemented on this platform" -#endif - -const bool steady_clock::is_steady; - -steady_clock::time_point -steady_clock::now() noexcept -{ - return __libcpp_steady_clock_now(); -} - -#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK - -} - -_LIBCPP_END_NAMESPACE_STD +} + +static steady_clock::time_point __libcpp_steady_clock_now() { + static const LARGE_INTEGER freq = __QueryPerformanceFrequency(); + + LARGE_INTEGER counter; + (void) QueryPerformanceCounter(&counter); + auto seconds = counter.QuadPart / freq.QuadPart; + auto fractions = counter.QuadPart % freq.QuadPart; + auto dur = seconds * nano::den + fractions * nano::den / freq.QuadPart; + return steady_clock::time_point(steady_clock::duration(dur)); +} + +#elif defined(__MVS__) + +static steady_clock::time_point __libcpp_steady_clock_now() { + struct timespec64 ts; + if (0 != gettimeofdayMonotonic(&ts)) + __throw_system_error(errno, "failed to obtain time of day"); + + return steady_clock::time_point(seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec)); +} + +#elif defined(CLOCK_MONOTONIC) + +static steady_clock::time_point __libcpp_steady_clock_now() { + struct timespec tp; + if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); + return steady_clock::time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); +} + +#else +# error "Monotonic clock not implemented on this platform" +#endif + +const bool steady_clock::is_steady; + +steady_clock::time_point +steady_clock::now() noexcept +{ + return __libcpp_steady_clock_now(); +} + +#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK + +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/condition_variable.cpp b/contrib/libs/cxxsupp/libcxx/src/condition_variable.cpp index ddc11d6ba4..1e29083e6e 100644 --- a/contrib/libs/cxxsupp/libcxx/src/condition_variable.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/condition_variable.cpp @@ -1,93 +1,93 @@ -//===-------------------- condition_variable.cpp --------------------------===// -// +//===-------------------- condition_variable.cpp --------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "__config" - -#ifndef _LIBCPP_HAS_NO_THREADS - -#include "condition_variable" -#include "thread" -#include "system_error" -#include "__undef_macros" - -#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -#pragma comment(lib, "pthread") -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -// ~condition_variable is defined elsewhere. - -void -condition_variable::notify_one() noexcept -{ - __libcpp_condvar_signal(&__cv_); -} - -void -condition_variable::notify_all() noexcept -{ - __libcpp_condvar_broadcast(&__cv_); -} - -void -condition_variable::wait(unique_lock<mutex>& lk) noexcept -{ - if (!lk.owns_lock()) - __throw_system_error(EPERM, - "condition_variable::wait: mutex not locked"); - int ec = __libcpp_condvar_wait(&__cv_, lk.mutex()->native_handle()); - if (ec) - __throw_system_error(ec, "condition_variable wait failed"); -} - -void -condition_variable::__do_timed_wait(unique_lock<mutex>& lk, - chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) noexcept -{ - using namespace chrono; - if (!lk.owns_lock()) - __throw_system_error(EPERM, - "condition_variable::timed wait: mutex not locked"); - nanoseconds d = tp.time_since_epoch(); - if (d > nanoseconds(0x59682F000000E941)) - d = nanoseconds(0x59682F000000E941); - __libcpp_timespec_t ts; - seconds s = duration_cast<seconds>(d); - typedef decltype(ts.tv_sec) ts_sec; - _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); - if (s.count() < ts_sec_max) - { - ts.tv_sec = static_cast<ts_sec>(s.count()); - ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count()); - } - else - { - ts.tv_sec = ts_sec_max; - ts.tv_nsec = giga::num - 1; - } - int ec = __libcpp_condvar_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); - if (ec != 0 && ec != ETIMEDOUT) - __throw_system_error(ec, "condition_variable timed_wait failed"); -} - -void -notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) -{ - auto& tl_ptr = __thread_local_data(); - // If this thread was not created using std::thread then it will not have - // previously allocated. - if (tl_ptr.get() == nullptr) { - tl_ptr.set_pointer(new __thread_struct); - } - __thread_local_data()->notify_all_at_thread_exit(&cond, lk.release()); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !_LIBCPP_HAS_NO_THREADS +// +//===----------------------------------------------------------------------===// + +#include "__config" + +#ifndef _LIBCPP_HAS_NO_THREADS + +#include "condition_variable" +#include "thread" +#include "system_error" +#include "__undef_macros" + +#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +#pragma comment(lib, "pthread") +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// ~condition_variable is defined elsewhere. + +void +condition_variable::notify_one() noexcept +{ + __libcpp_condvar_signal(&__cv_); +} + +void +condition_variable::notify_all() noexcept +{ + __libcpp_condvar_broadcast(&__cv_); +} + +void +condition_variable::wait(unique_lock<mutex>& lk) noexcept +{ + if (!lk.owns_lock()) + __throw_system_error(EPERM, + "condition_variable::wait: mutex not locked"); + int ec = __libcpp_condvar_wait(&__cv_, lk.mutex()->native_handle()); + if (ec) + __throw_system_error(ec, "condition_variable wait failed"); +} + +void +condition_variable::__do_timed_wait(unique_lock<mutex>& lk, + chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) noexcept +{ + using namespace chrono; + if (!lk.owns_lock()) + __throw_system_error(EPERM, + "condition_variable::timed wait: mutex not locked"); + nanoseconds d = tp.time_since_epoch(); + if (d > nanoseconds(0x59682F000000E941)) + d = nanoseconds(0x59682F000000E941); + __libcpp_timespec_t ts; + seconds s = duration_cast<seconds>(d); + typedef decltype(ts.tv_sec) ts_sec; + _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max(); + if (s.count() < ts_sec_max) + { + ts.tv_sec = static_cast<ts_sec>(s.count()); + ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count()); + } + else + { + ts.tv_sec = ts_sec_max; + ts.tv_nsec = giga::num - 1; + } + int ec = __libcpp_condvar_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); + if (ec != 0 && ec != ETIMEDOUT) + __throw_system_error(ec, "condition_variable timed_wait failed"); +} + +void +notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) +{ + auto& tl_ptr = __thread_local_data(); + // If this thread was not created using std::thread then it will not have + // previously allocated. + if (tl_ptr.get() == nullptr) { + tl_ptr.set_pointer(new __thread_struct); + } + __thread_local_data()->notify_all_at_thread_exit(&cond, lk.release()); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !_LIBCPP_HAS_NO_THREADS diff --git a/contrib/libs/cxxsupp/libcxx/src/condition_variable_destructor.cpp b/contrib/libs/cxxsupp/libcxx/src/condition_variable_destructor.cpp index 347244af71..44fa240ba7 100644 --- a/contrib/libs/cxxsupp/libcxx/src/condition_variable_destructor.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/condition_variable_destructor.cpp @@ -1,46 +1,46 @@ -//===---------------- condition_variable_destructor.cpp ------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -// Define ~condition_variable. -// -// On some platforms ~condition_variable has been made trivial and the -// definition is only provided for ABI compatibility. - -#include "__config" -#include "__threading_support" - -#if !defined(_LIBCPP_HAS_NO_THREADS) -# if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION) -# define NEEDS_CONDVAR_DESTRUCTOR -# endif -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -#ifdef NEEDS_CONDVAR_DESTRUCTOR - -class _LIBCPP_TYPE_VIS condition_variable -{ - __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; -public: - _LIBCPP_INLINE_VISIBILITY - constexpr condition_variable() noexcept = default; - - ~condition_variable(); - - condition_variable(const condition_variable&) = delete; - condition_variable& operator=(const condition_variable&) = delete; -}; - -condition_variable::~condition_variable() -{ - __libcpp_condvar_destroy(&__cv_); -} -#endif - -_LIBCPP_END_NAMESPACE_STD +//===---------------- condition_variable_destructor.cpp ------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// Define ~condition_variable. +// +// On some platforms ~condition_variable has been made trivial and the +// definition is only provided for ABI compatibility. + +#include "__config" +#include "__threading_support" + +#if !defined(_LIBCPP_HAS_NO_THREADS) +# if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION) +# define NEEDS_CONDVAR_DESTRUCTOR +# endif +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifdef NEEDS_CONDVAR_DESTRUCTOR + +class _LIBCPP_TYPE_VIS condition_variable +{ + __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; +public: + _LIBCPP_INLINE_VISIBILITY + constexpr condition_variable() noexcept = default; + + ~condition_variable(); + + condition_variable(const condition_variable&) = delete; + condition_variable& operator=(const condition_variable&) = delete; +}; + +condition_variable::~condition_variable() +{ + __libcpp_condvar_destroy(&__cv_); +} +#endif + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/debug.cpp b/contrib/libs/cxxsupp/libcxx/src/debug.cpp index 7b7a770f18..dd5963fcce 100644 --- a/contrib/libs/cxxsupp/libcxx/src/debug.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/debug.cpp @@ -1,578 +1,578 @@ -//===-------------------------- debug.cpp ---------------------------------===// -// +//===-------------------------- debug.cpp ---------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "__config" -#include "__debug" -#include "functional" -#include "algorithm" -#include "string" -#include "cstdio" -#include "__hash_table" -#ifndef _LIBCPP_HAS_NO_THREADS -#include "mutex" -#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -#pragma comment(lib, "pthread") -#endif -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -std::string __libcpp_debug_info::what() const { - string msg = __file_; - msg += ":" + to_string(__line_) + ": _LIBCPP_ASSERT '"; - msg += __pred_; - msg += "' failed. "; - msg += __msg_; - return msg; -} -_LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) { - std::fprintf(stderr, "%s\n", info.what().c_str()); - std::abort(); -} - -_LIBCPP_SAFE_STATIC __libcpp_debug_function_type - __libcpp_debug_function = __libcpp_abort_debug_function; - -bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) { - __libcpp_debug_function = __func; - return true; -} - -_LIBCPP_FUNC_VIS -__libcpp_db* -__get_db() -{ - static _LIBCPP_NO_DESTROY __libcpp_db db; - return &db; -} - -_LIBCPP_FUNC_VIS -const __libcpp_db* -__get_const_db() -{ - return __get_db(); -} - -namespace -{ - -#ifndef _LIBCPP_HAS_NO_THREADS -typedef mutex mutex_type; -typedef lock_guard<mutex_type> WLock; -typedef lock_guard<mutex_type> RLock; - -mutex_type& -mut() -{ - static _LIBCPP_NO_DESTROY mutex_type m; - return m; -} -#endif // !_LIBCPP_HAS_NO_THREADS - -} // unnamed namespace - -__i_node::~__i_node() -{ - if (__next_) - { - __next_->~__i_node(); - free(__next_); - } -} - -__c_node::~__c_node() -{ - free(beg_); - if (__next_) - { - __next_->~__c_node(); - free(__next_); - } -} - -__libcpp_db::__libcpp_db() - : __cbeg_(nullptr), - __cend_(nullptr), - __csz_(0), - __ibeg_(nullptr), - __iend_(nullptr), - __isz_(0) -{ -} - -__libcpp_db::~__libcpp_db() -{ - if (__cbeg_) - { - for (__c_node** p = __cbeg_; p != __cend_; ++p) - { - if (*p != nullptr) - { - (*p)->~__c_node(); - free(*p); - } - } - free(__cbeg_); - } - if (__ibeg_) - { - for (__i_node** p = __ibeg_; p != __iend_; ++p) - { - if (*p != nullptr) - { - (*p)->~__i_node(); - free(*p); - } - } - free(__ibeg_); - } -} - -void* -__libcpp_db::__find_c_from_i(void* __i) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database."); - return i->__c_ != nullptr ? i->__c_->__c_ : nullptr; -} - -void -__libcpp_db::__insert_ic(void* __i, const void* __c) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - if (__cbeg_ == __cend_) - return; - size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* c = __cbeg_[hc]; - if (c == nullptr) - return; - while (c->__c_ != __c) - { - c = c->__next_; - if (c == nullptr) - return; - } - __i_node* i = __insert_iterator(__i); - c->__add(i); - i->__c_ = c; -} - -void -__libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_)) - { - size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1); - __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*))); - if (cbeg == nullptr) - __throw_bad_alloc(); - - for (__c_node** p = __cbeg_; p != __cend_; ++p) - { - __c_node* q = *p; - while (q != nullptr) - { - size_t h = hash<void*>()(q->__c_) % nc; - __c_node* r = q->__next_; - q->__next_ = cbeg[h]; - cbeg[h] = q; - q = r; - } - } - free(__cbeg_); - __cbeg_ = cbeg; - __cend_ = __cbeg_ + nc; - } - size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - void *buf = malloc(sizeof(__c_node)); - if (buf == nullptr) +// +//===----------------------------------------------------------------------===// + +#include "__config" +#include "__debug" +#include "functional" +#include "algorithm" +#include "string" +#include "cstdio" +#include "__hash_table" +#ifndef _LIBCPP_HAS_NO_THREADS +#include "mutex" +#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +#pragma comment(lib, "pthread") +#endif +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +std::string __libcpp_debug_info::what() const { + string msg = __file_; + msg += ":" + to_string(__line_) + ": _LIBCPP_ASSERT '"; + msg += __pred_; + msg += "' failed. "; + msg += __msg_; + return msg; +} +_LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) { + std::fprintf(stderr, "%s\n", info.what().c_str()); + std::abort(); +} + +_LIBCPP_SAFE_STATIC __libcpp_debug_function_type + __libcpp_debug_function = __libcpp_abort_debug_function; + +bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) { + __libcpp_debug_function = __func; + return true; +} + +_LIBCPP_FUNC_VIS +__libcpp_db* +__get_db() +{ + static _LIBCPP_NO_DESTROY __libcpp_db db; + return &db; +} + +_LIBCPP_FUNC_VIS +const __libcpp_db* +__get_const_db() +{ + return __get_db(); +} + +namespace +{ + +#ifndef _LIBCPP_HAS_NO_THREADS +typedef mutex mutex_type; +typedef lock_guard<mutex_type> WLock; +typedef lock_guard<mutex_type> RLock; + +mutex_type& +mut() +{ + static _LIBCPP_NO_DESTROY mutex_type m; + return m; +} +#endif // !_LIBCPP_HAS_NO_THREADS + +} // unnamed namespace + +__i_node::~__i_node() +{ + if (__next_) + { + __next_->~__i_node(); + free(__next_); + } +} + +__c_node::~__c_node() +{ + free(beg_); + if (__next_) + { + __next_->~__c_node(); + free(__next_); + } +} + +__libcpp_db::__libcpp_db() + : __cbeg_(nullptr), + __cend_(nullptr), + __csz_(0), + __ibeg_(nullptr), + __iend_(nullptr), + __isz_(0) +{ +} + +__libcpp_db::~__libcpp_db() +{ + if (__cbeg_) + { + for (__c_node** p = __cbeg_; p != __cend_; ++p) + { + if (*p != nullptr) + { + (*p)->~__c_node(); + free(*p); + } + } + free(__cbeg_); + } + if (__ibeg_) + { + for (__i_node** p = __ibeg_; p != __iend_; ++p) + { + if (*p != nullptr) + { + (*p)->~__i_node(); + free(*p); + } + } + free(__ibeg_); + } +} + +void* +__libcpp_db::__find_c_from_i(void* __i) const +{ +#ifndef _LIBCPP_HAS_NO_THREADS + RLock _(mut()); +#endif + __i_node* i = __find_iterator(__i); + _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database."); + return i->__c_ != nullptr ? i->__c_->__c_ : nullptr; +} + +void +__libcpp_db::__insert_ic(void* __i, const void* __c) +{ +#ifndef _LIBCPP_HAS_NO_THREADS + WLock _(mut()); +#endif + if (__cbeg_ == __cend_) + return; + size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); + __c_node* c = __cbeg_[hc]; + if (c == nullptr) + return; + while (c->__c_ != __c) + { + c = c->__next_; + if (c == nullptr) + return; + } + __i_node* i = __insert_iterator(__i); + c->__add(i); + i->__c_ = c; +} + +void +__libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn) +{ +#ifndef _LIBCPP_HAS_NO_THREADS + WLock _(mut()); +#endif + if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_)) + { + size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1); + __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*))); + if (cbeg == nullptr) + __throw_bad_alloc(); + + for (__c_node** p = __cbeg_; p != __cend_; ++p) + { + __c_node* q = *p; + while (q != nullptr) + { + size_t h = hash<void*>()(q->__c_) % nc; + __c_node* r = q->__next_; + q->__next_ = cbeg[h]; + cbeg[h] = q; + q = r; + } + } + free(__cbeg_); + __cbeg_ = cbeg; + __cend_ = __cbeg_ + nc; + } + size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); + __c_node* p = __cbeg_[hc]; + void *buf = malloc(sizeof(__c_node)); + if (buf == nullptr) __throw_bad_alloc(); - __cbeg_[hc] = __fn(buf, __c, p); - - ++__csz_; -} - -void -__libcpp_db::__erase_i(void* __i) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - if (__ibeg_ != __iend_) - { - size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); - __i_node* p = __ibeg_[hi]; - if (p != nullptr) - { - __i_node* q = nullptr; - while (p->__i_ != __i) - { - q = p; - p = p->__next_; - if (p == nullptr) - return; - } - if (q == nullptr) - __ibeg_[hi] = p->__next_; - else - q->__next_ = p->__next_; - __c_node* c = p->__c_; - --__isz_; - if (c != nullptr) - c->__remove(p); - free(p); - } - } -} - -void -__libcpp_db::__invalidate_all(void* __c) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - if (__cend_ != __cbeg_) - { - size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - if (p == nullptr) - return; - while (p->__c_ != __c) - { - p = p->__next_; - if (p == nullptr) - return; - } - while (p->end_ != p->beg_) - { - --p->end_; - (*p->end_)->__c_ = nullptr; - } - } -} - -__c_node* -__libcpp_db::__find_c_and_lock(void* __c) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - mut().lock(); -#endif - if (__cend_ == __cbeg_) - { -#ifndef _LIBCPP_HAS_NO_THREADS - mut().unlock(); -#endif - return nullptr; - } - size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - if (p == nullptr) - { -#ifndef _LIBCPP_HAS_NO_THREADS - mut().unlock(); -#endif - return nullptr; - } - while (p->__c_ != __c) - { - p = p->__next_; - if (p == nullptr) - { -#ifndef _LIBCPP_HAS_NO_THREADS - mut().unlock(); -#endif - return nullptr; - } - } - return p; -} - -__c_node* -__libcpp_db::__find_c(void* __c) const -{ - size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A"); - while (p->__c_ != __c) - { - p = p->__next_; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B"); - } - return p; -} - -void -__libcpp_db::unlock() const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - mut().unlock(); -#endif -} - -void -__libcpp_db::__erase_c(void* __c) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - if (__cend_ != __cbeg_) - { - size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - if (p == nullptr) - return; - __c_node* q = nullptr; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A"); - while (p->__c_ != __c) - { - q = p; - p = p->__next_; - if (p == nullptr) - return; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B"); - } - if (q == nullptr) - __cbeg_[hc] = p->__next_; - else - q->__next_ = p->__next_; - while (p->end_ != p->beg_) - { - --p->end_; - (*p->end_)->__c_ = nullptr; - } - free(p->beg_); - free(p); - --__csz_; - } -} - -void -__libcpp_db::__iterator_copy(void* __i, const void* __i0) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - __i_node* i0 = __find_iterator(__i0); - __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr; - if (i == nullptr && i0 != nullptr) - i = __insert_iterator(__i); - __c_node* c = i != nullptr ? i->__c_ : nullptr; - if (c != c0) - { - if (c != nullptr) - c->__remove(i); - if (i != nullptr) - { - i->__c_ = nullptr; - if (c0 != nullptr) - { - i->__c_ = c0; - i->__c_->__add(i); - } - } - } -} - -bool -__libcpp_db::__dereferenceable(const void* __i) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i); -} - -bool -__libcpp_db::__decrementable(const void* __i) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i); -} - -bool -__libcpp_db::__addable(const void* __i, ptrdiff_t __n) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n); -} - -bool -__libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n); -} - -bool -__libcpp_db::__less_than_comparable(const void* __i, const void* __j) const -{ -#ifndef _LIBCPP_HAS_NO_THREADS - RLock _(mut()); -#endif - __i_node* i = __find_iterator(__i); - __i_node* j = __find_iterator(__j); - __c_node* ci = i != nullptr ? i->__c_ : nullptr; - __c_node* cj = j != nullptr ? j->__c_ : nullptr; - return ci == cj; -} - -void -__libcpp_db::swap(void* c1, void* c2) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p1 = __cbeg_[hc]; - _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A"); - while (p1->__c_ != c1) - { - p1 = p1->__next_; - _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B"); - } - hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_); - __c_node* p2 = __cbeg_[hc]; - _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C"); - while (p2->__c_ != c2) - { - p2 = p2->__next_; - _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D"); - } - std::swap(p1->beg_, p2->beg_); - std::swap(p1->end_, p2->end_); - std::swap(p1->cap_, p2->cap_); - for (__i_node** p = p1->beg_; p != p1->end_; ++p) - (*p)->__c_ = p1; - for (__i_node** p = p2->beg_; p != p2->end_; ++p) - (*p)->__c_ = p2; -} - -void -__libcpp_db::__insert_i(void* __i) -{ -#ifndef _LIBCPP_HAS_NO_THREADS - WLock _(mut()); -#endif - __insert_iterator(__i); -} - -void -__c_node::__add(__i_node* i) -{ - if (end_ == cap_) - { - size_t nc = 2*static_cast<size_t>(cap_ - beg_); - if (nc == 0) - nc = 1; - __i_node** beg = - static_cast<__i_node**>(malloc(nc * sizeof(__i_node*))); - if (beg == nullptr) - __throw_bad_alloc(); - - if (nc > 1) - memcpy(beg, beg_, nc/2*sizeof(__i_node*)); - free(beg_); - beg_ = beg; - end_ = beg_ + nc/2; - cap_ = beg_ + nc; - } - *end_++ = i; -} - -// private api - -_LIBCPP_HIDDEN -__i_node* -__libcpp_db::__insert_iterator(void* __i) -{ - if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_)) - { - size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1); - __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(__i_node*))); - if (ibeg == nullptr) - __throw_bad_alloc(); - - for (__i_node** p = __ibeg_; p != __iend_; ++p) - { - __i_node* q = *p; - while (q != nullptr) - { - size_t h = hash<void*>()(q->__i_) % nc; - __i_node* r = q->__next_; - q->__next_ = ibeg[h]; - ibeg[h] = q; - q = r; - } - } - free(__ibeg_); - __ibeg_ = ibeg; - __iend_ = __ibeg_ + nc; - } - size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); - __i_node* p = __ibeg_[hi]; - __i_node* r = __ibeg_[hi] = - static_cast<__i_node*>(malloc(sizeof(__i_node))); - if (r == nullptr) - __throw_bad_alloc(); - - ::new(r) __i_node(__i, p, nullptr); - ++__isz_; - return r; -} - -_LIBCPP_HIDDEN -__i_node* -__libcpp_db::__find_iterator(const void* __i) const -{ - __i_node* r = nullptr; - if (__ibeg_ != __iend_) - { - size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); - for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_) - { - if (nd->__i_ == __i) - { - r = nd; - break; - } - } - } - return r; -} - -_LIBCPP_HIDDEN -void -__c_node::__remove(__i_node* p) -{ - __i_node** r = find(beg_, end_, p); - _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove"); - if (--end_ != r) - memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*)); -} - -_LIBCPP_END_NAMESPACE_STD + __cbeg_[hc] = __fn(buf, __c, p); + + ++__csz_; +} + +void +__libcpp_db::__erase_i(void* __i) +{ +#ifndef _LIBCPP_HAS_NO_THREADS + WLock _(mut()); +#endif + if (__ibeg_ != __iend_) + { + size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); + __i_node* p = __ibeg_[hi]; + if (p != nullptr) + { + __i_node* q = nullptr; + while (p->__i_ != __i) + { + q = p; + p = p->__next_; + if (p == nullptr) + return; + } + if (q == nullptr) + __ibeg_[hi] = p->__next_; + else + q->__next_ = p->__next_; + __c_node* c = p->__c_; + --__isz_; + if (c != nullptr) + c->__remove(p); + free(p); + } + } +} + +void +__libcpp_db::__invalidate_all(void* __c) +{ +#ifndef _LIBCPP_HAS_NO_THREADS + WLock _(mut()); +#endif + if (__cend_ != __cbeg_) + { + size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); + __c_node* p = __cbeg_[hc]; + if (p == nullptr) + return; + while (p->__c_ != __c) + { + p = p->__next_; + if (p == nullptr) + return; + } + while (p->end_ != p->beg_) + { + --p->end_; + (*p->end_)->__c_ = nullptr; + } + } +} + +__c_node* +__libcpp_db::__find_c_and_lock(void* __c) const +{ +#ifndef _LIBCPP_HAS_NO_THREADS + mut().lock(); +#endif + if (__cend_ == __cbeg_) + { +#ifndef _LIBCPP_HAS_NO_THREADS + mut().unlock(); +#endif + return nullptr; + } + size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); + __c_node* p = __cbeg_[hc]; + if (p == nullptr) + { +#ifndef _LIBCPP_HAS_NO_THREADS + mut().unlock(); +#endif + return nullptr; + } + while (p->__c_ != __c) + { + p = p->__next_; + if (p == nullptr) + { +#ifndef _LIBCPP_HAS_NO_THREADS + mut().unlock(); +#endif + return nullptr; + } + } + return p; +} + +__c_node* +__libcpp_db::__find_c(void* __c) const +{ + size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); + __c_node* p = __cbeg_[hc]; + _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A"); + while (p->__c_ != __c) + { + p = p->__next_; + _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B"); + } + return p; +} + +void +__libcpp_db::unlock() const +{ +#ifndef _LIBCPP_HAS_NO_THREADS + mut().unlock(); +#endif +} + +void +__libcpp_db::__erase_c(void* __c) +{ +#ifndef _LIBCPP_HAS_NO_THREADS + WLock _(mut()); +#endif + if (__cend_ != __cbeg_) + { + size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); + __c_node* p = __cbeg_[hc]; + if (p == nullptr) + return; + __c_node* q = nullptr; + _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A"); + while (p->__c_ != __c) + { + q = p; + p = p->__next_; + if (p == nullptr) + return; + _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B"); + } + if (q == nullptr) + __cbeg_[hc] = p->__next_; + else + q->__next_ = p->__next_; + while (p->end_ != p->beg_) + { + --p->end_; + (*p->end_)->__c_ = nullptr; + } + free(p->beg_); + free(p); + --__csz_; + } +} + +void +__libcpp_db::__iterator_copy(void* __i, const void* __i0) +{ +#ifndef _LIBCPP_HAS_NO_THREADS + WLock _(mut()); +#endif + __i_node* i = __find_iterator(__i); + __i_node* i0 = __find_iterator(__i0); + __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr; + if (i == nullptr && i0 != nullptr) + i = __insert_iterator(__i); + __c_node* c = i != nullptr ? i->__c_ : nullptr; + if (c != c0) + { + if (c != nullptr) + c->__remove(i); + if (i != nullptr) + { + i->__c_ = nullptr; + if (c0 != nullptr) + { + i->__c_ = c0; + i->__c_->__add(i); + } + } + } +} + +bool +__libcpp_db::__dereferenceable(const void* __i) const +{ +#ifndef _LIBCPP_HAS_NO_THREADS + RLock _(mut()); +#endif + __i_node* i = __find_iterator(__i); + return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i); +} + +bool +__libcpp_db::__decrementable(const void* __i) const +{ +#ifndef _LIBCPP_HAS_NO_THREADS + RLock _(mut()); +#endif + __i_node* i = __find_iterator(__i); + return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i); +} + +bool +__libcpp_db::__addable(const void* __i, ptrdiff_t __n) const +{ +#ifndef _LIBCPP_HAS_NO_THREADS + RLock _(mut()); +#endif + __i_node* i = __find_iterator(__i); + return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n); +} + +bool +__libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const +{ +#ifndef _LIBCPP_HAS_NO_THREADS + RLock _(mut()); +#endif + __i_node* i = __find_iterator(__i); + return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n); +} + +bool +__libcpp_db::__less_than_comparable(const void* __i, const void* __j) const +{ +#ifndef _LIBCPP_HAS_NO_THREADS + RLock _(mut()); +#endif + __i_node* i = __find_iterator(__i); + __i_node* j = __find_iterator(__j); + __c_node* ci = i != nullptr ? i->__c_ : nullptr; + __c_node* cj = j != nullptr ? j->__c_ : nullptr; + return ci == cj; +} + +void +__libcpp_db::swap(void* c1, void* c2) +{ +#ifndef _LIBCPP_HAS_NO_THREADS + WLock _(mut()); +#endif + size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_); + __c_node* p1 = __cbeg_[hc]; + _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A"); + while (p1->__c_ != c1) + { + p1 = p1->__next_; + _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B"); + } + hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_); + __c_node* p2 = __cbeg_[hc]; + _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C"); + while (p2->__c_ != c2) + { + p2 = p2->__next_; + _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D"); + } + std::swap(p1->beg_, p2->beg_); + std::swap(p1->end_, p2->end_); + std::swap(p1->cap_, p2->cap_); + for (__i_node** p = p1->beg_; p != p1->end_; ++p) + (*p)->__c_ = p1; + for (__i_node** p = p2->beg_; p != p2->end_; ++p) + (*p)->__c_ = p2; +} + +void +__libcpp_db::__insert_i(void* __i) +{ +#ifndef _LIBCPP_HAS_NO_THREADS + WLock _(mut()); +#endif + __insert_iterator(__i); +} + +void +__c_node::__add(__i_node* i) +{ + if (end_ == cap_) + { + size_t nc = 2*static_cast<size_t>(cap_ - beg_); + if (nc == 0) + nc = 1; + __i_node** beg = + static_cast<__i_node**>(malloc(nc * sizeof(__i_node*))); + if (beg == nullptr) + __throw_bad_alloc(); + + if (nc > 1) + memcpy(beg, beg_, nc/2*sizeof(__i_node*)); + free(beg_); + beg_ = beg; + end_ = beg_ + nc/2; + cap_ = beg_ + nc; + } + *end_++ = i; +} + +// private api + +_LIBCPP_HIDDEN +__i_node* +__libcpp_db::__insert_iterator(void* __i) +{ + if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_)) + { + size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1); + __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(__i_node*))); + if (ibeg == nullptr) + __throw_bad_alloc(); + + for (__i_node** p = __ibeg_; p != __iend_; ++p) + { + __i_node* q = *p; + while (q != nullptr) + { + size_t h = hash<void*>()(q->__i_) % nc; + __i_node* r = q->__next_; + q->__next_ = ibeg[h]; + ibeg[h] = q; + q = r; + } + } + free(__ibeg_); + __ibeg_ = ibeg; + __iend_ = __ibeg_ + nc; + } + size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); + __i_node* p = __ibeg_[hi]; + __i_node* r = __ibeg_[hi] = + static_cast<__i_node*>(malloc(sizeof(__i_node))); + if (r == nullptr) + __throw_bad_alloc(); + + ::new(r) __i_node(__i, p, nullptr); + ++__isz_; + return r; +} + +_LIBCPP_HIDDEN +__i_node* +__libcpp_db::__find_iterator(const void* __i) const +{ + __i_node* r = nullptr; + if (__ibeg_ != __iend_) + { + size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); + for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_) + { + if (nd->__i_ == __i) + { + r = nd; + break; + } + } + } + return r; +} + +_LIBCPP_HIDDEN +void +__c_node::__remove(__i_node* p) +{ + __i_node** r = find(beg_, end_, p); + _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove"); + if (--end_ != r) + memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*)); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/exception.cpp b/contrib/libs/cxxsupp/libcxx/src/exception.cpp index dbd1cf6e13..cc73288377 100644 --- a/contrib/libs/cxxsupp/libcxx/src/exception.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/exception.cpp @@ -1,34 +1,34 @@ -//===------------------------ exception.cpp -------------------------------===// -// +//===------------------------ exception.cpp -------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "exception" -#include "new" -#include "typeinfo" - +// +//===----------------------------------------------------------------------===// + +#include "exception" +#include "new" +#include "typeinfo" + #if defined(LIBCXX_BUILDING_LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI) - #include <cxxabi.h> - using namespace __cxxabiv1; - #define HAVE_DEPENDENT_EH_ABI 1 -#endif - -#if defined(_LIBCPP_ABI_MICROSOFT) -#include "support/runtime/exception_msvc.ipp" -#include "support/runtime/exception_pointer_msvc.ipp" -#elif defined(_LIBCPPABI_VERSION) -#include "support/runtime/exception_libcxxabi.ipp" -#include "support/runtime/exception_pointer_cxxabi.ipp" + #include <cxxabi.h> + using namespace __cxxabiv1; + #define HAVE_DEPENDENT_EH_ABI 1 +#endif + +#if defined(_LIBCPP_ABI_MICROSOFT) +#include "support/runtime/exception_msvc.ipp" +#include "support/runtime/exception_pointer_msvc.ipp" +#elif defined(_LIBCPPABI_VERSION) +#include "support/runtime/exception_libcxxabi.ipp" +#include "support/runtime/exception_pointer_cxxabi.ipp" #elif defined(LIBCXX_BUILDING_LIBCXXRT) -#include "support/runtime/exception_libcxxrt.ipp" -#include "support/runtime/exception_pointer_cxxabi.ipp" -#elif defined(__GLIBCXX__) -#include "support/runtime/exception_glibcxx.ipp" -#include "support/runtime/exception_pointer_glibcxx.ipp" -#else -#include "support/runtime/exception_fallback.ipp" -#include "support/runtime/exception_pointer_unimplemented.ipp" -#endif +#include "support/runtime/exception_libcxxrt.ipp" +#include "support/runtime/exception_pointer_cxxabi.ipp" +#elif defined(__GLIBCXX__) +#include "support/runtime/exception_glibcxx.ipp" +#include "support/runtime/exception_pointer_glibcxx.ipp" +#else +#include "support/runtime/exception_fallback.ipp" +#include "support/runtime/exception_pointer_unimplemented.ipp" +#endif diff --git a/contrib/libs/cxxsupp/libcxx/src/experimental/memory_resource.cpp b/contrib/libs/cxxsupp/libcxx/src/experimental/memory_resource.cpp index c795802789..5f9d3b8a4c 100644 --- a/contrib/libs/cxxsupp/libcxx/src/experimental/memory_resource.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/experimental/memory_resource.cpp @@ -1,148 +1,148 @@ -//===------------------------ memory_resource.cpp -------------------------===// -// +//===------------------------ memory_resource.cpp -------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "experimental/memory_resource" - -#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER -#include "atomic" -#elif !defined(_LIBCPP_HAS_NO_THREADS) -#include "mutex" -#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -#pragma comment(lib, "pthread") -#endif -#endif - -_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR - -// memory_resource - -//memory_resource::~memory_resource() {} - -// new_delete_resource() - -class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp - : public memory_resource -{ - void *do_allocate(size_t size, size_t align) override { -#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION - if (__is_overaligned_for_new(align)) - __throw_bad_alloc(); -#endif - return _VSTD::__libcpp_allocate(size, align); - } - - void do_deallocate(void *p, size_t n, size_t align) override { - _VSTD::__libcpp_deallocate(p, n, align); +// +//===----------------------------------------------------------------------===// + +#include "experimental/memory_resource" + +#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER +#include "atomic" +#elif !defined(_LIBCPP_HAS_NO_THREADS) +#include "mutex" +#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +#pragma comment(lib, "pthread") +#endif +#endif + +_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR + +// memory_resource + +//memory_resource::~memory_resource() {} + +// new_delete_resource() + +class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp + : public memory_resource +{ + void *do_allocate(size_t size, size_t align) override { +#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION + if (__is_overaligned_for_new(align)) + __throw_bad_alloc(); +#endif + return _VSTD::__libcpp_allocate(size, align); } - - bool do_is_equal(memory_resource const & other) const noexcept override - { return &other == this; } - -public: - ~__new_delete_memory_resource_imp() override = default; -}; - -// null_memory_resource() - -class _LIBCPP_TYPE_VIS __null_memory_resource_imp - : public memory_resource -{ -public: - ~__null_memory_resource_imp() = default; - -protected: - virtual void* do_allocate(size_t, size_t) { - __throw_bad_alloc(); - } - virtual void do_deallocate(void *, size_t, size_t) {} - virtual bool do_is_equal(memory_resource const & __other) const noexcept - { return &__other == this; } -}; - -namespace { - -union ResourceInitHelper { - struct { - __new_delete_memory_resource_imp new_delete_res; - __null_memory_resource_imp null_res; - } resources; - char dummy; - _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {} - ~ResourceInitHelper() {} -}; - -# 79 "memory_resource.cpp" 1 3 -_LIBCPP_SAFE_STATIC ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; -# 81 "memory_resource.cpp" 2 - -} // end namespace - - -memory_resource * new_delete_resource() noexcept { - return &res_init.resources.new_delete_res; -} - -memory_resource * null_memory_resource() noexcept { - return &res_init.resources.null_res; -} - -// default_memory_resource() - -static memory_resource * -__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) noexcept -{ -#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER - _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res = - ATOMIC_VAR_INIT(&res_init.resources.new_delete_res); - if (set) { - new_res = new_res ? new_res : new_delete_resource(); - // TODO: Can a weaker ordering be used? - return _VSTD::atomic_exchange_explicit( - &__res, new_res, memory_order_acq_rel); - } - else { - return _VSTD::atomic_load_explicit( - &__res, memory_order_acquire); - } -#elif !defined(_LIBCPP_HAS_NO_THREADS) - _LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res; - static mutex res_lock; - if (set) { - new_res = new_res ? new_res : new_delete_resource(); - lock_guard<mutex> guard(res_lock); - memory_resource * old_res = res; - res = new_res; - return old_res; - } else { - lock_guard<mutex> guard(res_lock); - return res; - } -#else - _LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res; - if (set) { - new_res = new_res ? new_res : new_delete_resource(); - memory_resource * old_res = res; - res = new_res; - return old_res; - } else { - return res; - } -#endif -} - -memory_resource * get_default_resource() noexcept -{ - return __default_memory_resource(); -} - -memory_resource * set_default_resource(memory_resource * __new_res) noexcept -{ - return __default_memory_resource(true, __new_res); -} - -_LIBCPP_END_NAMESPACE_LFTS_PMR + + void do_deallocate(void *p, size_t n, size_t align) override { + _VSTD::__libcpp_deallocate(p, n, align); + } + + bool do_is_equal(memory_resource const & other) const noexcept override + { return &other == this; } + +public: + ~__new_delete_memory_resource_imp() override = default; +}; + +// null_memory_resource() + +class _LIBCPP_TYPE_VIS __null_memory_resource_imp + : public memory_resource +{ +public: + ~__null_memory_resource_imp() = default; + +protected: + virtual void* do_allocate(size_t, size_t) { + __throw_bad_alloc(); + } + virtual void do_deallocate(void *, size_t, size_t) {} + virtual bool do_is_equal(memory_resource const & __other) const noexcept + { return &__other == this; } +}; + +namespace { + +union ResourceInitHelper { + struct { + __new_delete_memory_resource_imp new_delete_res; + __null_memory_resource_imp null_res; + } resources; + char dummy; + _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {} + ~ResourceInitHelper() {} +}; + +# 79 "memory_resource.cpp" 1 3 +_LIBCPP_SAFE_STATIC ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; +# 81 "memory_resource.cpp" 2 + +} // end namespace + + +memory_resource * new_delete_resource() noexcept { + return &res_init.resources.new_delete_res; +} + +memory_resource * null_memory_resource() noexcept { + return &res_init.resources.null_res; +} + +// default_memory_resource() + +static memory_resource * +__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) noexcept +{ +#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER + _LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res = + ATOMIC_VAR_INIT(&res_init.resources.new_delete_res); + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + // TODO: Can a weaker ordering be used? + return _VSTD::atomic_exchange_explicit( + &__res, new_res, memory_order_acq_rel); + } + else { + return _VSTD::atomic_load_explicit( + &__res, memory_order_acquire); + } +#elif !defined(_LIBCPP_HAS_NO_THREADS) + _LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res; + static mutex res_lock; + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + lock_guard<mutex> guard(res_lock); + memory_resource * old_res = res; + res = new_res; + return old_res; + } else { + lock_guard<mutex> guard(res_lock); + return res; + } +#else + _LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res; + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + memory_resource * old_res = res; + res = new_res; + return old_res; + } else { + return res; + } +#endif +} + +memory_resource * get_default_resource() noexcept +{ + return __default_memory_resource(); +} + +memory_resource * set_default_resource(memory_resource * __new_res) noexcept +{ + return __default_memory_resource(true, __new_res); +} + +_LIBCPP_END_NAMESPACE_LFTS_PMR diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/directory_iterator.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/directory_iterator.cpp index 764acfb256..a098dd163b 100644 --- a/contrib/libs/cxxsupp/libcxx/src/filesystem/directory_iterator.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/directory_iterator.cpp @@ -1,158 +1,158 @@ -//===------------------ directory_iterator.cpp ----------------------------===// -// +//===------------------ directory_iterator.cpp ----------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "filesystem" -#include "__config" -#if defined(_LIBCPP_WIN32API) -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX -#include <windows.h> -#else -#include <dirent.h> -#endif -#include <errno.h> - -#include "filesystem_common.h" - -_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM - -namespace detail { -namespace { - -#if !defined(_LIBCPP_WIN32API) +// +//===----------------------------------------------------------------------===// + +#include "filesystem" +#include "__config" +#if defined(_LIBCPP_WIN32API) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include <windows.h> +#else +#include <dirent.h> +#endif +#include <errno.h> + +#include "filesystem_common.h" + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +namespace detail { +namespace { + +#if !defined(_LIBCPP_WIN32API) #if defined(DT_BLK) -template <class DirEntT, class = decltype(DirEntT::d_type)> -static file_type get_file_type(DirEntT* ent, int) { - switch (ent->d_type) { - case DT_BLK: - return file_type::block; - case DT_CHR: - return file_type::character; - case DT_DIR: - return file_type::directory; - case DT_FIFO: - return file_type::fifo; - case DT_LNK: - return file_type::symlink; - case DT_REG: - return file_type::regular; - case DT_SOCK: - return file_type::socket; - // Unlike in lstat, hitting "unknown" here simply means that the underlying - // filesystem doesn't support d_type. Report is as 'none' so we correctly - // set the cache to empty. - case DT_UNKNOWN: - break; - } - return file_type::none; -} +template <class DirEntT, class = decltype(DirEntT::d_type)> +static file_type get_file_type(DirEntT* ent, int) { + switch (ent->d_type) { + case DT_BLK: + return file_type::block; + case DT_CHR: + return file_type::character; + case DT_DIR: + return file_type::directory; + case DT_FIFO: + return file_type::fifo; + case DT_LNK: + return file_type::symlink; + case DT_REG: + return file_type::regular; + case DT_SOCK: + return file_type::socket; + // Unlike in lstat, hitting "unknown" here simply means that the underlying + // filesystem doesn't support d_type. Report is as 'none' so we correctly + // set the cache to empty. + case DT_UNKNOWN: + break; + } + return file_type::none; +} #endif // defined(DT_BLK) - -template <class DirEntT> + +template <class DirEntT> static file_type get_file_type(DirEntT*, long) { - return file_type::none; -} - -static pair<string_view, file_type> posix_readdir(DIR* dir_stream, - error_code& ec) { - struct dirent* dir_entry_ptr = nullptr; - errno = 0; // zero errno in order to detect errors - ec.clear(); - if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) { - if (errno) - ec = capture_errno(); - return {}; - } else { - return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)}; - } -} -#else -// defined(_LIBCPP_WIN32API) - -static file_type get_file_type(const WIN32_FIND_DATAW& data) { - if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && - data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) - return file_type::symlink; - if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - return file_type::directory; - return file_type::regular; -} -static uintmax_t get_file_size(const WIN32_FIND_DATAW& data) { - return (static_cast<uint64_t>(data.nFileSizeHigh) << 32) + data.nFileSizeLow; -} -static file_time_type get_write_time(const WIN32_FIND_DATAW& data) { - ULARGE_INTEGER tmp; - const FILETIME& time = data.ftLastWriteTime; - tmp.u.LowPart = time.dwLowDateTime; - tmp.u.HighPart = time.dwHighDateTime; - return file_time_type(file_time_type::duration(tmp.QuadPart)); -} - -#endif - -} // namespace -} // namespace detail - -using detail::ErrorHandler; - -#if defined(_LIBCPP_WIN32API) -class __dir_stream { -public: - __dir_stream() = delete; - __dir_stream& operator=(const __dir_stream&) = delete; - - __dir_stream(__dir_stream&& __ds) noexcept : __stream_(__ds.__stream_), - __root_(move(__ds.__root_)), - __entry_(move(__ds.__entry_)) { - __ds.__stream_ = INVALID_HANDLE_VALUE; - } - - __dir_stream(const path& root, directory_options opts, error_code& ec) - : __stream_(INVALID_HANDLE_VALUE), __root_(root) { - if (root.native().empty()) { - ec = make_error_code(errc::no_such_file_or_directory); - return; - } - __stream_ = ::FindFirstFileW((root / "*").c_str(), &__data_); - if (__stream_ == INVALID_HANDLE_VALUE) { - ec = detail::make_windows_error(GetLastError()); - const bool ignore_permission_denied = - bool(opts & directory_options::skip_permission_denied); - if (ignore_permission_denied && - ec.value() == static_cast<int>(errc::permission_denied)) - ec.clear(); - return; - } - if (!assign()) - advance(ec); - } - - ~__dir_stream() noexcept { - if (__stream_ == INVALID_HANDLE_VALUE) - return; - close(); - } - - bool good() const noexcept { return __stream_ != INVALID_HANDLE_VALUE; } - - bool advance(error_code& ec) { - while (::FindNextFileW(__stream_, &__data_)) { - if (assign()) - return true; - } - close(); - return false; - } - - bool assign() { - if (!wcscmp(__data_.cFileName, L".") || !wcscmp(__data_.cFileName, L"..")) - return false; + return file_type::none; +} + +static pair<string_view, file_type> posix_readdir(DIR* dir_stream, + error_code& ec) { + struct dirent* dir_entry_ptr = nullptr; + errno = 0; // zero errno in order to detect errors + ec.clear(); + if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) { + if (errno) + ec = capture_errno(); + return {}; + } else { + return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)}; + } +} +#else +// defined(_LIBCPP_WIN32API) + +static file_type get_file_type(const WIN32_FIND_DATAW& data) { + if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && + data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) + return file_type::symlink; + if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + return file_type::directory; + return file_type::regular; +} +static uintmax_t get_file_size(const WIN32_FIND_DATAW& data) { + return (static_cast<uint64_t>(data.nFileSizeHigh) << 32) + data.nFileSizeLow; +} +static file_time_type get_write_time(const WIN32_FIND_DATAW& data) { + ULARGE_INTEGER tmp; + const FILETIME& time = data.ftLastWriteTime; + tmp.u.LowPart = time.dwLowDateTime; + tmp.u.HighPart = time.dwHighDateTime; + return file_time_type(file_time_type::duration(tmp.QuadPart)); +} + +#endif + +} // namespace +} // namespace detail + +using detail::ErrorHandler; + +#if defined(_LIBCPP_WIN32API) +class __dir_stream { +public: + __dir_stream() = delete; + __dir_stream& operator=(const __dir_stream&) = delete; + + __dir_stream(__dir_stream&& __ds) noexcept : __stream_(__ds.__stream_), + __root_(move(__ds.__root_)), + __entry_(move(__ds.__entry_)) { + __ds.__stream_ = INVALID_HANDLE_VALUE; + } + + __dir_stream(const path& root, directory_options opts, error_code& ec) + : __stream_(INVALID_HANDLE_VALUE), __root_(root) { + if (root.native().empty()) { + ec = make_error_code(errc::no_such_file_or_directory); + return; + } + __stream_ = ::FindFirstFileW((root / "*").c_str(), &__data_); + if (__stream_ == INVALID_HANDLE_VALUE) { + ec = detail::make_windows_error(GetLastError()); + const bool ignore_permission_denied = + bool(opts & directory_options::skip_permission_denied); + if (ignore_permission_denied && + ec.value() == static_cast<int>(errc::permission_denied)) + ec.clear(); + return; + } + if (!assign()) + advance(ec); + } + + ~__dir_stream() noexcept { + if (__stream_ == INVALID_HANDLE_VALUE) + return; + close(); + } + + bool good() const noexcept { return __stream_ != INVALID_HANDLE_VALUE; } + + bool advance(error_code& ec) { + while (::FindNextFileW(__stream_, &__data_)) { + if (assign()) + return true; + } + close(); + return false; + } + + bool assign() { + if (!wcscmp(__data_.cFileName, L".") || !wcscmp(__data_.cFileName, L"..")) + return false; // FIXME: Cache more of this //directory_entry::__cached_data cdata; //cdata.__type_ = get_file_type(__data_); @@ -160,256 +160,256 @@ public: //cdata.__write_time_ = get_write_time(__data_); __entry_.__assign_iter_entry( __root_ / __data_.cFileName, - directory_entry::__create_iter_result(detail::get_file_type(__data_))); + directory_entry::__create_iter_result(detail::get_file_type(__data_))); return true; } - -private: - error_code close() noexcept { - error_code ec; - if (!::FindClose(__stream_)) - ec = detail::make_windows_error(GetLastError()); - __stream_ = INVALID_HANDLE_VALUE; - return ec; - } - - HANDLE __stream_{INVALID_HANDLE_VALUE}; - WIN32_FIND_DATAW __data_; - -public: - path __root_; - directory_entry __entry_; -}; -#else -class __dir_stream { -public: - __dir_stream() = delete; - __dir_stream& operator=(const __dir_stream&) = delete; - - __dir_stream(__dir_stream&& other) noexcept : __stream_(other.__stream_), - __root_(move(other.__root_)), - __entry_(move(other.__entry_)) { - other.__stream_ = nullptr; - } - - __dir_stream(const path& root, directory_options opts, error_code& ec) - : __stream_(nullptr), __root_(root) { - if ((__stream_ = ::opendir(root.c_str())) == nullptr) { - ec = detail::capture_errno(); - const bool allow_eacess = - bool(opts & directory_options::skip_permission_denied); - if (allow_eacess && ec.value() == EACCES) - ec.clear(); - return; - } - advance(ec); - } - - ~__dir_stream() noexcept { - if (__stream_) - close(); - } - - bool good() const noexcept { return __stream_ != nullptr; } - - bool advance(error_code& ec) { - while (true) { - auto str_type_pair = detail::posix_readdir(__stream_, ec); - auto& str = str_type_pair.first; - if (str == "." || str == "..") { - continue; - } else if (ec || str.empty()) { - close(); - return false; - } else { - __entry_.__assign_iter_entry( - __root_ / str, - directory_entry::__create_iter_result(str_type_pair.second)); - return true; - } - } - } - -private: - error_code close() noexcept { - error_code m_ec; - if (::closedir(__stream_) == -1) - m_ec = detail::capture_errno(); - __stream_ = nullptr; - return m_ec; - } - - DIR* __stream_{nullptr}; - -public: - path __root_; - directory_entry __entry_; -}; -#endif - -// directory_iterator - -directory_iterator::directory_iterator(const path& p, error_code* ec, - directory_options opts) { - ErrorHandler<void> err("directory_iterator::directory_iterator(...)", ec, &p); - - error_code m_ec; - __imp_ = make_shared<__dir_stream>(p, opts, m_ec); - if (ec) - *ec = m_ec; - if (!__imp_->good()) { - __imp_.reset(); - if (m_ec) - err.report(m_ec); - } -} - -directory_iterator& directory_iterator::__increment(error_code* ec) { - _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator"); - ErrorHandler<void> err("directory_iterator::operator++()", ec); - - error_code m_ec; - if (!__imp_->advance(m_ec)) { - path root = move(__imp_->__root_); - __imp_.reset(); - if (m_ec) - err.report(m_ec, "at root " PATH_CSTR_FMT, root.c_str()); - } - return *this; -} - -directory_entry const& directory_iterator::__dereference() const { - _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator"); - return __imp_->__entry_; -} - -// recursive_directory_iterator - -struct recursive_directory_iterator::__shared_imp { - stack<__dir_stream> __stack_; - directory_options __options_; -}; - -recursive_directory_iterator::recursive_directory_iterator( - const path& p, directory_options opt, error_code* ec) - : __imp_(nullptr), __rec_(true) { - ErrorHandler<void> err("recursive_directory_iterator", ec, &p); - - error_code m_ec; - __dir_stream new_s(p, opt, m_ec); - if (m_ec) - err.report(m_ec); - if (m_ec || !new_s.good()) - return; - - __imp_ = make_shared<__shared_imp>(); - __imp_->__options_ = opt; - __imp_->__stack_.push(move(new_s)); -} - -void recursive_directory_iterator::__pop(error_code* ec) { - _LIBCPP_ASSERT(__imp_, "Popping the end iterator"); - if (ec) - ec->clear(); - __imp_->__stack_.pop(); - if (__imp_->__stack_.size() == 0) - __imp_.reset(); - else - __advance(ec); -} - -directory_options recursive_directory_iterator::options() const { - return __imp_->__options_; -} - -int recursive_directory_iterator::depth() const { - return __imp_->__stack_.size() - 1; -} - -const directory_entry& recursive_directory_iterator::__dereference() const { - return __imp_->__stack_.top().__entry_; -} - -recursive_directory_iterator& -recursive_directory_iterator::__increment(error_code* ec) { - if (ec) - ec->clear(); - if (recursion_pending()) { - if (__try_recursion(ec) || (ec && *ec)) - return *this; - } - __rec_ = true; - __advance(ec); - return *this; -} - -void recursive_directory_iterator::__advance(error_code* ec) { - ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec); - - const directory_iterator end_it; - auto& stack = __imp_->__stack_; - error_code m_ec; - while (stack.size() > 0) { - if (stack.top().advance(m_ec)) - return; - if (m_ec) - break; - stack.pop(); - } - - if (m_ec) { - path root = move(stack.top().__root_); - __imp_.reset(); - err.report(m_ec, "at root " PATH_CSTR_FMT, root.c_str()); - } else { - __imp_.reset(); - } -} - -bool recursive_directory_iterator::__try_recursion(error_code* ec) { - ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec); - - bool rec_sym = bool(options() & directory_options::follow_directory_symlink); - - auto& curr_it = __imp_->__stack_.top(); - - bool skip_rec = false; - error_code m_ec; - if (!rec_sym) { - file_status st(curr_it.__entry_.__get_sym_ft(&m_ec)); - if (m_ec && status_known(st)) - m_ec.clear(); - if (m_ec || is_symlink(st) || !is_directory(st)) - skip_rec = true; - } else { - file_status st(curr_it.__entry_.__get_ft(&m_ec)); - if (m_ec && status_known(st)) - m_ec.clear(); - if (m_ec || !is_directory(st)) - skip_rec = true; - } - - if (!skip_rec) { - __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec); - if (new_it.good()) { - __imp_->__stack_.push(move(new_it)); - return true; - } - } - if (m_ec) { - const bool allow_eacess = - bool(__imp_->__options_ & directory_options::skip_permission_denied); - if (m_ec.value() == EACCES && allow_eacess) { - if (ec) - ec->clear(); - } else { - path at_ent = move(curr_it.__entry_.__p_); - __imp_.reset(); - err.report(m_ec, "attempting recursion into " PATH_CSTR_FMT, - at_ent.c_str()); - } - } - return false; -} - -_LIBCPP_END_NAMESPACE_FILESYSTEM + +private: + error_code close() noexcept { + error_code ec; + if (!::FindClose(__stream_)) + ec = detail::make_windows_error(GetLastError()); + __stream_ = INVALID_HANDLE_VALUE; + return ec; + } + + HANDLE __stream_{INVALID_HANDLE_VALUE}; + WIN32_FIND_DATAW __data_; + +public: + path __root_; + directory_entry __entry_; +}; +#else +class __dir_stream { +public: + __dir_stream() = delete; + __dir_stream& operator=(const __dir_stream&) = delete; + + __dir_stream(__dir_stream&& other) noexcept : __stream_(other.__stream_), + __root_(move(other.__root_)), + __entry_(move(other.__entry_)) { + other.__stream_ = nullptr; + } + + __dir_stream(const path& root, directory_options opts, error_code& ec) + : __stream_(nullptr), __root_(root) { + if ((__stream_ = ::opendir(root.c_str())) == nullptr) { + ec = detail::capture_errno(); + const bool allow_eacess = + bool(opts & directory_options::skip_permission_denied); + if (allow_eacess && ec.value() == EACCES) + ec.clear(); + return; + } + advance(ec); + } + + ~__dir_stream() noexcept { + if (__stream_) + close(); + } + + bool good() const noexcept { return __stream_ != nullptr; } + + bool advance(error_code& ec) { + while (true) { + auto str_type_pair = detail::posix_readdir(__stream_, ec); + auto& str = str_type_pair.first; + if (str == "." || str == "..") { + continue; + } else if (ec || str.empty()) { + close(); + return false; + } else { + __entry_.__assign_iter_entry( + __root_ / str, + directory_entry::__create_iter_result(str_type_pair.second)); + return true; + } + } + } + +private: + error_code close() noexcept { + error_code m_ec; + if (::closedir(__stream_) == -1) + m_ec = detail::capture_errno(); + __stream_ = nullptr; + return m_ec; + } + + DIR* __stream_{nullptr}; + +public: + path __root_; + directory_entry __entry_; +}; +#endif + +// directory_iterator + +directory_iterator::directory_iterator(const path& p, error_code* ec, + directory_options opts) { + ErrorHandler<void> err("directory_iterator::directory_iterator(...)", ec, &p); + + error_code m_ec; + __imp_ = make_shared<__dir_stream>(p, opts, m_ec); + if (ec) + *ec = m_ec; + if (!__imp_->good()) { + __imp_.reset(); + if (m_ec) + err.report(m_ec); + } +} + +directory_iterator& directory_iterator::__increment(error_code* ec) { + _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator"); + ErrorHandler<void> err("directory_iterator::operator++()", ec); + + error_code m_ec; + if (!__imp_->advance(m_ec)) { + path root = move(__imp_->__root_); + __imp_.reset(); + if (m_ec) + err.report(m_ec, "at root " PATH_CSTR_FMT, root.c_str()); + } + return *this; +} + +directory_entry const& directory_iterator::__dereference() const { + _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator"); + return __imp_->__entry_; +} + +// recursive_directory_iterator + +struct recursive_directory_iterator::__shared_imp { + stack<__dir_stream> __stack_; + directory_options __options_; +}; + +recursive_directory_iterator::recursive_directory_iterator( + const path& p, directory_options opt, error_code* ec) + : __imp_(nullptr), __rec_(true) { + ErrorHandler<void> err("recursive_directory_iterator", ec, &p); + + error_code m_ec; + __dir_stream new_s(p, opt, m_ec); + if (m_ec) + err.report(m_ec); + if (m_ec || !new_s.good()) + return; + + __imp_ = make_shared<__shared_imp>(); + __imp_->__options_ = opt; + __imp_->__stack_.push(move(new_s)); +} + +void recursive_directory_iterator::__pop(error_code* ec) { + _LIBCPP_ASSERT(__imp_, "Popping the end iterator"); + if (ec) + ec->clear(); + __imp_->__stack_.pop(); + if (__imp_->__stack_.size() == 0) + __imp_.reset(); + else + __advance(ec); +} + +directory_options recursive_directory_iterator::options() const { + return __imp_->__options_; +} + +int recursive_directory_iterator::depth() const { + return __imp_->__stack_.size() - 1; +} + +const directory_entry& recursive_directory_iterator::__dereference() const { + return __imp_->__stack_.top().__entry_; +} + +recursive_directory_iterator& +recursive_directory_iterator::__increment(error_code* ec) { + if (ec) + ec->clear(); + if (recursion_pending()) { + if (__try_recursion(ec) || (ec && *ec)) + return *this; + } + __rec_ = true; + __advance(ec); + return *this; +} + +void recursive_directory_iterator::__advance(error_code* ec) { + ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec); + + const directory_iterator end_it; + auto& stack = __imp_->__stack_; + error_code m_ec; + while (stack.size() > 0) { + if (stack.top().advance(m_ec)) + return; + if (m_ec) + break; + stack.pop(); + } + + if (m_ec) { + path root = move(stack.top().__root_); + __imp_.reset(); + err.report(m_ec, "at root " PATH_CSTR_FMT, root.c_str()); + } else { + __imp_.reset(); + } +} + +bool recursive_directory_iterator::__try_recursion(error_code* ec) { + ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec); + + bool rec_sym = bool(options() & directory_options::follow_directory_symlink); + + auto& curr_it = __imp_->__stack_.top(); + + bool skip_rec = false; + error_code m_ec; + if (!rec_sym) { + file_status st(curr_it.__entry_.__get_sym_ft(&m_ec)); + if (m_ec && status_known(st)) + m_ec.clear(); + if (m_ec || is_symlink(st) || !is_directory(st)) + skip_rec = true; + } else { + file_status st(curr_it.__entry_.__get_ft(&m_ec)); + if (m_ec && status_known(st)) + m_ec.clear(); + if (m_ec || !is_directory(st)) + skip_rec = true; + } + + if (!skip_rec) { + __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec); + if (new_it.good()) { + __imp_->__stack_.push(move(new_it)); + return true; + } + } + if (m_ec) { + const bool allow_eacess = + bool(__imp_->__options_ & directory_options::skip_permission_denied); + if (m_ec.value() == EACCES && allow_eacess) { + if (ec) + ec->clear(); + } else { + path at_ent = move(curr_it.__entry_.__p_); + __imp_.reset(); + err.report(m_ec, "attempting recursion into " PATH_CSTR_FMT, + at_ent.c_str()); + } + } + return false; +} + +_LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_common.h b/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_common.h index 55bba1a738..a5f5749783 100644 --- a/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_common.h +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/filesystem_common.h @@ -1,535 +1,535 @@ -//===----------------------------------------------------------------------===//// -// +//===----------------------------------------------------------------------===//// +// // 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 FILESYSTEM_COMMON_H -#define FILESYSTEM_COMMON_H - -#include "__config" -#include "array" -#include "chrono" -#include "climits" -#include "cstdarg" -#include "cstdlib" -#include "ctime" -#include "filesystem" - -#if !defined(_LIBCPP_WIN32API) +// +//===----------------------------------------------------------------------===//// + +#ifndef FILESYSTEM_COMMON_H +#define FILESYSTEM_COMMON_H + +#include "__config" +#include "array" +#include "chrono" +#include "climits" +#include "cstdarg" +#include "cstdlib" +#include "ctime" +#include "filesystem" + +#if !defined(_LIBCPP_WIN32API) # include <unistd.h> # include <sys/stat.h> # include <sys/statvfs.h> # include <sys/time.h> // for ::utimes as used in __last_write_time # include <fcntl.h> /* values for fchmodat */ -#endif - -#include "../include/apple_availability.h" - -#if !defined(__APPLE__) -// We can use the presence of UTIME_OMIT to detect platforms that provide -// utimensat. -#if defined(UTIME_OMIT) -#define _LIBCPP_USE_UTIMENSAT -#endif -#endif - -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" -#endif - -#if defined(_LIBCPP_WIN32API) -#define PS(x) (L##x) -#define PATH_CSTR_FMT "\"%ls\"" -#else -#define PS(x) (x) -#define PATH_CSTR_FMT "\"%s\"" -#endif - -_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM - -namespace detail { - -#if defined(_LIBCPP_WIN32API) -// Non anonymous, to allow access from two translation units. -errc __win_err_to_errc(int err); -#endif - -namespace { - -static _LIBCPP_FORMAT_PRINTF(1, 0) string -format_string_impl(const char* msg, va_list ap) { - array<char, 256> buf; - - va_list apcopy; - va_copy(apcopy, ap); - int ret = ::vsnprintf(buf.data(), buf.size(), msg, apcopy); - va_end(apcopy); - - string result; - if (static_cast<size_t>(ret) < buf.size()) { - result.assign(buf.data(), static_cast<size_t>(ret)); - } else { +#endif + +#include "../include/apple_availability.h" + +#if !defined(__APPLE__) +// We can use the presence of UTIME_OMIT to detect platforms that provide +// utimensat. +#if defined(UTIME_OMIT) +#define _LIBCPP_USE_UTIMENSAT +#endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#if defined(_LIBCPP_WIN32API) +#define PS(x) (L##x) +#define PATH_CSTR_FMT "\"%ls\"" +#else +#define PS(x) (x) +#define PATH_CSTR_FMT "\"%s\"" +#endif + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +namespace detail { + +#if defined(_LIBCPP_WIN32API) +// Non anonymous, to allow access from two translation units. +errc __win_err_to_errc(int err); +#endif + +namespace { + +static _LIBCPP_FORMAT_PRINTF(1, 0) string +format_string_impl(const char* msg, va_list ap) { + array<char, 256> buf; + + va_list apcopy; + va_copy(apcopy, ap); + int ret = ::vsnprintf(buf.data(), buf.size(), msg, apcopy); + va_end(apcopy); + + string result; + if (static_cast<size_t>(ret) < buf.size()) { + result.assign(buf.data(), static_cast<size_t>(ret)); + } else { // we did not provide a long enough buffer on our first attempt. The // return value is the number of bytes (excluding the null byte) that are // needed for formatting. - size_t size_with_null = static_cast<size_t>(ret) + 1; + size_t size_with_null = static_cast<size_t>(ret) + 1; result.__resize_default_init(size_with_null - 1); - ret = ::vsnprintf(&result[0], size_with_null, msg, ap); + ret = ::vsnprintf(&result[0], size_with_null, msg, ap); _LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO"); -} +} return result; -} - -static _LIBCPP_FORMAT_PRINTF(1, 2) string -format_string(const char* msg, ...) { - string ret; - va_list ap; - va_start(ap, msg); -#ifndef _LIBCPP_NO_EXCEPTIONS - try { -#endif // _LIBCPP_NO_EXCEPTIONS - ret = format_string_impl(msg, ap); -#ifndef _LIBCPP_NO_EXCEPTIONS - } catch (...) { - va_end(ap); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS - va_end(ap); - return ret; -} - -error_code capture_errno() { - _LIBCPP_ASSERT(errno, "Expected errno to be non-zero"); - return error_code(errno, generic_category()); -} - -#if defined(_LIBCPP_WIN32API) -error_code make_windows_error(int err) { - return make_error_code(__win_err_to_errc(err)); -} -#endif - -template <class T> -T error_value(); -template <> -_LIBCPP_CONSTEXPR_AFTER_CXX11 void error_value<void>() {} -template <> -bool error_value<bool>() { - return false; -} -#if __SIZEOF_SIZE_T__ != __SIZEOF_LONG_LONG__ -template <> -size_t error_value<size_t>() { - return size_t(-1); -} -#endif -template <> -uintmax_t error_value<uintmax_t>() { - return uintmax_t(-1); -} -template <> -_LIBCPP_CONSTEXPR_AFTER_CXX11 file_time_type error_value<file_time_type>() { - return file_time_type::min(); -} -template <> -path error_value<path>() { - return {}; -} - -template <class T> -struct ErrorHandler { - const char* func_name_; - error_code* ec_ = nullptr; - const path* p1_ = nullptr; - const path* p2_ = nullptr; - - ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr, - const path* p2 = nullptr) - : func_name_(fname), ec_(ec), p1_(p1), p2_(p2) { - if (ec_) - ec_->clear(); - } - - T report(const error_code& ec) const { - if (ec_) { - *ec_ = ec; - return error_value<T>(); - } - string what = string("in ") + func_name_; - switch (bool(p1_) + bool(p2_)) { - case 0: - __throw_filesystem_error(what, ec); - case 1: - __throw_filesystem_error(what, *p1_, ec); - case 2: - __throw_filesystem_error(what, *p1_, *p2_, ec); - } - _LIBCPP_UNREACHABLE(); - } - - _LIBCPP_FORMAT_PRINTF(3, 0) - void report_impl(const error_code& ec, const char* msg, va_list ap) const { - if (ec_) { - *ec_ = ec; - return; - } - string what = - string("in ") + func_name_ + ": " + format_string_impl(msg, ap); - switch (bool(p1_) + bool(p2_)) { - case 0: - __throw_filesystem_error(what, ec); - case 1: - __throw_filesystem_error(what, *p1_, ec); - case 2: - __throw_filesystem_error(what, *p1_, *p2_, ec); - } - _LIBCPP_UNREACHABLE(); - } - - _LIBCPP_FORMAT_PRINTF(3, 4) - T report(const error_code& ec, const char* msg, ...) const { - va_list ap; - va_start(ap, msg); -#ifndef _LIBCPP_NO_EXCEPTIONS - try { -#endif // _LIBCPP_NO_EXCEPTIONS - report_impl(ec, msg, ap); -#ifndef _LIBCPP_NO_EXCEPTIONS - } catch (...) { - va_end(ap); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS - va_end(ap); - return error_value<T>(); - } - - T report(errc const& err) const { - return report(make_error_code(err)); - } - - _LIBCPP_FORMAT_PRINTF(3, 4) - T report(errc const& err, const char* msg, ...) const { - va_list ap; - va_start(ap, msg); -#ifndef _LIBCPP_NO_EXCEPTIONS - try { -#endif // _LIBCPP_NO_EXCEPTIONS - report_impl(make_error_code(err), msg, ap); -#ifndef _LIBCPP_NO_EXCEPTIONS - } catch (...) { - va_end(ap); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS - va_end(ap); - return error_value<T>(); - } - -private: - ErrorHandler(ErrorHandler const&) = delete; - ErrorHandler& operator=(ErrorHandler const&) = delete; -}; - -using chrono::duration; -using chrono::duration_cast; - -#if defined(_LIBCPP_WIN32API) -// Various C runtime versions (UCRT, or the legacy msvcrt.dll used by -// some mingw toolchains) provide different stat function implementations, -// with a number of limitations with respect to what we want from the -// stat function. Instead provide our own (in the anonymous detail namespace -// in posix_compat.h) which does exactly what we want, along with our own -// stat structure and flag macros. - -struct TimeSpec { - int64_t tv_sec; - int64_t tv_nsec; -}; -struct StatT { - unsigned st_mode; - TimeSpec st_atim; - TimeSpec st_mtim; - uint64_t st_dev; // FILE_ID_INFO::VolumeSerialNumber - struct FileIdStruct { - unsigned char id[16]; // FILE_ID_INFO::FileId - bool operator==(const FileIdStruct &other) const { - for (int i = 0; i < 16; i++) - if (id[i] != other.id[i]) - return false; - return true; - } - } st_ino; - uint32_t st_nlink; - uintmax_t st_size; -}; - -#else -using TimeSpec = struct timespec; -using TimeVal = struct timeval; -using StatT = struct stat; -#endif - -template <class FileTimeT, class TimeT, - bool IsFloat = is_floating_point<typename FileTimeT::rep>::value> -struct time_util_base { - using rep = typename FileTimeT::rep; - using fs_duration = typename FileTimeT::duration; - using fs_seconds = duration<rep>; - using fs_nanoseconds = duration<rep, nano>; - using fs_microseconds = duration<rep, micro>; - - static constexpr rep max_seconds = - duration_cast<fs_seconds>(FileTimeT::duration::max()).count(); - - static constexpr rep max_nsec = - duration_cast<fs_nanoseconds>(FileTimeT::duration::max() - - fs_seconds(max_seconds)) - .count(); - - static constexpr rep min_seconds = - duration_cast<fs_seconds>(FileTimeT::duration::min()).count(); - - static constexpr rep min_nsec_timespec = - duration_cast<fs_nanoseconds>( - (FileTimeT::duration::min() - fs_seconds(min_seconds)) + - fs_seconds(1)) - .count(); - -private: - static _LIBCPP_CONSTEXPR_AFTER_CXX11 fs_duration get_min_nsecs() { - return duration_cast<fs_duration>( - fs_nanoseconds(min_nsec_timespec) - - duration_cast<fs_nanoseconds>(fs_seconds(1))); - } - // Static assert that these values properly round trip. - static_assert(fs_seconds(min_seconds) + get_min_nsecs() == - FileTimeT::duration::min(), - "value doesn't roundtrip"); - - static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool check_range() { - // This kinda sucks, but it's what happens when we don't have __int128_t. - if (sizeof(TimeT) == sizeof(rep)) { - typedef duration<long long, ratio<3600 * 24 * 365> > Years; - return duration_cast<Years>(fs_seconds(max_seconds)) > Years(250) && - duration_cast<Years>(fs_seconds(min_seconds)) < Years(-250); - } - return max_seconds >= numeric_limits<TimeT>::max() && - min_seconds <= numeric_limits<TimeT>::min(); - } - static_assert(check_range(), "the representable range is unacceptable small"); -}; - -template <class FileTimeT, class TimeT> -struct time_util_base<FileTimeT, TimeT, true> { - using rep = typename FileTimeT::rep; - using fs_duration = typename FileTimeT::duration; - using fs_seconds = duration<rep>; - using fs_nanoseconds = duration<rep, nano>; - using fs_microseconds = duration<rep, micro>; - - static const rep max_seconds; - static const rep max_nsec; - static const rep min_seconds; - static const rep min_nsec_timespec; -}; - -template <class FileTimeT, class TimeT> -const typename FileTimeT::rep - time_util_base<FileTimeT, TimeT, true>::max_seconds = - duration_cast<fs_seconds>(FileTimeT::duration::max()).count(); - -template <class FileTimeT, class TimeT> -const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_nsec = - duration_cast<fs_nanoseconds>(FileTimeT::duration::max() - - fs_seconds(max_seconds)) - .count(); - -template <class FileTimeT, class TimeT> -const typename FileTimeT::rep - time_util_base<FileTimeT, TimeT, true>::min_seconds = - duration_cast<fs_seconds>(FileTimeT::duration::min()).count(); - -template <class FileTimeT, class TimeT> -const typename FileTimeT::rep - time_util_base<FileTimeT, TimeT, true>::min_nsec_timespec = - duration_cast<fs_nanoseconds>((FileTimeT::duration::min() - - fs_seconds(min_seconds)) + - fs_seconds(1)) - .count(); - -template <class FileTimeT, class TimeT, class TimeSpecT> -struct time_util : time_util_base<FileTimeT, TimeT> { - using Base = time_util_base<FileTimeT, TimeT>; - using Base::max_nsec; - using Base::max_seconds; - using Base::min_nsec_timespec; - using Base::min_seconds; - - using typename Base::fs_duration; - using typename Base::fs_microseconds; - using typename Base::fs_nanoseconds; - using typename Base::fs_seconds; - -public: - template <class CType, class ChronoType> - static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool checked_set(CType* out, - ChronoType time) { - using Lim = numeric_limits<CType>; - if (time > Lim::max() || time < Lim::min()) - return false; - *out = static_cast<CType>(time); - return true; - } - - static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) { - if (tm.tv_sec >= 0) { - return tm.tv_sec < max_seconds || - (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec); - } else if (tm.tv_sec == (min_seconds - 1)) { - return tm.tv_nsec >= min_nsec_timespec; - } else { - return tm.tv_sec >= min_seconds; - } - } - - static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) { - auto secs = duration_cast<fs_seconds>(tm.time_since_epoch()); - auto nsecs = duration_cast<fs_nanoseconds>(tm.time_since_epoch() - secs); - if (nsecs.count() < 0) { - secs = secs + fs_seconds(1); - nsecs = nsecs + fs_seconds(1); - } - using TLim = numeric_limits<TimeT>; - if (secs.count() >= 0) - return secs.count() <= TLim::max(); - return secs.count() >= TLim::min(); - } - - static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT - convert_from_timespec(TimeSpecT tm) { - if (tm.tv_sec >= 0 || tm.tv_nsec == 0) { - return FileTimeT(fs_seconds(tm.tv_sec) + - duration_cast<fs_duration>(fs_nanoseconds(tm.tv_nsec))); - } else { // tm.tv_sec < 0 - auto adj_subsec = duration_cast<fs_duration>(fs_seconds(1) - - fs_nanoseconds(tm.tv_nsec)); - auto Dur = fs_seconds(tm.tv_sec + 1) - adj_subsec; - return FileTimeT(Dur); - } - } - - template <class SubSecT> - static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool - set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) { - auto dur = tp.time_since_epoch(); - auto sec_dur = duration_cast<fs_seconds>(dur); - auto subsec_dur = duration_cast<fs_nanoseconds>(dur - sec_dur); - // The tv_nsec and tv_usec fields must not be negative so adjust accordingly - if (subsec_dur.count() < 0) { - if (sec_dur.count() > min_seconds) { - sec_dur = sec_dur - fs_seconds(1); - subsec_dur = subsec_dur + fs_seconds(1); - } else { - subsec_dur = fs_nanoseconds::zero(); - } - } - return checked_set(sec_out, sec_dur.count()) && - checked_set(subsec_out, subsec_dur.count()); - } - static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool convert_to_timespec(TimeSpecT& dest, - FileTimeT tp) { - if (!is_representable(tp)) - return false; - return set_times_checked(&dest.tv_sec, &dest.tv_nsec, tp); - } -}; - -#if defined(_LIBCPP_WIN32API) -using fs_time = time_util<file_time_type, int64_t, TimeSpec>; -#else -using fs_time = time_util<file_time_type, time_t, TimeSpec>; -#endif - -#if defined(__APPLE__) -inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; } -inline TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; } -#elif defined(__MVS__) -inline TimeSpec extract_mtime(StatT const& st) { - TimeSpec TS = {st.st_mtime, 0}; - return TS; -} -inline TimeSpec extract_atime(StatT const& st) { - TimeSpec TS = {st.st_atime, 0}; - return TS; -} -#elif defined(_AIX) -inline TimeSpec extract_mtime(StatT const& st) { - TimeSpec TS = {st.st_mtime, st.st_mtime_n}; - return TS; -} -inline TimeSpec extract_atime(StatT const& st) { - TimeSpec TS = {st.st_atime, st.st_atime_n}; - return TS; -} -#else -inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } -inline TimeSpec extract_atime(StatT const& st) { return st.st_atim; } -#endif - -#if !defined(_LIBCPP_WIN32API) -inline TimeVal make_timeval(TimeSpec const& ts) { - using namespace chrono; - auto Convert = [](long nsec) { - using int_type = decltype(std::declval<TimeVal>().tv_usec); - auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count(); - return static_cast<int_type>(dur); - }; - TimeVal TV = {}; - TV.tv_sec = ts.tv_sec; - TV.tv_usec = Convert(ts.tv_nsec); - return TV; -} - -inline bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS, - error_code& ec) { - TimeVal ConvertedTS[2] = {make_timeval(TS[0]), make_timeval(TS[1])}; - if (::utimes(p.c_str(), ConvertedTS) == -1) { - ec = capture_errno(); - return true; - } - return false; -} - -#if defined(_LIBCPP_USE_UTIMENSAT) -bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS, - error_code& ec) { - if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) { - ec = capture_errno(); - return true; - } - return false; -} -#endif - -bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS, - error_code& ec) { -#if !defined(_LIBCPP_USE_UTIMENSAT) - return posix_utimes(p, TS, ec); -#else - return posix_utimensat(p, TS, ec); -#endif -} -#endif /* !_LIBCPP_WIN32API */ - -} // namespace -} // end namespace detail - -_LIBCPP_END_NAMESPACE_FILESYSTEM - -#endif // FILESYSTEM_COMMON_H +} + +static _LIBCPP_FORMAT_PRINTF(1, 2) string +format_string(const char* msg, ...) { + string ret; + va_list ap; + va_start(ap, msg); +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif // _LIBCPP_NO_EXCEPTIONS + ret = format_string_impl(msg, ap); +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + va_end(ap); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + va_end(ap); + return ret; +} + +error_code capture_errno() { + _LIBCPP_ASSERT(errno, "Expected errno to be non-zero"); + return error_code(errno, generic_category()); +} + +#if defined(_LIBCPP_WIN32API) +error_code make_windows_error(int err) { + return make_error_code(__win_err_to_errc(err)); +} +#endif + +template <class T> +T error_value(); +template <> +_LIBCPP_CONSTEXPR_AFTER_CXX11 void error_value<void>() {} +template <> +bool error_value<bool>() { + return false; +} +#if __SIZEOF_SIZE_T__ != __SIZEOF_LONG_LONG__ +template <> +size_t error_value<size_t>() { + return size_t(-1); +} +#endif +template <> +uintmax_t error_value<uintmax_t>() { + return uintmax_t(-1); +} +template <> +_LIBCPP_CONSTEXPR_AFTER_CXX11 file_time_type error_value<file_time_type>() { + return file_time_type::min(); +} +template <> +path error_value<path>() { + return {}; +} + +template <class T> +struct ErrorHandler { + const char* func_name_; + error_code* ec_ = nullptr; + const path* p1_ = nullptr; + const path* p2_ = nullptr; + + ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr, + const path* p2 = nullptr) + : func_name_(fname), ec_(ec), p1_(p1), p2_(p2) { + if (ec_) + ec_->clear(); + } + + T report(const error_code& ec) const { + if (ec_) { + *ec_ = ec; + return error_value<T>(); + } + string what = string("in ") + func_name_; + switch (bool(p1_) + bool(p2_)) { + case 0: + __throw_filesystem_error(what, ec); + case 1: + __throw_filesystem_error(what, *p1_, ec); + case 2: + __throw_filesystem_error(what, *p1_, *p2_, ec); + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_FORMAT_PRINTF(3, 0) + void report_impl(const error_code& ec, const char* msg, va_list ap) const { + if (ec_) { + *ec_ = ec; + return; + } + string what = + string("in ") + func_name_ + ": " + format_string_impl(msg, ap); + switch (bool(p1_) + bool(p2_)) { + case 0: + __throw_filesystem_error(what, ec); + case 1: + __throw_filesystem_error(what, *p1_, ec); + case 2: + __throw_filesystem_error(what, *p1_, *p2_, ec); + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_FORMAT_PRINTF(3, 4) + T report(const error_code& ec, const char* msg, ...) const { + va_list ap; + va_start(ap, msg); +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif // _LIBCPP_NO_EXCEPTIONS + report_impl(ec, msg, ap); +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + va_end(ap); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + va_end(ap); + return error_value<T>(); + } + + T report(errc const& err) const { + return report(make_error_code(err)); + } + + _LIBCPP_FORMAT_PRINTF(3, 4) + T report(errc const& err, const char* msg, ...) const { + va_list ap; + va_start(ap, msg); +#ifndef _LIBCPP_NO_EXCEPTIONS + try { +#endif // _LIBCPP_NO_EXCEPTIONS + report_impl(make_error_code(err), msg, ap); +#ifndef _LIBCPP_NO_EXCEPTIONS + } catch (...) { + va_end(ap); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + va_end(ap); + return error_value<T>(); + } + +private: + ErrorHandler(ErrorHandler const&) = delete; + ErrorHandler& operator=(ErrorHandler const&) = delete; +}; + +using chrono::duration; +using chrono::duration_cast; + +#if defined(_LIBCPP_WIN32API) +// Various C runtime versions (UCRT, or the legacy msvcrt.dll used by +// some mingw toolchains) provide different stat function implementations, +// with a number of limitations with respect to what we want from the +// stat function. Instead provide our own (in the anonymous detail namespace +// in posix_compat.h) which does exactly what we want, along with our own +// stat structure and flag macros. + +struct TimeSpec { + int64_t tv_sec; + int64_t tv_nsec; +}; +struct StatT { + unsigned st_mode; + TimeSpec st_atim; + TimeSpec st_mtim; + uint64_t st_dev; // FILE_ID_INFO::VolumeSerialNumber + struct FileIdStruct { + unsigned char id[16]; // FILE_ID_INFO::FileId + bool operator==(const FileIdStruct &other) const { + for (int i = 0; i < 16; i++) + if (id[i] != other.id[i]) + return false; + return true; + } + } st_ino; + uint32_t st_nlink; + uintmax_t st_size; +}; + +#else +using TimeSpec = struct timespec; +using TimeVal = struct timeval; +using StatT = struct stat; +#endif + +template <class FileTimeT, class TimeT, + bool IsFloat = is_floating_point<typename FileTimeT::rep>::value> +struct time_util_base { + using rep = typename FileTimeT::rep; + using fs_duration = typename FileTimeT::duration; + using fs_seconds = duration<rep>; + using fs_nanoseconds = duration<rep, nano>; + using fs_microseconds = duration<rep, micro>; + + static constexpr rep max_seconds = + duration_cast<fs_seconds>(FileTimeT::duration::max()).count(); + + static constexpr rep max_nsec = + duration_cast<fs_nanoseconds>(FileTimeT::duration::max() - + fs_seconds(max_seconds)) + .count(); + + static constexpr rep min_seconds = + duration_cast<fs_seconds>(FileTimeT::duration::min()).count(); + + static constexpr rep min_nsec_timespec = + duration_cast<fs_nanoseconds>( + (FileTimeT::duration::min() - fs_seconds(min_seconds)) + + fs_seconds(1)) + .count(); + +private: + static _LIBCPP_CONSTEXPR_AFTER_CXX11 fs_duration get_min_nsecs() { + return duration_cast<fs_duration>( + fs_nanoseconds(min_nsec_timespec) - + duration_cast<fs_nanoseconds>(fs_seconds(1))); + } + // Static assert that these values properly round trip. + static_assert(fs_seconds(min_seconds) + get_min_nsecs() == + FileTimeT::duration::min(), + "value doesn't roundtrip"); + + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool check_range() { + // This kinda sucks, but it's what happens when we don't have __int128_t. + if (sizeof(TimeT) == sizeof(rep)) { + typedef duration<long long, ratio<3600 * 24 * 365> > Years; + return duration_cast<Years>(fs_seconds(max_seconds)) > Years(250) && + duration_cast<Years>(fs_seconds(min_seconds)) < Years(-250); + } + return max_seconds >= numeric_limits<TimeT>::max() && + min_seconds <= numeric_limits<TimeT>::min(); + } + static_assert(check_range(), "the representable range is unacceptable small"); +}; + +template <class FileTimeT, class TimeT> +struct time_util_base<FileTimeT, TimeT, true> { + using rep = typename FileTimeT::rep; + using fs_duration = typename FileTimeT::duration; + using fs_seconds = duration<rep>; + using fs_nanoseconds = duration<rep, nano>; + using fs_microseconds = duration<rep, micro>; + + static const rep max_seconds; + static const rep max_nsec; + static const rep min_seconds; + static const rep min_nsec_timespec; +}; + +template <class FileTimeT, class TimeT> +const typename FileTimeT::rep + time_util_base<FileTimeT, TimeT, true>::max_seconds = + duration_cast<fs_seconds>(FileTimeT::duration::max()).count(); + +template <class FileTimeT, class TimeT> +const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_nsec = + duration_cast<fs_nanoseconds>(FileTimeT::duration::max() - + fs_seconds(max_seconds)) + .count(); + +template <class FileTimeT, class TimeT> +const typename FileTimeT::rep + time_util_base<FileTimeT, TimeT, true>::min_seconds = + duration_cast<fs_seconds>(FileTimeT::duration::min()).count(); + +template <class FileTimeT, class TimeT> +const typename FileTimeT::rep + time_util_base<FileTimeT, TimeT, true>::min_nsec_timespec = + duration_cast<fs_nanoseconds>((FileTimeT::duration::min() - + fs_seconds(min_seconds)) + + fs_seconds(1)) + .count(); + +template <class FileTimeT, class TimeT, class TimeSpecT> +struct time_util : time_util_base<FileTimeT, TimeT> { + using Base = time_util_base<FileTimeT, TimeT>; + using Base::max_nsec; + using Base::max_seconds; + using Base::min_nsec_timespec; + using Base::min_seconds; + + using typename Base::fs_duration; + using typename Base::fs_microseconds; + using typename Base::fs_nanoseconds; + using typename Base::fs_seconds; + +public: + template <class CType, class ChronoType> + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool checked_set(CType* out, + ChronoType time) { + using Lim = numeric_limits<CType>; + if (time > Lim::max() || time < Lim::min()) + return false; + *out = static_cast<CType>(time); + return true; + } + + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) { + if (tm.tv_sec >= 0) { + return tm.tv_sec < max_seconds || + (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec); + } else if (tm.tv_sec == (min_seconds - 1)) { + return tm.tv_nsec >= min_nsec_timespec; + } else { + return tm.tv_sec >= min_seconds; + } + } + + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) { + auto secs = duration_cast<fs_seconds>(tm.time_since_epoch()); + auto nsecs = duration_cast<fs_nanoseconds>(tm.time_since_epoch() - secs); + if (nsecs.count() < 0) { + secs = secs + fs_seconds(1); + nsecs = nsecs + fs_seconds(1); + } + using TLim = numeric_limits<TimeT>; + if (secs.count() >= 0) + return secs.count() <= TLim::max(); + return secs.count() >= TLim::min(); + } + + static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT + convert_from_timespec(TimeSpecT tm) { + if (tm.tv_sec >= 0 || tm.tv_nsec == 0) { + return FileTimeT(fs_seconds(tm.tv_sec) + + duration_cast<fs_duration>(fs_nanoseconds(tm.tv_nsec))); + } else { // tm.tv_sec < 0 + auto adj_subsec = duration_cast<fs_duration>(fs_seconds(1) - + fs_nanoseconds(tm.tv_nsec)); + auto Dur = fs_seconds(tm.tv_sec + 1) - adj_subsec; + return FileTimeT(Dur); + } + } + + template <class SubSecT> + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool + set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) { + auto dur = tp.time_since_epoch(); + auto sec_dur = duration_cast<fs_seconds>(dur); + auto subsec_dur = duration_cast<fs_nanoseconds>(dur - sec_dur); + // The tv_nsec and tv_usec fields must not be negative so adjust accordingly + if (subsec_dur.count() < 0) { + if (sec_dur.count() > min_seconds) { + sec_dur = sec_dur - fs_seconds(1); + subsec_dur = subsec_dur + fs_seconds(1); + } else { + subsec_dur = fs_nanoseconds::zero(); + } + } + return checked_set(sec_out, sec_dur.count()) && + checked_set(subsec_out, subsec_dur.count()); + } + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool convert_to_timespec(TimeSpecT& dest, + FileTimeT tp) { + if (!is_representable(tp)) + return false; + return set_times_checked(&dest.tv_sec, &dest.tv_nsec, tp); + } +}; + +#if defined(_LIBCPP_WIN32API) +using fs_time = time_util<file_time_type, int64_t, TimeSpec>; +#else +using fs_time = time_util<file_time_type, time_t, TimeSpec>; +#endif + +#if defined(__APPLE__) +inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; } +inline TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; } +#elif defined(__MVS__) +inline TimeSpec extract_mtime(StatT const& st) { + TimeSpec TS = {st.st_mtime, 0}; + return TS; +} +inline TimeSpec extract_atime(StatT const& st) { + TimeSpec TS = {st.st_atime, 0}; + return TS; +} +#elif defined(_AIX) +inline TimeSpec extract_mtime(StatT const& st) { + TimeSpec TS = {st.st_mtime, st.st_mtime_n}; + return TS; +} +inline TimeSpec extract_atime(StatT const& st) { + TimeSpec TS = {st.st_atime, st.st_atime_n}; + return TS; +} +#else +inline TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } +inline TimeSpec extract_atime(StatT const& st) { return st.st_atim; } +#endif + +#if !defined(_LIBCPP_WIN32API) +inline TimeVal make_timeval(TimeSpec const& ts) { + using namespace chrono; + auto Convert = [](long nsec) { + using int_type = decltype(std::declval<TimeVal>().tv_usec); + auto dur = duration_cast<microseconds>(nanoseconds(nsec)).count(); + return static_cast<int_type>(dur); + }; + TimeVal TV = {}; + TV.tv_sec = ts.tv_sec; + TV.tv_usec = Convert(ts.tv_nsec); + return TV; +} + +inline bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS, + error_code& ec) { + TimeVal ConvertedTS[2] = {make_timeval(TS[0]), make_timeval(TS[1])}; + if (::utimes(p.c_str(), ConvertedTS) == -1) { + ec = capture_errno(); + return true; + } + return false; +} + +#if defined(_LIBCPP_USE_UTIMENSAT) +bool posix_utimensat(const path& p, std::array<TimeSpec, 2> const& TS, + error_code& ec) { + if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) { + ec = capture_errno(); + return true; + } + return false; +} +#endif + +bool set_file_times(const path& p, std::array<TimeSpec, 2> const& TS, + error_code& ec) { +#if !defined(_LIBCPP_USE_UTIMENSAT) + return posix_utimes(p, TS, ec); +#else + return posix_utimensat(p, TS, ec); +#endif +} +#endif /* !_LIBCPP_WIN32API */ + +} // namespace +} // end namespace detail + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // FILESYSTEM_COMMON_H diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/int128_builtins.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/int128_builtins.cpp index a3073ce90a..ed531ee145 100644 --- a/contrib/libs/cxxsupp/libcxx/src/filesystem/int128_builtins.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/int128_builtins.cpp @@ -1,54 +1,54 @@ -/*===-- int128_builtins.cpp - Implement __muloti4 --------------------------=== - * +/*===-- int128_builtins.cpp - Implement __muloti4 --------------------------=== + * * 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 - * - * ===----------------------------------------------------------------------=== - * - * This file implements __muloti4, and is stolen from the compiler_rt library. - * - * FIXME: we steal and re-compile it into filesystem, which uses __int128_t, - * and requires this builtin when sanitized. See llvm.org/PR30643 - * - * ===----------------------------------------------------------------------=== - */ -#include "__config" -#include "climits" - -#if !defined(_LIBCPP_HAS_NO_INT128) - -extern "C" __attribute__((no_sanitize("undefined"))) _LIBCPP_FUNC_VIS -__int128_t __muloti4(__int128_t a, __int128_t b, int* overflow) { - const int N = (int)(sizeof(__int128_t) * CHAR_BIT); - const __int128_t MIN = (__int128_t)1 << (N - 1); - const __int128_t MAX = ~MIN; - *overflow = 0; - __int128_t result = a * b; - if (a == MIN) { - if (b != 0 && b != 1) - *overflow = 1; - return result; - } - if (b == MIN) { - if (a != 0 && a != 1) - *overflow = 1; - return result; - } - __int128_t sa = a >> (N - 1); - __int128_t abs_a = (a ^ sa) - sa; - __int128_t sb = b >> (N - 1); - __int128_t abs_b = (b ^ sb) - sb; - if (abs_a < 2 || abs_b < 2) - return result; - if (sa == sb) { - if (abs_a > MAX / abs_b) - *overflow = 1; - } else { - if (abs_a > MIN / -abs_b) - *overflow = 1; - } - return result; -} - -#endif + * + * ===----------------------------------------------------------------------=== + * + * This file implements __muloti4, and is stolen from the compiler_rt library. + * + * FIXME: we steal and re-compile it into filesystem, which uses __int128_t, + * and requires this builtin when sanitized. See llvm.org/PR30643 + * + * ===----------------------------------------------------------------------=== + */ +#include "__config" +#include "climits" + +#if !defined(_LIBCPP_HAS_NO_INT128) + +extern "C" __attribute__((no_sanitize("undefined"))) _LIBCPP_FUNC_VIS +__int128_t __muloti4(__int128_t a, __int128_t b, int* overflow) { + const int N = (int)(sizeof(__int128_t) * CHAR_BIT); + const __int128_t MIN = (__int128_t)1 << (N - 1); + const __int128_t MAX = ~MIN; + *overflow = 0; + __int128_t result = a * b; + if (a == MIN) { + if (b != 0 && b != 1) + *overflow = 1; + return result; + } + if (b == MIN) { + if (a != 0 && a != 1) + *overflow = 1; + return result; + } + __int128_t sa = a >> (N - 1); + __int128_t abs_a = (a ^ sa) - sa; + __int128_t sb = b >> (N - 1); + __int128_t abs_b = (b ^ sb) - sb; + if (abs_a < 2 || abs_b < 2) + return result; + if (sa == sb) { + if (abs_a > MAX / abs_b) + *overflow = 1; + } else { + if (abs_a > MIN / -abs_b) + *overflow = 1; + } + return result; +} + +#endif diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp b/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp index eefc641e93..63593be223 100644 --- a/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/operations.cpp @@ -1,245 +1,245 @@ -//===--------------------- filesystem/ops.cpp -----------------------------===// -// +//===--------------------- filesystem/ops.cpp -----------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "filesystem" -#include "array" -#include "iterator" -#include "string_view" -#include "type_traits" -#include "vector" -#include "cstdlib" -#include "climits" - -#include "filesystem_common.h" - -#include "posix_compat.h" - -#if defined(_LIBCPP_WIN32API) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# include <windows.h> -#else +// +//===----------------------------------------------------------------------===// + +#include "filesystem" +#include "array" +#include "iterator" +#include "string_view" +#include "type_traits" +#include "vector" +#include "cstdlib" +#include "climits" + +#include "filesystem_common.h" + +#include "posix_compat.h" + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <windows.h> +#else # include <unistd.h> # include <sys/stat.h> # include <sys/statvfs.h> -#endif -#include <time.h> -#include <fcntl.h> /* values for fchmodat */ - -#if __has_include(<sys/sendfile.h>) +#endif +#include <time.h> +#include <fcntl.h> /* values for fchmodat */ + +#if __has_include(<sys/sendfile.h>) # include <sys/sendfile.h> -# define _LIBCPP_FILESYSTEM_USE_SENDFILE -#elif defined(__APPLE__) || __has_include(<copyfile.h>) +# define _LIBCPP_FILESYSTEM_USE_SENDFILE +#elif defined(__APPLE__) || __has_include(<copyfile.h>) # include <copyfile.h> -# define _LIBCPP_FILESYSTEM_USE_COPYFILE -#else -# include "fstream" -# define _LIBCPP_FILESYSTEM_USE_FSTREAM -#endif - -#if !defined(CLOCK_REALTIME) && !defined(_LIBCPP_WIN32API) +# define _LIBCPP_FILESYSTEM_USE_COPYFILE +#else +# include "fstream" +# define _LIBCPP_FILESYSTEM_USE_FSTREAM +#endif + +#if !defined(CLOCK_REALTIME) && !defined(_LIBCPP_WIN32API) # include <sys/time.h> // for gettimeofday and timeval -#endif - -#if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) +#endif + +#if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB) # pragma comment(lib, "rt") -#endif - -_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM - -namespace { - -bool isSeparator(path::value_type C) { - if (C == '/') - return true; -#if defined(_LIBCPP_WIN32API) - if (C == '\\') - return true; -#endif - return false; -} - -bool isDriveLetter(path::value_type C) { - return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z'); -} - -namespace parser { - -using string_view_t = path::__string_view; -using string_view_pair = pair<string_view_t, string_view_t>; -using PosPtr = path::value_type const*; - -struct PathParser { - enum ParserState : unsigned char { - // Zero is a special sentinel value used by default constructed iterators. - PS_BeforeBegin = path::iterator::_BeforeBegin, - PS_InRootName = path::iterator::_InRootName, - PS_InRootDir = path::iterator::_InRootDir, - PS_InFilenames = path::iterator::_InFilenames, - PS_InTrailingSep = path::iterator::_InTrailingSep, - PS_AtEnd = path::iterator::_AtEnd - }; - - const string_view_t Path; - string_view_t RawEntry; - ParserState State; - -private: - PathParser(string_view_t P, ParserState State) noexcept : Path(P), - State(State) {} - -public: - PathParser(string_view_t P, string_view_t E, unsigned char S) - : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) { - // S cannot be '0' or PS_BeforeBegin. - } - - static PathParser CreateBegin(string_view_t P) noexcept { - PathParser PP(P, PS_BeforeBegin); - PP.increment(); - return PP; - } - - static PathParser CreateEnd(string_view_t P) noexcept { - PathParser PP(P, PS_AtEnd); - return PP; - } - - PosPtr peek() const noexcept { - auto TkEnd = getNextTokenStartPos(); - auto End = getAfterBack(); - return TkEnd == End ? nullptr : TkEnd; - } - - void increment() noexcept { - const PosPtr End = getAfterBack(); - const PosPtr Start = getNextTokenStartPos(); - if (Start == End) - return makeState(PS_AtEnd); - - switch (State) { - case PS_BeforeBegin: { - PosPtr TkEnd = consumeRootName(Start, End); - if (TkEnd) - return makeState(PS_InRootName, Start, TkEnd); - } - _LIBCPP_FALLTHROUGH(); - case PS_InRootName: { - PosPtr TkEnd = consumeAllSeparators(Start, End); - if (TkEnd) - return makeState(PS_InRootDir, Start, TkEnd); - else - return makeState(PS_InFilenames, Start, consumeName(Start, End)); - } - case PS_InRootDir: - return makeState(PS_InFilenames, Start, consumeName(Start, End)); - - case PS_InFilenames: { - PosPtr SepEnd = consumeAllSeparators(Start, End); - if (SepEnd != End) { - PosPtr TkEnd = consumeName(SepEnd, End); - if (TkEnd) - return makeState(PS_InFilenames, SepEnd, TkEnd); - } - return makeState(PS_InTrailingSep, Start, SepEnd); - } - - case PS_InTrailingSep: - return makeState(PS_AtEnd); - - case PS_AtEnd: - _LIBCPP_UNREACHABLE(); - } - } - - void decrement() noexcept { - const PosPtr REnd = getBeforeFront(); - const PosPtr RStart = getCurrentTokenStartPos() - 1; - if (RStart == REnd) // we're decrementing the begin - return makeState(PS_BeforeBegin); - - switch (State) { - case PS_AtEnd: { - // Try to consume a trailing separator or root directory first. - if (PosPtr SepEnd = consumeAllSeparators(RStart, REnd)) { - if (SepEnd == REnd) - return makeState(PS_InRootDir, Path.data(), RStart + 1); - PosPtr TkStart = consumeRootName(SepEnd, REnd); - if (TkStart == REnd) - return makeState(PS_InRootDir, RStart, RStart + 1); - return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1); - } else { - PosPtr TkStart = consumeRootName(RStart, REnd); - if (TkStart == REnd) - return makeState(PS_InRootName, TkStart + 1, RStart + 1); - TkStart = consumeName(RStart, REnd); - return makeState(PS_InFilenames, TkStart + 1, RStart + 1); - } - } - case PS_InTrailingSep: - return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1, - RStart + 1); - case PS_InFilenames: { - PosPtr SepEnd = consumeAllSeparators(RStart, REnd); - if (SepEnd == REnd) - return makeState(PS_InRootDir, Path.data(), RStart + 1); - PosPtr TkStart = consumeRootName(SepEnd ? SepEnd : RStart, REnd); - if (TkStart == REnd) { - if (SepEnd) - return makeState(PS_InRootDir, SepEnd + 1, RStart + 1); - return makeState(PS_InRootName, TkStart + 1, RStart + 1); - } - TkStart = consumeName(SepEnd, REnd); - return makeState(PS_InFilenames, TkStart + 1, SepEnd + 1); - } - case PS_InRootDir: - return makeState(PS_InRootName, Path.data(), RStart + 1); - case PS_InRootName: - case PS_BeforeBegin: - _LIBCPP_UNREACHABLE(); - } - } - - /// \brief Return a view with the "preferred representation" of the current - /// element. For example trailing separators are represented as a '.' - string_view_t operator*() const noexcept { - switch (State) { - case PS_BeforeBegin: - case PS_AtEnd: - return PS(""); - case PS_InRootDir: - if (RawEntry[0] == '\\') - return PS("\\"); - else - return PS("/"); - case PS_InTrailingSep: - return PS(""); - case PS_InRootName: - case PS_InFilenames: - return RawEntry; - } - _LIBCPP_UNREACHABLE(); - } - - explicit operator bool() const noexcept { - return State != PS_BeforeBegin && State != PS_AtEnd; - } - - PathParser& operator++() noexcept { - increment(); - return *this; - } - - PathParser& operator--() noexcept { - decrement(); - return *this; - } - +#endif + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +namespace { + +bool isSeparator(path::value_type C) { + if (C == '/') + return true; +#if defined(_LIBCPP_WIN32API) + if (C == '\\') + return true; +#endif + return false; +} + +bool isDriveLetter(path::value_type C) { + return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z'); +} + +namespace parser { + +using string_view_t = path::__string_view; +using string_view_pair = pair<string_view_t, string_view_t>; +using PosPtr = path::value_type const*; + +struct PathParser { + enum ParserState : unsigned char { + // Zero is a special sentinel value used by default constructed iterators. + PS_BeforeBegin = path::iterator::_BeforeBegin, + PS_InRootName = path::iterator::_InRootName, + PS_InRootDir = path::iterator::_InRootDir, + PS_InFilenames = path::iterator::_InFilenames, + PS_InTrailingSep = path::iterator::_InTrailingSep, + PS_AtEnd = path::iterator::_AtEnd + }; + + const string_view_t Path; + string_view_t RawEntry; + ParserState State; + +private: + PathParser(string_view_t P, ParserState State) noexcept : Path(P), + State(State) {} + +public: + PathParser(string_view_t P, string_view_t E, unsigned char S) + : Path(P), RawEntry(E), State(static_cast<ParserState>(S)) { + // S cannot be '0' or PS_BeforeBegin. + } + + static PathParser CreateBegin(string_view_t P) noexcept { + PathParser PP(P, PS_BeforeBegin); + PP.increment(); + return PP; + } + + static PathParser CreateEnd(string_view_t P) noexcept { + PathParser PP(P, PS_AtEnd); + return PP; + } + + PosPtr peek() const noexcept { + auto TkEnd = getNextTokenStartPos(); + auto End = getAfterBack(); + return TkEnd == End ? nullptr : TkEnd; + } + + void increment() noexcept { + const PosPtr End = getAfterBack(); + const PosPtr Start = getNextTokenStartPos(); + if (Start == End) + return makeState(PS_AtEnd); + + switch (State) { + case PS_BeforeBegin: { + PosPtr TkEnd = consumeRootName(Start, End); + if (TkEnd) + return makeState(PS_InRootName, Start, TkEnd); + } + _LIBCPP_FALLTHROUGH(); + case PS_InRootName: { + PosPtr TkEnd = consumeAllSeparators(Start, End); + if (TkEnd) + return makeState(PS_InRootDir, Start, TkEnd); + else + return makeState(PS_InFilenames, Start, consumeName(Start, End)); + } + case PS_InRootDir: + return makeState(PS_InFilenames, Start, consumeName(Start, End)); + + case PS_InFilenames: { + PosPtr SepEnd = consumeAllSeparators(Start, End); + if (SepEnd != End) { + PosPtr TkEnd = consumeName(SepEnd, End); + if (TkEnd) + return makeState(PS_InFilenames, SepEnd, TkEnd); + } + return makeState(PS_InTrailingSep, Start, SepEnd); + } + + case PS_InTrailingSep: + return makeState(PS_AtEnd); + + case PS_AtEnd: + _LIBCPP_UNREACHABLE(); + } + } + + void decrement() noexcept { + const PosPtr REnd = getBeforeFront(); + const PosPtr RStart = getCurrentTokenStartPos() - 1; + if (RStart == REnd) // we're decrementing the begin + return makeState(PS_BeforeBegin); + + switch (State) { + case PS_AtEnd: { + // Try to consume a trailing separator or root directory first. + if (PosPtr SepEnd = consumeAllSeparators(RStart, REnd)) { + if (SepEnd == REnd) + return makeState(PS_InRootDir, Path.data(), RStart + 1); + PosPtr TkStart = consumeRootName(SepEnd, REnd); + if (TkStart == REnd) + return makeState(PS_InRootDir, RStart, RStart + 1); + return makeState(PS_InTrailingSep, SepEnd + 1, RStart + 1); + } else { + PosPtr TkStart = consumeRootName(RStart, REnd); + if (TkStart == REnd) + return makeState(PS_InRootName, TkStart + 1, RStart + 1); + TkStart = consumeName(RStart, REnd); + return makeState(PS_InFilenames, TkStart + 1, RStart + 1); + } + } + case PS_InTrailingSep: + return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1, + RStart + 1); + case PS_InFilenames: { + PosPtr SepEnd = consumeAllSeparators(RStart, REnd); + if (SepEnd == REnd) + return makeState(PS_InRootDir, Path.data(), RStart + 1); + PosPtr TkStart = consumeRootName(SepEnd ? SepEnd : RStart, REnd); + if (TkStart == REnd) { + if (SepEnd) + return makeState(PS_InRootDir, SepEnd + 1, RStart + 1); + return makeState(PS_InRootName, TkStart + 1, RStart + 1); + } + TkStart = consumeName(SepEnd, REnd); + return makeState(PS_InFilenames, TkStart + 1, SepEnd + 1); + } + case PS_InRootDir: + return makeState(PS_InRootName, Path.data(), RStart + 1); + case PS_InRootName: + case PS_BeforeBegin: + _LIBCPP_UNREACHABLE(); + } + } + + /// \brief Return a view with the "preferred representation" of the current + /// element. For example trailing separators are represented as a '.' + string_view_t operator*() const noexcept { + switch (State) { + case PS_BeforeBegin: + case PS_AtEnd: + return PS(""); + case PS_InRootDir: + if (RawEntry[0] == '\\') + return PS("\\"); + else + return PS("/"); + case PS_InTrailingSep: + return PS(""); + case PS_InRootName: + case PS_InFilenames: + return RawEntry; + } + _LIBCPP_UNREACHABLE(); + } + + explicit operator bool() const noexcept { + return State != PS_BeforeBegin && State != PS_AtEnd; + } + + PathParser& operator++() noexcept { + increment(); + return *this; + } + + PathParser& operator--() noexcept { + decrement(); + return *this; + } + bool atEnd() const noexcept { return State == PS_AtEnd; } @@ -252,1306 +252,1306 @@ public: return State == PS_InRootName; } - bool inRootPath() const noexcept { + bool inRootPath() const noexcept { return inRootName() || inRootDir(); - } - -private: - void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept { - State = NewState; - RawEntry = string_view_t(Start, End - Start); - } - void makeState(ParserState NewState) noexcept { - State = NewState; - RawEntry = {}; - } - - PosPtr getAfterBack() const noexcept { return Path.data() + Path.size(); } - - PosPtr getBeforeFront() const noexcept { return Path.data() - 1; } - - /// \brief Return a pointer to the first character after the currently - /// lexed element. - PosPtr getNextTokenStartPos() const noexcept { - switch (State) { - case PS_BeforeBegin: - return Path.data(); - case PS_InRootName: - case PS_InRootDir: - case PS_InFilenames: - return &RawEntry.back() + 1; - case PS_InTrailingSep: - case PS_AtEnd: - return getAfterBack(); - } - _LIBCPP_UNREACHABLE(); - } - - /// \brief Return a pointer to the first character in the currently lexed - /// element. - PosPtr getCurrentTokenStartPos() const noexcept { - switch (State) { - case PS_BeforeBegin: - case PS_InRootName: - return &Path.front(); - case PS_InRootDir: - case PS_InFilenames: - case PS_InTrailingSep: - return &RawEntry.front(); - case PS_AtEnd: - return &Path.back() + 1; - } - _LIBCPP_UNREACHABLE(); - } - - // Consume all consecutive separators. - PosPtr consumeAllSeparators(PosPtr P, PosPtr End) const noexcept { - if (P == nullptr || P == End || !isSeparator(*P)) - return nullptr; - const int Inc = P < End ? 1 : -1; - P += Inc; - while (P != End && isSeparator(*P)) - P += Inc; - return P; - } - - // Consume exactly N separators, or return nullptr. - PosPtr consumeNSeparators(PosPtr P, PosPtr End, int N) const noexcept { - PosPtr Ret = consumeAllSeparators(P, End); - if (Ret == nullptr) - return nullptr; - if (P < End) { - if (Ret == P + N) - return Ret; - } else { - if (Ret == P - N) - return Ret; - } - return nullptr; - } - - PosPtr consumeName(PosPtr P, PosPtr End) const noexcept { - PosPtr Start = P; - if (P == nullptr || P == End || isSeparator(*P)) - return nullptr; - const int Inc = P < End ? 1 : -1; - P += Inc; - while (P != End && !isSeparator(*P)) - P += Inc; - if (P == End && Inc < 0) { - // Iterating backwards and consumed all the rest of the input. - // Check if the start of the string would have been considered - // a root name. - PosPtr RootEnd = consumeRootName(End + 1, Start); - if (RootEnd) - return RootEnd - 1; - } - return P; - } - - PosPtr consumeDriveLetter(PosPtr P, PosPtr End) const noexcept { - if (P == End) - return nullptr; - if (P < End) { - if (P + 1 == End || !isDriveLetter(P[0]) || P[1] != ':') - return nullptr; - return P + 2; - } else { - if (P - 1 == End || !isDriveLetter(P[-1]) || P[0] != ':') - return nullptr; - return P - 2; - } - } - - PosPtr consumeNetworkRoot(PosPtr P, PosPtr End) const noexcept { - if (P == End) - return nullptr; - if (P < End) - return consumeName(consumeNSeparators(P, End, 2), End); - else - return consumeNSeparators(consumeName(P, End), End, 2); - } - -#if defined(_LIBCPP_WIN32API) - PosPtr consumeRootName(PosPtr P, PosPtr End) const noexcept { - if (PosPtr Ret = consumeDriveLetter(P, End)) - return Ret; - if (PosPtr Ret = consumeNetworkRoot(P, End)) - return Ret; - return nullptr; - } -#else - PosPtr consumeRootName(PosPtr /*P*/, PosPtr /*End*/) const noexcept { - return nullptr; - } -#endif -}; - -string_view_pair separate_filename(string_view_t const& s) { - if (s == PS(".") || s == PS("..") || s.empty()) - return string_view_pair{s, PS("")}; - auto pos = s.find_last_of('.'); - if (pos == string_view_t::npos || pos == 0) - return string_view_pair{s, string_view_t{}}; - return string_view_pair{s.substr(0, pos), s.substr(pos)}; -} - -string_view_t createView(PosPtr S, PosPtr E) noexcept { - return {S, static_cast<size_t>(E - S) + 1}; -} - -} // namespace parser -} // namespace - -// POSIX HELPERS - -#if defined(_LIBCPP_WIN32API) -namespace detail { - -errc __win_err_to_errc(int err) { - constexpr struct { - DWORD win; - errc errc; - } win_error_mapping[] = { - {ERROR_ACCESS_DENIED, errc::permission_denied}, - {ERROR_ALREADY_EXISTS, errc::file_exists}, - {ERROR_BAD_NETPATH, errc::no_such_file_or_directory}, - {ERROR_BAD_PATHNAME, errc::no_such_file_or_directory}, - {ERROR_BAD_UNIT, errc::no_such_device}, - {ERROR_BROKEN_PIPE, errc::broken_pipe}, - {ERROR_BUFFER_OVERFLOW, errc::filename_too_long}, - {ERROR_BUSY, errc::device_or_resource_busy}, - {ERROR_BUSY_DRIVE, errc::device_or_resource_busy}, - {ERROR_CANNOT_MAKE, errc::permission_denied}, - {ERROR_CANTOPEN, errc::io_error}, - {ERROR_CANTREAD, errc::io_error}, - {ERROR_CANTWRITE, errc::io_error}, - {ERROR_CURRENT_DIRECTORY, errc::permission_denied}, - {ERROR_DEV_NOT_EXIST, errc::no_such_device}, - {ERROR_DEVICE_IN_USE, errc::device_or_resource_busy}, - {ERROR_DIR_NOT_EMPTY, errc::directory_not_empty}, - {ERROR_DIRECTORY, errc::invalid_argument}, - {ERROR_DISK_FULL, errc::no_space_on_device}, - {ERROR_FILE_EXISTS, errc::file_exists}, - {ERROR_FILE_NOT_FOUND, errc::no_such_file_or_directory}, - {ERROR_HANDLE_DISK_FULL, errc::no_space_on_device}, - {ERROR_INVALID_ACCESS, errc::permission_denied}, - {ERROR_INVALID_DRIVE, errc::no_such_device}, - {ERROR_INVALID_FUNCTION, errc::function_not_supported}, - {ERROR_INVALID_HANDLE, errc::invalid_argument}, - {ERROR_INVALID_NAME, errc::no_such_file_or_directory}, - {ERROR_INVALID_PARAMETER, errc::invalid_argument}, - {ERROR_LOCK_VIOLATION, errc::no_lock_available}, - {ERROR_LOCKED, errc::no_lock_available}, - {ERROR_NEGATIVE_SEEK, errc::invalid_argument}, - {ERROR_NOACCESS, errc::permission_denied}, - {ERROR_NOT_ENOUGH_MEMORY, errc::not_enough_memory}, - {ERROR_NOT_READY, errc::resource_unavailable_try_again}, - {ERROR_NOT_SAME_DEVICE, errc::cross_device_link}, - {ERROR_NOT_SUPPORTED, errc::not_supported}, - {ERROR_OPEN_FAILED, errc::io_error}, - {ERROR_OPEN_FILES, errc::device_or_resource_busy}, - {ERROR_OPERATION_ABORTED, errc::operation_canceled}, - {ERROR_OUTOFMEMORY, errc::not_enough_memory}, - {ERROR_PATH_NOT_FOUND, errc::no_such_file_or_directory}, - {ERROR_READ_FAULT, errc::io_error}, - {ERROR_REPARSE_TAG_INVALID, errc::invalid_argument}, - {ERROR_RETRY, errc::resource_unavailable_try_again}, - {ERROR_SEEK, errc::io_error}, - {ERROR_SHARING_VIOLATION, errc::permission_denied}, - {ERROR_TOO_MANY_OPEN_FILES, errc::too_many_files_open}, - {ERROR_WRITE_FAULT, errc::io_error}, - {ERROR_WRITE_PROTECT, errc::permission_denied}, - }; - - for (const auto &pair : win_error_mapping) - if (pair.win == static_cast<DWORD>(err)) - return pair.errc; - return errc::invalid_argument; -} - -} // namespace detail -#endif - -namespace detail { -namespace { - -using value_type = path::value_type; -using string_type = path::string_type; - -struct FileDescriptor { - const path& name; - int fd = -1; - StatT m_stat; - file_status m_status; - - template <class... Args> - static FileDescriptor create(const path* p, error_code& ec, Args... args) { - ec.clear(); - int fd; - if ((fd = detail::open(p->c_str(), args...)) == -1) { - ec = capture_errno(); - return FileDescriptor{p}; - } - return FileDescriptor(p, fd); - } - - template <class... Args> - static FileDescriptor create_with_status(const path* p, error_code& ec, - Args... args) { - FileDescriptor fd = create(p, ec, args...); - if (!ec) - fd.refresh_status(ec); - - return fd; - } - - file_status get_status() const { return m_status; } - StatT const& get_stat() const { return m_stat; } - - bool status_known() const { return _VSTD_FS::status_known(m_status); } - - file_status refresh_status(error_code& ec); - - void close() noexcept { - if (fd != -1) - detail::close(fd); - fd = -1; - } - - FileDescriptor(FileDescriptor&& other) - : name(other.name), fd(other.fd), m_stat(other.m_stat), - m_status(other.m_status) { - other.fd = -1; - other.m_status = file_status{}; - } - - ~FileDescriptor() { close(); } - - FileDescriptor(FileDescriptor const&) = delete; - FileDescriptor& operator=(FileDescriptor const&) = delete; - -private: - explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {} -}; - -perms posix_get_perms(const StatT& st) noexcept { - return static_cast<perms>(st.st_mode) & perms::mask; -} - -file_status create_file_status(error_code& m_ec, path const& p, - const StatT& path_stat, error_code* ec) { - if (ec) - *ec = m_ec; - if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { - return file_status(file_type::not_found); - } else if (m_ec) { - ErrorHandler<void> err("posix_stat", ec, &p); - err.report(m_ec, "failed to determine attributes for the specified path"); - return file_status(file_type::none); - } - // else - - file_status fs_tmp; - auto const mode = path_stat.st_mode; - if (S_ISLNK(mode)) - fs_tmp.type(file_type::symlink); - else if (S_ISREG(mode)) - fs_tmp.type(file_type::regular); - else if (S_ISDIR(mode)) - fs_tmp.type(file_type::directory); - else if (S_ISBLK(mode)) - fs_tmp.type(file_type::block); - else if (S_ISCHR(mode)) - fs_tmp.type(file_type::character); - else if (S_ISFIFO(mode)) - fs_tmp.type(file_type::fifo); - else if (S_ISSOCK(mode)) - fs_tmp.type(file_type::socket); - else - fs_tmp.type(file_type::unknown); - - fs_tmp.permissions(detail::posix_get_perms(path_stat)); - return fs_tmp; -} - -file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) { - error_code m_ec; - if (detail::stat(p.c_str(), &path_stat) == -1) - m_ec = detail::capture_errno(); - return create_file_status(m_ec, p, path_stat, ec); -} - -file_status posix_stat(path const& p, error_code* ec) { - StatT path_stat; - return posix_stat(p, path_stat, ec); -} - -file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) { - error_code m_ec; - if (detail::lstat(p.c_str(), &path_stat) == -1) - m_ec = detail::capture_errno(); - return create_file_status(m_ec, p, path_stat, ec); -} - -file_status posix_lstat(path const& p, error_code* ec) { - StatT path_stat; - return posix_lstat(p, path_stat, ec); -} - + } + +private: + void makeState(ParserState NewState, PosPtr Start, PosPtr End) noexcept { + State = NewState; + RawEntry = string_view_t(Start, End - Start); + } + void makeState(ParserState NewState) noexcept { + State = NewState; + RawEntry = {}; + } + + PosPtr getAfterBack() const noexcept { return Path.data() + Path.size(); } + + PosPtr getBeforeFront() const noexcept { return Path.data() - 1; } + + /// \brief Return a pointer to the first character after the currently + /// lexed element. + PosPtr getNextTokenStartPos() const noexcept { + switch (State) { + case PS_BeforeBegin: + return Path.data(); + case PS_InRootName: + case PS_InRootDir: + case PS_InFilenames: + return &RawEntry.back() + 1; + case PS_InTrailingSep: + case PS_AtEnd: + return getAfterBack(); + } + _LIBCPP_UNREACHABLE(); + } + + /// \brief Return a pointer to the first character in the currently lexed + /// element. + PosPtr getCurrentTokenStartPos() const noexcept { + switch (State) { + case PS_BeforeBegin: + case PS_InRootName: + return &Path.front(); + case PS_InRootDir: + case PS_InFilenames: + case PS_InTrailingSep: + return &RawEntry.front(); + case PS_AtEnd: + return &Path.back() + 1; + } + _LIBCPP_UNREACHABLE(); + } + + // Consume all consecutive separators. + PosPtr consumeAllSeparators(PosPtr P, PosPtr End) const noexcept { + if (P == nullptr || P == End || !isSeparator(*P)) + return nullptr; + const int Inc = P < End ? 1 : -1; + P += Inc; + while (P != End && isSeparator(*P)) + P += Inc; + return P; + } + + // Consume exactly N separators, or return nullptr. + PosPtr consumeNSeparators(PosPtr P, PosPtr End, int N) const noexcept { + PosPtr Ret = consumeAllSeparators(P, End); + if (Ret == nullptr) + return nullptr; + if (P < End) { + if (Ret == P + N) + return Ret; + } else { + if (Ret == P - N) + return Ret; + } + return nullptr; + } + + PosPtr consumeName(PosPtr P, PosPtr End) const noexcept { + PosPtr Start = P; + if (P == nullptr || P == End || isSeparator(*P)) + return nullptr; + const int Inc = P < End ? 1 : -1; + P += Inc; + while (P != End && !isSeparator(*P)) + P += Inc; + if (P == End && Inc < 0) { + // Iterating backwards and consumed all the rest of the input. + // Check if the start of the string would have been considered + // a root name. + PosPtr RootEnd = consumeRootName(End + 1, Start); + if (RootEnd) + return RootEnd - 1; + } + return P; + } + + PosPtr consumeDriveLetter(PosPtr P, PosPtr End) const noexcept { + if (P == End) + return nullptr; + if (P < End) { + if (P + 1 == End || !isDriveLetter(P[0]) || P[1] != ':') + return nullptr; + return P + 2; + } else { + if (P - 1 == End || !isDriveLetter(P[-1]) || P[0] != ':') + return nullptr; + return P - 2; + } + } + + PosPtr consumeNetworkRoot(PosPtr P, PosPtr End) const noexcept { + if (P == End) + return nullptr; + if (P < End) + return consumeName(consumeNSeparators(P, End, 2), End); + else + return consumeNSeparators(consumeName(P, End), End, 2); + } + +#if defined(_LIBCPP_WIN32API) + PosPtr consumeRootName(PosPtr P, PosPtr End) const noexcept { + if (PosPtr Ret = consumeDriveLetter(P, End)) + return Ret; + if (PosPtr Ret = consumeNetworkRoot(P, End)) + return Ret; + return nullptr; + } +#else + PosPtr consumeRootName(PosPtr /*P*/, PosPtr /*End*/) const noexcept { + return nullptr; + } +#endif +}; + +string_view_pair separate_filename(string_view_t const& s) { + if (s == PS(".") || s == PS("..") || s.empty()) + return string_view_pair{s, PS("")}; + auto pos = s.find_last_of('.'); + if (pos == string_view_t::npos || pos == 0) + return string_view_pair{s, string_view_t{}}; + return string_view_pair{s.substr(0, pos), s.substr(pos)}; +} + +string_view_t createView(PosPtr S, PosPtr E) noexcept { + return {S, static_cast<size_t>(E - S) + 1}; +} + +} // namespace parser +} // namespace + +// POSIX HELPERS + +#if defined(_LIBCPP_WIN32API) +namespace detail { + +errc __win_err_to_errc(int err) { + constexpr struct { + DWORD win; + errc errc; + } win_error_mapping[] = { + {ERROR_ACCESS_DENIED, errc::permission_denied}, + {ERROR_ALREADY_EXISTS, errc::file_exists}, + {ERROR_BAD_NETPATH, errc::no_such_file_or_directory}, + {ERROR_BAD_PATHNAME, errc::no_such_file_or_directory}, + {ERROR_BAD_UNIT, errc::no_such_device}, + {ERROR_BROKEN_PIPE, errc::broken_pipe}, + {ERROR_BUFFER_OVERFLOW, errc::filename_too_long}, + {ERROR_BUSY, errc::device_or_resource_busy}, + {ERROR_BUSY_DRIVE, errc::device_or_resource_busy}, + {ERROR_CANNOT_MAKE, errc::permission_denied}, + {ERROR_CANTOPEN, errc::io_error}, + {ERROR_CANTREAD, errc::io_error}, + {ERROR_CANTWRITE, errc::io_error}, + {ERROR_CURRENT_DIRECTORY, errc::permission_denied}, + {ERROR_DEV_NOT_EXIST, errc::no_such_device}, + {ERROR_DEVICE_IN_USE, errc::device_or_resource_busy}, + {ERROR_DIR_NOT_EMPTY, errc::directory_not_empty}, + {ERROR_DIRECTORY, errc::invalid_argument}, + {ERROR_DISK_FULL, errc::no_space_on_device}, + {ERROR_FILE_EXISTS, errc::file_exists}, + {ERROR_FILE_NOT_FOUND, errc::no_such_file_or_directory}, + {ERROR_HANDLE_DISK_FULL, errc::no_space_on_device}, + {ERROR_INVALID_ACCESS, errc::permission_denied}, + {ERROR_INVALID_DRIVE, errc::no_such_device}, + {ERROR_INVALID_FUNCTION, errc::function_not_supported}, + {ERROR_INVALID_HANDLE, errc::invalid_argument}, + {ERROR_INVALID_NAME, errc::no_such_file_or_directory}, + {ERROR_INVALID_PARAMETER, errc::invalid_argument}, + {ERROR_LOCK_VIOLATION, errc::no_lock_available}, + {ERROR_LOCKED, errc::no_lock_available}, + {ERROR_NEGATIVE_SEEK, errc::invalid_argument}, + {ERROR_NOACCESS, errc::permission_denied}, + {ERROR_NOT_ENOUGH_MEMORY, errc::not_enough_memory}, + {ERROR_NOT_READY, errc::resource_unavailable_try_again}, + {ERROR_NOT_SAME_DEVICE, errc::cross_device_link}, + {ERROR_NOT_SUPPORTED, errc::not_supported}, + {ERROR_OPEN_FAILED, errc::io_error}, + {ERROR_OPEN_FILES, errc::device_or_resource_busy}, + {ERROR_OPERATION_ABORTED, errc::operation_canceled}, + {ERROR_OUTOFMEMORY, errc::not_enough_memory}, + {ERROR_PATH_NOT_FOUND, errc::no_such_file_or_directory}, + {ERROR_READ_FAULT, errc::io_error}, + {ERROR_REPARSE_TAG_INVALID, errc::invalid_argument}, + {ERROR_RETRY, errc::resource_unavailable_try_again}, + {ERROR_SEEK, errc::io_error}, + {ERROR_SHARING_VIOLATION, errc::permission_denied}, + {ERROR_TOO_MANY_OPEN_FILES, errc::too_many_files_open}, + {ERROR_WRITE_FAULT, errc::io_error}, + {ERROR_WRITE_PROTECT, errc::permission_denied}, + }; + + for (const auto &pair : win_error_mapping) + if (pair.win == static_cast<DWORD>(err)) + return pair.errc; + return errc::invalid_argument; +} + +} // namespace detail +#endif + +namespace detail { +namespace { + +using value_type = path::value_type; +using string_type = path::string_type; + +struct FileDescriptor { + const path& name; + int fd = -1; + StatT m_stat; + file_status m_status; + + template <class... Args> + static FileDescriptor create(const path* p, error_code& ec, Args... args) { + ec.clear(); + int fd; + if ((fd = detail::open(p->c_str(), args...)) == -1) { + ec = capture_errno(); + return FileDescriptor{p}; + } + return FileDescriptor(p, fd); + } + + template <class... Args> + static FileDescriptor create_with_status(const path* p, error_code& ec, + Args... args) { + FileDescriptor fd = create(p, ec, args...); + if (!ec) + fd.refresh_status(ec); + + return fd; + } + + file_status get_status() const { return m_status; } + StatT const& get_stat() const { return m_stat; } + + bool status_known() const { return _VSTD_FS::status_known(m_status); } + + file_status refresh_status(error_code& ec); + + void close() noexcept { + if (fd != -1) + detail::close(fd); + fd = -1; + } + + FileDescriptor(FileDescriptor&& other) + : name(other.name), fd(other.fd), m_stat(other.m_stat), + m_status(other.m_status) { + other.fd = -1; + other.m_status = file_status{}; + } + + ~FileDescriptor() { close(); } + + FileDescriptor(FileDescriptor const&) = delete; + FileDescriptor& operator=(FileDescriptor const&) = delete; + +private: + explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {} +}; + +perms posix_get_perms(const StatT& st) noexcept { + return static_cast<perms>(st.st_mode) & perms::mask; +} + +file_status create_file_status(error_code& m_ec, path const& p, + const StatT& path_stat, error_code* ec) { + if (ec) + *ec = m_ec; + if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { + return file_status(file_type::not_found); + } else if (m_ec) { + ErrorHandler<void> err("posix_stat", ec, &p); + err.report(m_ec, "failed to determine attributes for the specified path"); + return file_status(file_type::none); + } + // else + + file_status fs_tmp; + auto const mode = path_stat.st_mode; + if (S_ISLNK(mode)) + fs_tmp.type(file_type::symlink); + else if (S_ISREG(mode)) + fs_tmp.type(file_type::regular); + else if (S_ISDIR(mode)) + fs_tmp.type(file_type::directory); + else if (S_ISBLK(mode)) + fs_tmp.type(file_type::block); + else if (S_ISCHR(mode)) + fs_tmp.type(file_type::character); + else if (S_ISFIFO(mode)) + fs_tmp.type(file_type::fifo); + else if (S_ISSOCK(mode)) + fs_tmp.type(file_type::socket); + else + fs_tmp.type(file_type::unknown); + + fs_tmp.permissions(detail::posix_get_perms(path_stat)); + return fs_tmp; +} + +file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) { + error_code m_ec; + if (detail::stat(p.c_str(), &path_stat) == -1) + m_ec = detail::capture_errno(); + return create_file_status(m_ec, p, path_stat, ec); +} + +file_status posix_stat(path const& p, error_code* ec) { + StatT path_stat; + return posix_stat(p, path_stat, ec); +} + +file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) { + error_code m_ec; + if (detail::lstat(p.c_str(), &path_stat) == -1) + m_ec = detail::capture_errno(); + return create_file_status(m_ec, p, path_stat, ec); +} + +file_status posix_lstat(path const& p, error_code* ec) { + StatT path_stat; + return posix_lstat(p, path_stat, ec); +} + // http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html bool posix_ftruncate(const FileDescriptor& fd, off_t to_size, error_code& ec) { - if (detail::ftruncate(fd.fd, to_size) == -1) { - ec = capture_errno(); - return true; - } - ec.clear(); - return false; -} - -bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) { - if (detail::fchmod(fd.fd, st.st_mode) == -1) { - ec = capture_errno(); - return true; - } - ec.clear(); - return false; -} - -bool stat_equivalent(const StatT& st1, const StatT& st2) { - return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); -} - -file_status FileDescriptor::refresh_status(error_code& ec) { - // FD must be open and good. - m_status = file_status{}; - m_stat = {}; - error_code m_ec; - if (detail::fstat(fd, &m_stat) == -1) - m_ec = capture_errno(); - m_status = create_file_status(m_ec, name, m_stat, &ec); - return m_status; -} -} // namespace -} // end namespace detail - -using detail::capture_errno; -using detail::ErrorHandler; -using detail::StatT; -using detail::TimeSpec; -using parser::createView; -using parser::PathParser; -using parser::string_view_t; - -const bool _FilesystemClock::is_steady; - -_FilesystemClock::time_point _FilesystemClock::now() noexcept { - typedef chrono::duration<rep> __secs; -#if defined(_LIBCPP_WIN32API) - typedef chrono::duration<rep, nano> __nsecs; - FILETIME time; - GetSystemTimeAsFileTime(&time); - TimeSpec tp = detail::filetime_to_timespec(time); - return time_point(__secs(tp.tv_sec) + - chrono::duration_cast<duration>(__nsecs(tp.tv_nsec))); -#elif defined(CLOCK_REALTIME) - typedef chrono::duration<rep, nano> __nsecs; - struct timespec tp; - if (0 != clock_gettime(CLOCK_REALTIME, &tp)) - __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); - return time_point(__secs(tp.tv_sec) + - chrono::duration_cast<duration>(__nsecs(tp.tv_nsec))); -#else - typedef chrono::duration<rep, micro> __microsecs; - timeval tv; - gettimeofday(&tv, 0); - return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec)); -#endif // CLOCK_REALTIME -} - -filesystem_error::~filesystem_error() {} - -void filesystem_error::__create_what(int __num_paths) { - const char* derived_what = system_error::what(); - __storage_->__what_ = [&]() -> string { - switch (__num_paths) { - case 0: - return detail::format_string("filesystem error: %s", derived_what); - case 1: - return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "]", - derived_what, path1().c_str()); - case 2: - return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "] [" PATH_CSTR_FMT "]", - derived_what, path1().c_str(), path2().c_str()); - } - _LIBCPP_UNREACHABLE(); - }(); -} - -static path __do_absolute(const path& p, path* cwd, error_code* ec) { - if (ec) - ec->clear(); - if (p.is_absolute()) - return p; - *cwd = __current_path(ec); - if (ec && *ec) - return {}; - return (*cwd) / p; -} - -path __absolute(const path& p, error_code* ec) { - path cwd; - return __do_absolute(p, &cwd, ec); -} - -path __canonical(path const& orig_p, error_code* ec) { - path cwd; - ErrorHandler<path> err("canonical", ec, &orig_p, &cwd); - - path p = __do_absolute(orig_p, &cwd, ec); -#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || defined(_LIBCPP_WIN32API) - std::unique_ptr<path::value_type, decltype(&::free)> - hold(detail::realpath(p.c_str(), nullptr), &::free); + if (detail::ftruncate(fd.fd, to_size) == -1) { + ec = capture_errno(); + return true; + } + ec.clear(); + return false; +} + +bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) { + if (detail::fchmod(fd.fd, st.st_mode) == -1) { + ec = capture_errno(); + return true; + } + ec.clear(); + return false; +} + +bool stat_equivalent(const StatT& st1, const StatT& st2) { + return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); +} + +file_status FileDescriptor::refresh_status(error_code& ec) { + // FD must be open and good. + m_status = file_status{}; + m_stat = {}; + error_code m_ec; + if (detail::fstat(fd, &m_stat) == -1) + m_ec = capture_errno(); + m_status = create_file_status(m_ec, name, m_stat, &ec); + return m_status; +} +} // namespace +} // end namespace detail + +using detail::capture_errno; +using detail::ErrorHandler; +using detail::StatT; +using detail::TimeSpec; +using parser::createView; +using parser::PathParser; +using parser::string_view_t; + +const bool _FilesystemClock::is_steady; + +_FilesystemClock::time_point _FilesystemClock::now() noexcept { + typedef chrono::duration<rep> __secs; +#if defined(_LIBCPP_WIN32API) + typedef chrono::duration<rep, nano> __nsecs; + FILETIME time; + GetSystemTimeAsFileTime(&time); + TimeSpec tp = detail::filetime_to_timespec(time); + return time_point(__secs(tp.tv_sec) + + chrono::duration_cast<duration>(__nsecs(tp.tv_nsec))); +#elif defined(CLOCK_REALTIME) + typedef chrono::duration<rep, nano> __nsecs; + struct timespec tp; + if (0 != clock_gettime(CLOCK_REALTIME, &tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); + return time_point(__secs(tp.tv_sec) + + chrono::duration_cast<duration>(__nsecs(tp.tv_nsec))); +#else + typedef chrono::duration<rep, micro> __microsecs; + timeval tv; + gettimeofday(&tv, 0); + return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec)); +#endif // CLOCK_REALTIME +} + +filesystem_error::~filesystem_error() {} + +void filesystem_error::__create_what(int __num_paths) { + const char* derived_what = system_error::what(); + __storage_->__what_ = [&]() -> string { + switch (__num_paths) { + case 0: + return detail::format_string("filesystem error: %s", derived_what); + case 1: + return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "]", + derived_what, path1().c_str()); + case 2: + return detail::format_string("filesystem error: %s [" PATH_CSTR_FMT "] [" PATH_CSTR_FMT "]", + derived_what, path1().c_str(), path2().c_str()); + } + _LIBCPP_UNREACHABLE(); + }(); +} + +static path __do_absolute(const path& p, path* cwd, error_code* ec) { + if (ec) + ec->clear(); + if (p.is_absolute()) + return p; + *cwd = __current_path(ec); + if (ec && *ec) + return {}; + return (*cwd) / p; +} + +path __absolute(const path& p, error_code* ec) { + path cwd; + return __do_absolute(p, &cwd, ec); +} + +path __canonical(path const& orig_p, error_code* ec) { + path cwd; + ErrorHandler<path> err("canonical", ec, &orig_p, &cwd); + + path p = __do_absolute(orig_p, &cwd, ec); +#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || defined(_LIBCPP_WIN32API) + std::unique_ptr<path::value_type, decltype(&::free)> + hold(detail::realpath(p.c_str(), nullptr), &::free); if (hold.get() == nullptr) return err.report(capture_errno()); return {hold.get()}; #else - #if defined(__MVS__) && !defined(PATH_MAX) - path::value_type buff[ _XOPEN_PATH_MAX + 1 ]; - #else - path::value_type buff[PATH_MAX + 1]; - #endif - path::value_type* ret; - if ((ret = detail::realpath(p.c_str(), buff)) == nullptr) - return err.report(capture_errno()); - return {ret}; + #if defined(__MVS__) && !defined(PATH_MAX) + path::value_type buff[ _XOPEN_PATH_MAX + 1 ]; + #else + path::value_type buff[PATH_MAX + 1]; + #endif + path::value_type* ret; + if ((ret = detail::realpath(p.c_str(), buff)) == nullptr) + return err.report(capture_errno()); + return {ret}; +#endif +} + +void __copy(const path& from, const path& to, copy_options options, + error_code* ec) { + ErrorHandler<void> err("copy", ec, &from, &to); + + const bool sym_status = bool( + options & (copy_options::create_symlinks | copy_options::skip_symlinks)); + + const bool sym_status2 = bool(options & copy_options::copy_symlinks); + + error_code m_ec1; + StatT f_st = {}; + const file_status f = sym_status || sym_status2 + ? detail::posix_lstat(from, f_st, &m_ec1) + : detail::posix_stat(from, f_st, &m_ec1); + if (m_ec1) + return err.report(m_ec1); + + StatT t_st = {}; + const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1) + : detail::posix_stat(to, t_st, &m_ec1); + + if (not status_known(t)) + return err.report(m_ec1); + + if (!exists(f) || is_other(f) || is_other(t) || + (is_directory(f) && is_regular_file(t)) || + detail::stat_equivalent(f_st, t_st)) { + return err.report(errc::function_not_supported); + } + + if (ec) + ec->clear(); + + if (is_symlink(f)) { + if (bool(copy_options::skip_symlinks & options)) { + // do nothing + } else if (not exists(t)) { + __copy_symlink(from, to, ec); + } else { + return err.report(errc::file_exists); + } + return; + } else if (is_regular_file(f)) { + if (bool(copy_options::directories_only & options)) { + // do nothing + } else if (bool(copy_options::create_symlinks & options)) { + __create_symlink(from, to, ec); + } else if (bool(copy_options::create_hard_links & options)) { + __create_hard_link(from, to, ec); + } else if (is_directory(t)) { + __copy_file(from, to / from.filename(), options, ec); + } else { + __copy_file(from, to, options, ec); + } + return; + } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) { + return err.report(errc::is_a_directory); + } else if (is_directory(f) && (bool(copy_options::recursive & options) || + copy_options::none == options)) { + + if (!exists(t)) { + // create directory to with attributes from 'from'. + __create_directory(to, from, ec); + if (ec && *ec) { + return; + } + } + directory_iterator it = + ec ? directory_iterator(from, *ec) : directory_iterator(from); + if (ec && *ec) { + return; + } + error_code m_ec2; + for (; it != directory_iterator(); it.increment(m_ec2)) { + if (m_ec2) { + return err.report(m_ec2); + } + __copy(it->path(), to / it->path().filename(), + options | copy_options::__in_recursive_copy, ec); + if (ec && *ec) { + return; + } + } + } +} + +namespace detail { +namespace { + +#if defined(_LIBCPP_FILESYSTEM_USE_SENDFILE) + bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { + size_t count = read_fd.get_stat().st_size; + do { + ssize_t res; + if ((res = ::sendfile(write_fd.fd, read_fd.fd, nullptr, count)) == -1) { + ec = capture_errno(); + return false; + } + count -= res; + } while (count > 0); + + ec.clear(); + + return true; + } +#elif defined(_LIBCPP_FILESYSTEM_USE_COPYFILE) + bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { + struct CopyFileState { + copyfile_state_t state; + CopyFileState() { state = copyfile_state_alloc(); } + ~CopyFileState() { copyfile_state_free(state); } + + private: + CopyFileState(CopyFileState const&) = delete; + CopyFileState& operator=(CopyFileState const&) = delete; + }; + + CopyFileState cfs; + if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) { + ec = capture_errno(); + return false; + } + + ec.clear(); + return true; + } +#elif defined(_LIBCPP_FILESYSTEM_USE_FSTREAM) + bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { + ifstream in; + in.__open(read_fd.fd, ios::binary); + if (!in.is_open()) { + // This assumes that __open didn't reset the error code. + ec = capture_errno(); + return false; + } + read_fd.fd = -1; + ofstream out; + out.__open(write_fd.fd, ios::binary); + if (!out.is_open()) { + ec = capture_errno(); + return false; + } + write_fd.fd = -1; + + if (in.good() && out.good()) { + using InIt = istreambuf_iterator<char>; + using OutIt = ostreambuf_iterator<char>; + InIt bin(in); + InIt ein; + OutIt bout(out); + copy(bin, ein, bout); + } + if (out.fail() || in.fail()) { + ec = make_error_code(errc::io_error); + return false; + } + + ec.clear(); + return true; + } +#else +# error "Unknown implementation for copy_file_impl" +#endif // copy_file_impl implementation + +} // end anonymous namespace +} // end namespace detail + +bool __copy_file(const path& from, const path& to, copy_options options, + error_code* ec) { + using detail::FileDescriptor; + ErrorHandler<bool> err("copy_file", ec, &to, &from); + + error_code m_ec; + FileDescriptor from_fd = FileDescriptor::create_with_status( + &from, m_ec, O_RDONLY | O_NONBLOCK | O_BINARY); + if (m_ec) + return err.report(m_ec); + + auto from_st = from_fd.get_status(); + StatT const& from_stat = from_fd.get_stat(); + if (!is_regular_file(from_st)) { + if (not m_ec) + m_ec = make_error_code(errc::not_supported); + return err.report(m_ec); + } + + const bool skip_existing = bool(copy_options::skip_existing & options); + const bool update_existing = bool(copy_options::update_existing & options); + const bool overwrite_existing = + bool(copy_options::overwrite_existing & options); + + StatT to_stat_path; + file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec); + if (!status_known(to_st)) + return err.report(m_ec); + + const bool to_exists = exists(to_st); + if (to_exists && !is_regular_file(to_st)) + return err.report(errc::not_supported); + + if (to_exists && detail::stat_equivalent(from_stat, to_stat_path)) + return err.report(errc::file_exists); + + if (to_exists && skip_existing) + return false; + + bool ShouldCopy = [&]() { + if (to_exists && update_existing) { + auto from_time = detail::extract_mtime(from_stat); + auto to_time = detail::extract_mtime(to_stat_path); + if (from_time.tv_sec < to_time.tv_sec) + return false; + if (from_time.tv_sec == to_time.tv_sec && + from_time.tv_nsec <= to_time.tv_nsec) + return false; + return true; + } + if (!to_exists || overwrite_existing) + return true; + return err.report(errc::file_exists); + }(); + if (!ShouldCopy) + return false; + + // Don't truncate right away. We may not be opening the file we originally + // looked at; we'll check this later. + int to_open_flags = O_WRONLY | O_BINARY; + if (!to_exists) + to_open_flags |= O_CREAT; + FileDescriptor to_fd = FileDescriptor::create_with_status( + &to, m_ec, to_open_flags, from_stat.st_mode); + if (m_ec) + return err.report(m_ec); + + if (to_exists) { + // Check that the file we initially stat'ed is equivalent to the one + // we opened. + // FIXME: report this better. + if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat())) + return err.report(errc::bad_file_descriptor); + + // Set the permissions and truncate the file we opened. + if (detail::posix_fchmod(to_fd, from_stat, m_ec)) + return err.report(m_ec); + if (detail::posix_ftruncate(to_fd, 0, m_ec)) + return err.report(m_ec); + } + + if (!copy_file_impl(from_fd, to_fd, m_ec)) { + // FIXME: Remove the dest file if we failed, and it didn't exist previously. + return err.report(m_ec); + } + + return true; +} + +void __copy_symlink(const path& existing_symlink, const path& new_symlink, + error_code* ec) { + const path real_path(__read_symlink(existing_symlink, ec)); + if (ec && *ec) { + return; + } +#if defined(_LIBCPP_WIN32API) + error_code local_ec; + if (is_directory(real_path, local_ec)) + __create_directory_symlink(real_path, new_symlink, ec); + else +#endif + __create_symlink(real_path, new_symlink, ec); +} + +bool __create_directories(const path& p, error_code* ec) { + ErrorHandler<bool> err("create_directories", ec, &p); + + error_code m_ec; + auto const st = detail::posix_stat(p, &m_ec); + if (!status_known(st)) + return err.report(m_ec); + else if (is_directory(st)) + return false; + else if (exists(st)) + return err.report(errc::file_exists); + + const path parent = p.parent_path(); + if (!parent.empty()) { + const file_status parent_st = status(parent, m_ec); + if (not status_known(parent_st)) + return err.report(m_ec); + if (not exists(parent_st)) { + if (parent == p) + return err.report(errc::invalid_argument); + __create_directories(parent, ec); + if (ec && *ec) { + return false; + } + } else if (not is_directory(parent_st)) + return err.report(errc::not_a_directory); + } + bool ret = __create_directory(p, &m_ec); + if (m_ec) + return err.report(m_ec); + return ret; +} + +bool __create_directory(const path& p, error_code* ec) { + ErrorHandler<bool> err("create_directory", ec, &p); + + if (detail::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0) + return true; + + if (errno != EEXIST) + return err.report(capture_errno()); + error_code mec = capture_errno(); + error_code ignored_ec; + const file_status st = status(p, ignored_ec); + if (!is_directory(st)) + return err.report(mec); + return false; +} + +bool __create_directory(path const& p, path const& attributes, error_code* ec) { + ErrorHandler<bool> err("create_directory", ec, &p, &attributes); + + StatT attr_stat; + error_code mec; + file_status st = detail::posix_stat(attributes, attr_stat, &mec); + if (!status_known(st)) + return err.report(mec); + if (!is_directory(st)) + return err.report(errc::not_a_directory, + "the specified attribute path is invalid"); + + if (detail::mkdir(p.c_str(), attr_stat.st_mode) == 0) + return true; + + if (errno != EEXIST) + return err.report(capture_errno()); + + mec = capture_errno(); + error_code ignored_ec; + st = status(p, ignored_ec); + if (!is_directory(st)) + return err.report(mec); + return false; +} + +void __create_directory_symlink(path const& from, path const& to, + error_code* ec) { + ErrorHandler<void> err("create_directory_symlink", ec, &from, &to); + if (detail::symlink_dir(from.c_str(), to.c_str()) == -1) + return err.report(capture_errno()); +} + +void __create_hard_link(const path& from, const path& to, error_code* ec) { + ErrorHandler<void> err("create_hard_link", ec, &from, &to); + if (detail::link(from.c_str(), to.c_str()) == -1) + return err.report(capture_errno()); +} + +void __create_symlink(path const& from, path const& to, error_code* ec) { + ErrorHandler<void> err("create_symlink", ec, &from, &to); + if (detail::symlink_file(from.c_str(), to.c_str()) == -1) + return err.report(capture_errno()); +} + +path __current_path(error_code* ec) { + ErrorHandler<path> err("current_path", ec); + +#if defined(_LIBCPP_WIN32API) || defined(__GLIBC__) || defined(__APPLE__) + // Common extension outside of POSIX getcwd() spec, without needing to + // preallocate a buffer. Also supported by a number of other POSIX libcs. + int size = 0; + path::value_type* ptr = nullptr; + typedef decltype(&::free) Deleter; + Deleter deleter = &::free; +#else + auto size = ::pathconf(".", _PC_PATH_MAX); + _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size"); + + auto buff = unique_ptr<path::value_type[]>(new path::value_type[size + 1]); + path::value_type* ptr = buff.get(); + + // Preallocated buffer, don't free the buffer in the second unique_ptr + // below. + struct Deleter { void operator()(void*) const {} }; + Deleter deleter; +#endif + + unique_ptr<path::value_type, Deleter> hold(detail::getcwd(ptr, size), + deleter); + if (hold.get() == nullptr) + return err.report(capture_errno(), "call to getcwd failed"); + + return {hold.get()}; +} + +void __current_path(const path& p, error_code* ec) { + ErrorHandler<void> err("current_path", ec, &p); + if (detail::chdir(p.c_str()) == -1) + err.report(capture_errno()); +} + +bool __equivalent(const path& p1, const path& p2, error_code* ec) { + ErrorHandler<bool> err("equivalent", ec, &p1, &p2); + + error_code ec1, ec2; + StatT st1 = {}, st2 = {}; + auto s1 = detail::posix_stat(p1.native(), st1, &ec1); + if (!exists(s1)) + return err.report(errc::not_supported); + auto s2 = detail::posix_stat(p2.native(), st2, &ec2); + if (!exists(s2)) + return err.report(errc::not_supported); + + return detail::stat_equivalent(st1, st2); +} + +uintmax_t __file_size(const path& p, error_code* ec) { + ErrorHandler<uintmax_t> err("file_size", ec, &p); + + error_code m_ec; + StatT st; + file_status fst = detail::posix_stat(p, st, &m_ec); + if (!exists(fst) || !is_regular_file(fst)) { + errc error_kind = + is_directory(fst) ? errc::is_a_directory : errc::not_supported; + if (!m_ec) + m_ec = make_error_code(error_kind); + return err.report(m_ec); + } + // is_regular_file(p) == true + return static_cast<uintmax_t>(st.st_size); +} + +uintmax_t __hard_link_count(const path& p, error_code* ec) { + ErrorHandler<uintmax_t> err("hard_link_count", ec, &p); + + error_code m_ec; + StatT st; + detail::posix_stat(p, st, &m_ec); + if (m_ec) + return err.report(m_ec); + return static_cast<uintmax_t>(st.st_nlink); +} + +bool __fs_is_empty(const path& p, error_code* ec) { + ErrorHandler<bool> err("is_empty", ec, &p); + + error_code m_ec; + StatT pst; + auto st = detail::posix_stat(p, pst, &m_ec); + if (m_ec) + return err.report(m_ec); + else if (!is_directory(st) && !is_regular_file(st)) + return err.report(errc::not_supported); + else if (is_directory(st)) { + auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p); + if (ec && *ec) + return false; + return it == directory_iterator{}; + } else if (is_regular_file(st)) + return static_cast<uintmax_t>(pst.st_size) == 0; + + _LIBCPP_UNREACHABLE(); +} + +static file_time_type __extract_last_write_time(const path& p, const StatT& st, + error_code* ec) { + using detail::fs_time; + ErrorHandler<file_time_type> err("last_write_time", ec, &p); + + auto ts = detail::extract_mtime(st); + if (!fs_time::is_representable(ts)) + return err.report(errc::value_too_large); + + return fs_time::convert_from_timespec(ts); +} + +file_time_type __last_write_time(const path& p, error_code* ec) { + using namespace chrono; + ErrorHandler<file_time_type> err("last_write_time", ec, &p); + + error_code m_ec; + StatT st; + detail::posix_stat(p, st, &m_ec); + if (m_ec) + return err.report(m_ec); + return __extract_last_write_time(p, st, ec); +} + +void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { + using detail::fs_time; + ErrorHandler<void> err("last_write_time", ec, &p); + +#if defined(_LIBCPP_WIN32API) + TimeSpec ts; + if (!fs_time::convert_to_timespec(ts, new_time)) + return err.report(errc::value_too_large); + detail::WinHandle h(p.c_str(), FILE_WRITE_ATTRIBUTES, 0); + if (!h) + return err.report(detail::make_windows_error(GetLastError())); + FILETIME last_write = timespec_to_filetime(ts); + if (!SetFileTime(h, nullptr, nullptr, &last_write)) + return err.report(detail::make_windows_error(GetLastError())); +#else + error_code m_ec; + array<TimeSpec, 2> tbuf; +#if !defined(_LIBCPP_USE_UTIMENSAT) + // This implementation has a race condition between determining the + // last access time and attempting to set it to the same value using + // ::utimes + StatT st; + file_status fst = detail::posix_stat(p, st, &m_ec); + if (m_ec) + return err.report(m_ec); + tbuf[0] = detail::extract_atime(st); +#else + tbuf[0].tv_sec = 0; + tbuf[0].tv_nsec = UTIME_OMIT; #endif -} - -void __copy(const path& from, const path& to, copy_options options, - error_code* ec) { - ErrorHandler<void> err("copy", ec, &from, &to); - - const bool sym_status = bool( - options & (copy_options::create_symlinks | copy_options::skip_symlinks)); - - const bool sym_status2 = bool(options & copy_options::copy_symlinks); - - error_code m_ec1; - StatT f_st = {}; - const file_status f = sym_status || sym_status2 - ? detail::posix_lstat(from, f_st, &m_ec1) - : detail::posix_stat(from, f_st, &m_ec1); - if (m_ec1) - return err.report(m_ec1); - - StatT t_st = {}; - const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1) - : detail::posix_stat(to, t_st, &m_ec1); - - if (not status_known(t)) - return err.report(m_ec1); - - if (!exists(f) || is_other(f) || is_other(t) || - (is_directory(f) && is_regular_file(t)) || - detail::stat_equivalent(f_st, t_st)) { - return err.report(errc::function_not_supported); - } - - if (ec) - ec->clear(); - - if (is_symlink(f)) { - if (bool(copy_options::skip_symlinks & options)) { - // do nothing - } else if (not exists(t)) { - __copy_symlink(from, to, ec); - } else { - return err.report(errc::file_exists); - } - return; - } else if (is_regular_file(f)) { - if (bool(copy_options::directories_only & options)) { - // do nothing - } else if (bool(copy_options::create_symlinks & options)) { - __create_symlink(from, to, ec); - } else if (bool(copy_options::create_hard_links & options)) { - __create_hard_link(from, to, ec); - } else if (is_directory(t)) { - __copy_file(from, to / from.filename(), options, ec); - } else { - __copy_file(from, to, options, ec); - } - return; - } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) { - return err.report(errc::is_a_directory); - } else if (is_directory(f) && (bool(copy_options::recursive & options) || - copy_options::none == options)) { - - if (!exists(t)) { - // create directory to with attributes from 'from'. - __create_directory(to, from, ec); - if (ec && *ec) { - return; - } - } - directory_iterator it = - ec ? directory_iterator(from, *ec) : directory_iterator(from); - if (ec && *ec) { - return; - } - error_code m_ec2; - for (; it != directory_iterator(); it.increment(m_ec2)) { - if (m_ec2) { - return err.report(m_ec2); - } - __copy(it->path(), to / it->path().filename(), - options | copy_options::__in_recursive_copy, ec); - if (ec && *ec) { - return; - } - } - } -} - -namespace detail { -namespace { - -#if defined(_LIBCPP_FILESYSTEM_USE_SENDFILE) - bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { - size_t count = read_fd.get_stat().st_size; - do { - ssize_t res; - if ((res = ::sendfile(write_fd.fd, read_fd.fd, nullptr, count)) == -1) { - ec = capture_errno(); - return false; - } - count -= res; - } while (count > 0); - - ec.clear(); - - return true; - } -#elif defined(_LIBCPP_FILESYSTEM_USE_COPYFILE) - bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { - struct CopyFileState { - copyfile_state_t state; - CopyFileState() { state = copyfile_state_alloc(); } - ~CopyFileState() { copyfile_state_free(state); } - - private: - CopyFileState(CopyFileState const&) = delete; - CopyFileState& operator=(CopyFileState const&) = delete; - }; - - CopyFileState cfs; - if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) { - ec = capture_errno(); - return false; - } - - ec.clear(); - return true; - } -#elif defined(_LIBCPP_FILESYSTEM_USE_FSTREAM) - bool copy_file_impl(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { - ifstream in; - in.__open(read_fd.fd, ios::binary); - if (!in.is_open()) { - // This assumes that __open didn't reset the error code. - ec = capture_errno(); - return false; - } - read_fd.fd = -1; - ofstream out; - out.__open(write_fd.fd, ios::binary); - if (!out.is_open()) { - ec = capture_errno(); - return false; - } - write_fd.fd = -1; - - if (in.good() && out.good()) { - using InIt = istreambuf_iterator<char>; - using OutIt = ostreambuf_iterator<char>; - InIt bin(in); - InIt ein; - OutIt bout(out); - copy(bin, ein, bout); - } - if (out.fail() || in.fail()) { - ec = make_error_code(errc::io_error); - return false; - } - - ec.clear(); - return true; - } -#else -# error "Unknown implementation for copy_file_impl" -#endif // copy_file_impl implementation - -} // end anonymous namespace -} // end namespace detail - -bool __copy_file(const path& from, const path& to, copy_options options, - error_code* ec) { - using detail::FileDescriptor; - ErrorHandler<bool> err("copy_file", ec, &to, &from); - - error_code m_ec; - FileDescriptor from_fd = FileDescriptor::create_with_status( - &from, m_ec, O_RDONLY | O_NONBLOCK | O_BINARY); - if (m_ec) - return err.report(m_ec); - - auto from_st = from_fd.get_status(); - StatT const& from_stat = from_fd.get_stat(); - if (!is_regular_file(from_st)) { - if (not m_ec) - m_ec = make_error_code(errc::not_supported); - return err.report(m_ec); - } - - const bool skip_existing = bool(copy_options::skip_existing & options); - const bool update_existing = bool(copy_options::update_existing & options); - const bool overwrite_existing = - bool(copy_options::overwrite_existing & options); - - StatT to_stat_path; - file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec); - if (!status_known(to_st)) - return err.report(m_ec); - - const bool to_exists = exists(to_st); - if (to_exists && !is_regular_file(to_st)) - return err.report(errc::not_supported); - - if (to_exists && detail::stat_equivalent(from_stat, to_stat_path)) - return err.report(errc::file_exists); - - if (to_exists && skip_existing) - return false; - - bool ShouldCopy = [&]() { - if (to_exists && update_existing) { - auto from_time = detail::extract_mtime(from_stat); - auto to_time = detail::extract_mtime(to_stat_path); - if (from_time.tv_sec < to_time.tv_sec) - return false; - if (from_time.tv_sec == to_time.tv_sec && - from_time.tv_nsec <= to_time.tv_nsec) - return false; - return true; - } - if (!to_exists || overwrite_existing) - return true; - return err.report(errc::file_exists); - }(); - if (!ShouldCopy) - return false; - - // Don't truncate right away. We may not be opening the file we originally - // looked at; we'll check this later. - int to_open_flags = O_WRONLY | O_BINARY; - if (!to_exists) - to_open_flags |= O_CREAT; - FileDescriptor to_fd = FileDescriptor::create_with_status( - &to, m_ec, to_open_flags, from_stat.st_mode); - if (m_ec) - return err.report(m_ec); - - if (to_exists) { - // Check that the file we initially stat'ed is equivalent to the one - // we opened. - // FIXME: report this better. - if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat())) - return err.report(errc::bad_file_descriptor); - - // Set the permissions and truncate the file we opened. - if (detail::posix_fchmod(to_fd, from_stat, m_ec)) - return err.report(m_ec); - if (detail::posix_ftruncate(to_fd, 0, m_ec)) - return err.report(m_ec); - } - - if (!copy_file_impl(from_fd, to_fd, m_ec)) { - // FIXME: Remove the dest file if we failed, and it didn't exist previously. - return err.report(m_ec); - } - - return true; -} - -void __copy_symlink(const path& existing_symlink, const path& new_symlink, - error_code* ec) { - const path real_path(__read_symlink(existing_symlink, ec)); - if (ec && *ec) { - return; - } -#if defined(_LIBCPP_WIN32API) - error_code local_ec; - if (is_directory(real_path, local_ec)) - __create_directory_symlink(real_path, new_symlink, ec); - else -#endif - __create_symlink(real_path, new_symlink, ec); -} - -bool __create_directories(const path& p, error_code* ec) { - ErrorHandler<bool> err("create_directories", ec, &p); - - error_code m_ec; - auto const st = detail::posix_stat(p, &m_ec); - if (!status_known(st)) - return err.report(m_ec); - else if (is_directory(st)) - return false; - else if (exists(st)) - return err.report(errc::file_exists); - - const path parent = p.parent_path(); - if (!parent.empty()) { - const file_status parent_st = status(parent, m_ec); - if (not status_known(parent_st)) - return err.report(m_ec); - if (not exists(parent_st)) { - if (parent == p) - return err.report(errc::invalid_argument); - __create_directories(parent, ec); - if (ec && *ec) { - return false; - } - } else if (not is_directory(parent_st)) - return err.report(errc::not_a_directory); - } - bool ret = __create_directory(p, &m_ec); - if (m_ec) - return err.report(m_ec); - return ret; -} - -bool __create_directory(const path& p, error_code* ec) { - ErrorHandler<bool> err("create_directory", ec, &p); - - if (detail::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0) - return true; - - if (errno != EEXIST) - return err.report(capture_errno()); - error_code mec = capture_errno(); - error_code ignored_ec; - const file_status st = status(p, ignored_ec); - if (!is_directory(st)) - return err.report(mec); - return false; -} - -bool __create_directory(path const& p, path const& attributes, error_code* ec) { - ErrorHandler<bool> err("create_directory", ec, &p, &attributes); - - StatT attr_stat; - error_code mec; - file_status st = detail::posix_stat(attributes, attr_stat, &mec); - if (!status_known(st)) - return err.report(mec); - if (!is_directory(st)) - return err.report(errc::not_a_directory, - "the specified attribute path is invalid"); - - if (detail::mkdir(p.c_str(), attr_stat.st_mode) == 0) - return true; - - if (errno != EEXIST) - return err.report(capture_errno()); - - mec = capture_errno(); - error_code ignored_ec; - st = status(p, ignored_ec); - if (!is_directory(st)) - return err.report(mec); - return false; -} - -void __create_directory_symlink(path const& from, path const& to, - error_code* ec) { - ErrorHandler<void> err("create_directory_symlink", ec, &from, &to); - if (detail::symlink_dir(from.c_str(), to.c_str()) == -1) - return err.report(capture_errno()); -} - -void __create_hard_link(const path& from, const path& to, error_code* ec) { - ErrorHandler<void> err("create_hard_link", ec, &from, &to); - if (detail::link(from.c_str(), to.c_str()) == -1) - return err.report(capture_errno()); -} - -void __create_symlink(path const& from, path const& to, error_code* ec) { - ErrorHandler<void> err("create_symlink", ec, &from, &to); - if (detail::symlink_file(from.c_str(), to.c_str()) == -1) - return err.report(capture_errno()); -} - -path __current_path(error_code* ec) { - ErrorHandler<path> err("current_path", ec); - -#if defined(_LIBCPP_WIN32API) || defined(__GLIBC__) || defined(__APPLE__) - // Common extension outside of POSIX getcwd() spec, without needing to - // preallocate a buffer. Also supported by a number of other POSIX libcs. - int size = 0; - path::value_type* ptr = nullptr; - typedef decltype(&::free) Deleter; - Deleter deleter = &::free; -#else - auto size = ::pathconf(".", _PC_PATH_MAX); - _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size"); - - auto buff = unique_ptr<path::value_type[]>(new path::value_type[size + 1]); - path::value_type* ptr = buff.get(); - - // Preallocated buffer, don't free the buffer in the second unique_ptr - // below. - struct Deleter { void operator()(void*) const {} }; - Deleter deleter; -#endif - - unique_ptr<path::value_type, Deleter> hold(detail::getcwd(ptr, size), - deleter); - if (hold.get() == nullptr) - return err.report(capture_errno(), "call to getcwd failed"); - - return {hold.get()}; -} - -void __current_path(const path& p, error_code* ec) { - ErrorHandler<void> err("current_path", ec, &p); - if (detail::chdir(p.c_str()) == -1) - err.report(capture_errno()); -} - -bool __equivalent(const path& p1, const path& p2, error_code* ec) { - ErrorHandler<bool> err("equivalent", ec, &p1, &p2); - - error_code ec1, ec2; - StatT st1 = {}, st2 = {}; - auto s1 = detail::posix_stat(p1.native(), st1, &ec1); - if (!exists(s1)) - return err.report(errc::not_supported); - auto s2 = detail::posix_stat(p2.native(), st2, &ec2); - if (!exists(s2)) - return err.report(errc::not_supported); - - return detail::stat_equivalent(st1, st2); -} - -uintmax_t __file_size(const path& p, error_code* ec) { - ErrorHandler<uintmax_t> err("file_size", ec, &p); - - error_code m_ec; - StatT st; - file_status fst = detail::posix_stat(p, st, &m_ec); - if (!exists(fst) || !is_regular_file(fst)) { - errc error_kind = - is_directory(fst) ? errc::is_a_directory : errc::not_supported; - if (!m_ec) - m_ec = make_error_code(error_kind); - return err.report(m_ec); - } - // is_regular_file(p) == true - return static_cast<uintmax_t>(st.st_size); -} - -uintmax_t __hard_link_count(const path& p, error_code* ec) { - ErrorHandler<uintmax_t> err("hard_link_count", ec, &p); - - error_code m_ec; - StatT st; - detail::posix_stat(p, st, &m_ec); - if (m_ec) - return err.report(m_ec); - return static_cast<uintmax_t>(st.st_nlink); -} - -bool __fs_is_empty(const path& p, error_code* ec) { - ErrorHandler<bool> err("is_empty", ec, &p); - - error_code m_ec; - StatT pst; - auto st = detail::posix_stat(p, pst, &m_ec); - if (m_ec) - return err.report(m_ec); - else if (!is_directory(st) && !is_regular_file(st)) - return err.report(errc::not_supported); - else if (is_directory(st)) { - auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p); - if (ec && *ec) - return false; - return it == directory_iterator{}; - } else if (is_regular_file(st)) - return static_cast<uintmax_t>(pst.st_size) == 0; - - _LIBCPP_UNREACHABLE(); -} - -static file_time_type __extract_last_write_time(const path& p, const StatT& st, - error_code* ec) { - using detail::fs_time; - ErrorHandler<file_time_type> err("last_write_time", ec, &p); - - auto ts = detail::extract_mtime(st); - if (!fs_time::is_representable(ts)) - return err.report(errc::value_too_large); - - return fs_time::convert_from_timespec(ts); -} - -file_time_type __last_write_time(const path& p, error_code* ec) { - using namespace chrono; - ErrorHandler<file_time_type> err("last_write_time", ec, &p); - - error_code m_ec; - StatT st; - detail::posix_stat(p, st, &m_ec); - if (m_ec) - return err.report(m_ec); - return __extract_last_write_time(p, st, ec); -} - -void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { - using detail::fs_time; - ErrorHandler<void> err("last_write_time", ec, &p); - -#if defined(_LIBCPP_WIN32API) - TimeSpec ts; - if (!fs_time::convert_to_timespec(ts, new_time)) - return err.report(errc::value_too_large); - detail::WinHandle h(p.c_str(), FILE_WRITE_ATTRIBUTES, 0); - if (!h) - return err.report(detail::make_windows_error(GetLastError())); - FILETIME last_write = timespec_to_filetime(ts); - if (!SetFileTime(h, nullptr, nullptr, &last_write)) - return err.report(detail::make_windows_error(GetLastError())); -#else - error_code m_ec; - array<TimeSpec, 2> tbuf; -#if !defined(_LIBCPP_USE_UTIMENSAT) - // This implementation has a race condition between determining the - // last access time and attempting to set it to the same value using - // ::utimes - StatT st; - file_status fst = detail::posix_stat(p, st, &m_ec); - if (m_ec) - return err.report(m_ec); - tbuf[0] = detail::extract_atime(st); -#else - tbuf[0].tv_sec = 0; - tbuf[0].tv_nsec = UTIME_OMIT; -#endif - if (!fs_time::convert_to_timespec(tbuf[1], new_time)) - return err.report(errc::value_too_large); - - detail::set_file_times(p, tbuf, m_ec); - if (m_ec) - return err.report(m_ec); -#endif -} - -void __permissions(const path& p, perms prms, perm_options opts, - error_code* ec) { - ErrorHandler<void> err("permissions", ec, &p); - - auto has_opt = [&](perm_options o) { return bool(o & opts); }; - const bool resolve_symlinks = !has_opt(perm_options::nofollow); - const bool add_perms = has_opt(perm_options::add); - const bool remove_perms = has_opt(perm_options::remove); - _LIBCPP_ASSERT( - (add_perms + remove_perms + has_opt(perm_options::replace)) == 1, - "One and only one of the perm_options constants replace, add, or remove " - "is present in opts"); - - bool set_sym_perms = false; - prms &= perms::mask; - if (!resolve_symlinks || (add_perms || remove_perms)) { - error_code m_ec; - file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec) - : detail::posix_lstat(p, &m_ec); - set_sym_perms = is_symlink(st); - if (m_ec) - return err.report(m_ec); - _LIBCPP_ASSERT(st.permissions() != perms::unknown, - "Permissions unexpectedly unknown"); - if (add_perms) - prms |= st.permissions(); - else if (remove_perms) - prms = st.permissions() & ~prms; - } - const auto real_perms = static_cast<detail::ModeT>(prms & perms::mask); - -#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) - const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0; - if (detail::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { - return err.report(capture_errno()); - } -#else - if (set_sym_perms) - return err.report(errc::operation_not_supported); - if (::chmod(p.c_str(), real_perms) == -1) { - return err.report(capture_errno()); - } -#endif -} - -path __read_symlink(const path& p, error_code* ec) { - ErrorHandler<path> err("read_symlink", ec, &p); - -#if defined(PATH_MAX) || defined(MAX_SYMLINK_SIZE) + if (!fs_time::convert_to_timespec(tbuf[1], new_time)) + return err.report(errc::value_too_large); + + detail::set_file_times(p, tbuf, m_ec); + if (m_ec) + return err.report(m_ec); +#endif +} + +void __permissions(const path& p, perms prms, perm_options opts, + error_code* ec) { + ErrorHandler<void> err("permissions", ec, &p); + + auto has_opt = [&](perm_options o) { return bool(o & opts); }; + const bool resolve_symlinks = !has_opt(perm_options::nofollow); + const bool add_perms = has_opt(perm_options::add); + const bool remove_perms = has_opt(perm_options::remove); + _LIBCPP_ASSERT( + (add_perms + remove_perms + has_opt(perm_options::replace)) == 1, + "One and only one of the perm_options constants replace, add, or remove " + "is present in opts"); + + bool set_sym_perms = false; + prms &= perms::mask; + if (!resolve_symlinks || (add_perms || remove_perms)) { + error_code m_ec; + file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec) + : detail::posix_lstat(p, &m_ec); + set_sym_perms = is_symlink(st); + if (m_ec) + return err.report(m_ec); + _LIBCPP_ASSERT(st.permissions() != perms::unknown, + "Permissions unexpectedly unknown"); + if (add_perms) + prms |= st.permissions(); + else if (remove_perms) + prms = st.permissions() & ~prms; + } + const auto real_perms = static_cast<detail::ModeT>(prms & perms::mask); + +#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) + const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0; + if (detail::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { + return err.report(capture_errno()); + } +#else + if (set_sym_perms) + return err.report(errc::operation_not_supported); + if (::chmod(p.c_str(), real_perms) == -1) { + return err.report(capture_errno()); + } +#endif +} + +path __read_symlink(const path& p, error_code* ec) { + ErrorHandler<path> err("read_symlink", ec, &p); + +#if defined(PATH_MAX) || defined(MAX_SYMLINK_SIZE) struct NullDeleter { void operator()(void*) const {} }; -#ifdef MAX_SYMLINK_SIZE - const size_t size = MAX_SYMLINK_SIZE + 1; -#else +#ifdef MAX_SYMLINK_SIZE + const size_t size = MAX_SYMLINK_SIZE + 1; +#else const size_t size = PATH_MAX + 1; -#endif - path::value_type stack_buff[size]; - auto buff = std::unique_ptr<path::value_type[], NullDeleter>(stack_buff); +#endif + path::value_type stack_buff[size]; + auto buff = std::unique_ptr<path::value_type[], NullDeleter>(stack_buff); #else StatT sb; - if (detail::lstat(p.c_str(), &sb) == -1) { + if (detail::lstat(p.c_str(), &sb) == -1) { return err.report(capture_errno()); } const size_t size = sb.st_size + 1; - auto buff = unique_ptr<path::value_type[]>(new path::value_type[size]); + auto buff = unique_ptr<path::value_type[]>(new path::value_type[size]); #endif - detail::SSizeT ret; - if ((ret = detail::readlink(p.c_str(), buff.get(), size)) == -1) - return err.report(capture_errno()); - _LIBCPP_ASSERT(ret > 0, "TODO"); + detail::SSizeT ret; + if ((ret = detail::readlink(p.c_str(), buff.get(), size)) == -1) + return err.report(capture_errno()); + _LIBCPP_ASSERT(ret > 0, "TODO"); if (static_cast<size_t>(ret) >= size) return err.report(errc::value_too_large); - buff[ret] = 0; + buff[ret] = 0; return {buff.get()}; -} - -bool __remove(const path& p, error_code* ec) { - ErrorHandler<bool> err("remove", ec, &p); - if (detail::remove(p.c_str()) == -1) { - if (errno != ENOENT) - err.report(capture_errno()); - return false; - } - return true; -} - -namespace { - -uintmax_t remove_all_impl(path const& p, error_code& ec) { - const auto npos = static_cast<uintmax_t>(-1); - const file_status st = __symlink_status(p, &ec); - if (ec) - return npos; - uintmax_t count = 1; - if (is_directory(st)) { - for (directory_iterator it(p, ec); !ec && it != directory_iterator(); - it.increment(ec)) { - auto other_count = remove_all_impl(it->path(), ec); - if (ec) - return npos; - count += other_count; - } - if (ec) - return npos; - } - if (!__remove(p, &ec)) - return npos; - return count; -} - -} // end namespace - -uintmax_t __remove_all(const path& p, error_code* ec) { - ErrorHandler<uintmax_t> err("remove_all", ec, &p); - - error_code mec; - auto count = remove_all_impl(p, mec); - if (mec) { - if (mec == errc::no_such_file_or_directory) - return 0; - return err.report(mec); - } - return count; -} - -void __rename(const path& from, const path& to, error_code* ec) { - ErrorHandler<void> err("rename", ec, &from, &to); - if (detail::rename(from.c_str(), to.c_str()) == -1) - err.report(capture_errno()); -} - -void __resize_file(const path& p, uintmax_t size, error_code* ec) { - ErrorHandler<void> err("resize_file", ec, &p); - if (detail::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) - return err.report(capture_errno()); -} - -space_info __space(const path& p, error_code* ec) { - ErrorHandler<void> err("space", ec, &p); - space_info si; - detail::StatVFS m_svfs = {}; - if (detail::statvfs(p.c_str(), &m_svfs) == -1) { - err.report(capture_errno()); - si.capacity = si.free = si.available = static_cast<uintmax_t>(-1); - return si; - } - // Multiply with overflow checking. - auto do_mult = [&](uintmax_t& out, uintmax_t other) { - out = other * m_svfs.f_frsize; - if (other == 0 || out / other != m_svfs.f_frsize) - out = static_cast<uintmax_t>(-1); - }; - do_mult(si.capacity, m_svfs.f_blocks); - do_mult(si.free, m_svfs.f_bfree); - do_mult(si.available, m_svfs.f_bavail); - return si; -} - -file_status __status(const path& p, error_code* ec) { - return detail::posix_stat(p, ec); -} - -file_status __symlink_status(const path& p, error_code* ec) { - return detail::posix_lstat(p, ec); -} - -path __temp_directory_path(error_code* ec) { - ErrorHandler<path> err("temp_directory_path", ec); - -#if defined(_LIBCPP_WIN32API) - wchar_t buf[MAX_PATH]; - DWORD retval = GetTempPathW(MAX_PATH, buf); - if (!retval) - return err.report(detail::make_windows_error(GetLastError())); - if (retval > MAX_PATH) - return err.report(errc::filename_too_long); - // GetTempPathW returns a path with a trailing slash, which we - // shouldn't include for consistency. - if (buf[retval-1] == L'\\') - buf[retval-1] = L'\0'; - path p(buf); -#else - const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; - const char* ret = nullptr; - - for (auto& ep : env_paths) - if ((ret = getenv(ep))) - break; - if (ret == nullptr) - ret = "/tmp"; - - path p(ret); -#endif - error_code m_ec; - file_status st = detail::posix_stat(p, &m_ec); - if (!status_known(st)) - return err.report(m_ec, "cannot access path " PATH_CSTR_FMT, p.c_str()); - - if (!exists(st) || !is_directory(st)) - return err.report(errc::not_a_directory, - "path " PATH_CSTR_FMT " is not a directory", p.c_str()); - - return p; -} - -path __weakly_canonical(const path& p, error_code* ec) { - ErrorHandler<path> err("weakly_canonical", ec, &p); - - if (p.empty()) - return __canonical("", ec); - - path result; - path tmp; - tmp.__reserve(p.native().size()); - auto PP = PathParser::CreateEnd(p.native()); - --PP; - vector<string_view_t> DNEParts; - - while (PP.State != PathParser::PS_BeforeBegin) { - tmp.assign(createView(p.native().data(), &PP.RawEntry.back())); - error_code m_ec; - file_status st = __status(tmp, &m_ec); - if (!status_known(st)) { - return err.report(m_ec); - } else if (exists(st)) { - result = __canonical(tmp, ec); - break; - } - DNEParts.push_back(*PP); - --PP; - } - if (PP.State == PathParser::PS_BeforeBegin) - result = __canonical("", ec); - if (ec) - ec->clear(); - if (DNEParts.empty()) - return result; - for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It) - result /= *It; - return result.lexically_normal(); -} - -/////////////////////////////////////////////////////////////////////////////// -// path definitions -/////////////////////////////////////////////////////////////////////////////// - -constexpr path::value_type path::preferred_separator; - -path& path::replace_extension(path const& replacement) { - path p = extension(); - if (not p.empty()) { - __pn_.erase(__pn_.size() - p.native().size()); - } - if (!replacement.empty()) { - if (replacement.native()[0] != '.') { - __pn_ += PS("."); - } - __pn_.append(replacement.__pn_); - } - return *this; -} - -/////////////////////////////////////////////////////////////////////////////// -// path.decompose - -string_view_t path::__root_name() const { - auto PP = PathParser::CreateBegin(__pn_); - if (PP.State == PathParser::PS_InRootName) - return *PP; - return {}; -} - -string_view_t path::__root_directory() const { - auto PP = PathParser::CreateBegin(__pn_); - if (PP.State == PathParser::PS_InRootName) - ++PP; - if (PP.State == PathParser::PS_InRootDir) - return *PP; - return {}; -} - -string_view_t path::__root_path_raw() const { - auto PP = PathParser::CreateBegin(__pn_); - if (PP.State == PathParser::PS_InRootName) { - auto NextCh = PP.peek(); - if (NextCh && isSeparator(*NextCh)) { - ++PP; - return createView(__pn_.data(), &PP.RawEntry.back()); - } - return PP.RawEntry; - } - if (PP.State == PathParser::PS_InRootDir) - return *PP; - return {}; -} - +} + +bool __remove(const path& p, error_code* ec) { + ErrorHandler<bool> err("remove", ec, &p); + if (detail::remove(p.c_str()) == -1) { + if (errno != ENOENT) + err.report(capture_errno()); + return false; + } + return true; +} + +namespace { + +uintmax_t remove_all_impl(path const& p, error_code& ec) { + const auto npos = static_cast<uintmax_t>(-1); + const file_status st = __symlink_status(p, &ec); + if (ec) + return npos; + uintmax_t count = 1; + if (is_directory(st)) { + for (directory_iterator it(p, ec); !ec && it != directory_iterator(); + it.increment(ec)) { + auto other_count = remove_all_impl(it->path(), ec); + if (ec) + return npos; + count += other_count; + } + if (ec) + return npos; + } + if (!__remove(p, &ec)) + return npos; + return count; +} + +} // end namespace + +uintmax_t __remove_all(const path& p, error_code* ec) { + ErrorHandler<uintmax_t> err("remove_all", ec, &p); + + error_code mec; + auto count = remove_all_impl(p, mec); + if (mec) { + if (mec == errc::no_such_file_or_directory) + return 0; + return err.report(mec); + } + return count; +} + +void __rename(const path& from, const path& to, error_code* ec) { + ErrorHandler<void> err("rename", ec, &from, &to); + if (detail::rename(from.c_str(), to.c_str()) == -1) + err.report(capture_errno()); +} + +void __resize_file(const path& p, uintmax_t size, error_code* ec) { + ErrorHandler<void> err("resize_file", ec, &p); + if (detail::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) + return err.report(capture_errno()); +} + +space_info __space(const path& p, error_code* ec) { + ErrorHandler<void> err("space", ec, &p); + space_info si; + detail::StatVFS m_svfs = {}; + if (detail::statvfs(p.c_str(), &m_svfs) == -1) { + err.report(capture_errno()); + si.capacity = si.free = si.available = static_cast<uintmax_t>(-1); + return si; + } + // Multiply with overflow checking. + auto do_mult = [&](uintmax_t& out, uintmax_t other) { + out = other * m_svfs.f_frsize; + if (other == 0 || out / other != m_svfs.f_frsize) + out = static_cast<uintmax_t>(-1); + }; + do_mult(si.capacity, m_svfs.f_blocks); + do_mult(si.free, m_svfs.f_bfree); + do_mult(si.available, m_svfs.f_bavail); + return si; +} + +file_status __status(const path& p, error_code* ec) { + return detail::posix_stat(p, ec); +} + +file_status __symlink_status(const path& p, error_code* ec) { + return detail::posix_lstat(p, ec); +} + +path __temp_directory_path(error_code* ec) { + ErrorHandler<path> err("temp_directory_path", ec); + +#if defined(_LIBCPP_WIN32API) + wchar_t buf[MAX_PATH]; + DWORD retval = GetTempPathW(MAX_PATH, buf); + if (!retval) + return err.report(detail::make_windows_error(GetLastError())); + if (retval > MAX_PATH) + return err.report(errc::filename_too_long); + // GetTempPathW returns a path with a trailing slash, which we + // shouldn't include for consistency. + if (buf[retval-1] == L'\\') + buf[retval-1] = L'\0'; + path p(buf); +#else + const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; + const char* ret = nullptr; + + for (auto& ep : env_paths) + if ((ret = getenv(ep))) + break; + if (ret == nullptr) + ret = "/tmp"; + + path p(ret); +#endif + error_code m_ec; + file_status st = detail::posix_stat(p, &m_ec); + if (!status_known(st)) + return err.report(m_ec, "cannot access path " PATH_CSTR_FMT, p.c_str()); + + if (!exists(st) || !is_directory(st)) + return err.report(errc::not_a_directory, + "path " PATH_CSTR_FMT " is not a directory", p.c_str()); + + return p; +} + +path __weakly_canonical(const path& p, error_code* ec) { + ErrorHandler<path> err("weakly_canonical", ec, &p); + + if (p.empty()) + return __canonical("", ec); + + path result; + path tmp; + tmp.__reserve(p.native().size()); + auto PP = PathParser::CreateEnd(p.native()); + --PP; + vector<string_view_t> DNEParts; + + while (PP.State != PathParser::PS_BeforeBegin) { + tmp.assign(createView(p.native().data(), &PP.RawEntry.back())); + error_code m_ec; + file_status st = __status(tmp, &m_ec); + if (!status_known(st)) { + return err.report(m_ec); + } else if (exists(st)) { + result = __canonical(tmp, ec); + break; + } + DNEParts.push_back(*PP); + --PP; + } + if (PP.State == PathParser::PS_BeforeBegin) + result = __canonical("", ec); + if (ec) + ec->clear(); + if (DNEParts.empty()) + return result; + for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It) + result /= *It; + return result.lexically_normal(); +} + +/////////////////////////////////////////////////////////////////////////////// +// path definitions +/////////////////////////////////////////////////////////////////////////////// + +constexpr path::value_type path::preferred_separator; + +path& path::replace_extension(path const& replacement) { + path p = extension(); + if (not p.empty()) { + __pn_.erase(__pn_.size() - p.native().size()); + } + if (!replacement.empty()) { + if (replacement.native()[0] != '.') { + __pn_ += PS("."); + } + __pn_.append(replacement.__pn_); + } + return *this; +} + +/////////////////////////////////////////////////////////////////////////////// +// path.decompose + +string_view_t path::__root_name() const { + auto PP = PathParser::CreateBegin(__pn_); + if (PP.State == PathParser::PS_InRootName) + return *PP; + return {}; +} + +string_view_t path::__root_directory() const { + auto PP = PathParser::CreateBegin(__pn_); + if (PP.State == PathParser::PS_InRootName) + ++PP; + if (PP.State == PathParser::PS_InRootDir) + return *PP; + return {}; +} + +string_view_t path::__root_path_raw() const { + auto PP = PathParser::CreateBegin(__pn_); + if (PP.State == PathParser::PS_InRootName) { + auto NextCh = PP.peek(); + if (NextCh && isSeparator(*NextCh)) { + ++PP; + return createView(__pn_.data(), &PP.RawEntry.back()); + } + return PP.RawEntry; + } + if (PP.State == PathParser::PS_InRootDir) + return *PP; + return {}; +} + static bool ConsumeRootName(PathParser *PP) { static_assert(PathParser::PS_BeforeBegin == 1 && PathParser::PS_InRootName == 2, @@ -1561,243 +1561,243 @@ static bool ConsumeRootName(PathParser *PP) { return PP->State == PathParser::PS_AtEnd; } -static bool ConsumeRootDir(PathParser* PP) { +static bool ConsumeRootDir(PathParser* PP) { static_assert(PathParser::PS_BeforeBegin == 1 && PathParser::PS_InRootName == 2 && PathParser::PS_InRootDir == 3, "Values for enums are incorrect"); - while (PP->State <= PathParser::PS_InRootDir) - ++(*PP); - return PP->State == PathParser::PS_AtEnd; -} - -string_view_t path::__relative_path() const { - auto PP = PathParser::CreateBegin(__pn_); - if (ConsumeRootDir(&PP)) - return {}; - return createView(PP.RawEntry.data(), &__pn_.back()); -} - -string_view_t path::__parent_path() const { - if (empty()) - return {}; - // Determine if we have a root path but not a relative path. In that case - // return *this. - { - auto PP = PathParser::CreateBegin(__pn_); - if (ConsumeRootDir(&PP)) - return __pn_; - } - // Otherwise remove a single element from the end of the path, and return - // a string representing that path - { - auto PP = PathParser::CreateEnd(__pn_); - --PP; - if (PP.RawEntry.data() == __pn_.data()) - return {}; - --PP; - return createView(__pn_.data(), &PP.RawEntry.back()); - } -} - -string_view_t path::__filename() const { - if (empty()) - return {}; - { - PathParser PP = PathParser::CreateBegin(__pn_); - if (ConsumeRootDir(&PP)) - return {}; - } - return *(--PathParser::CreateEnd(__pn_)); -} - -string_view_t path::__stem() const { - return parser::separate_filename(__filename()).first; -} - -string_view_t path::__extension() const { - return parser::separate_filename(__filename()).second; -} - -//////////////////////////////////////////////////////////////////////////// -// path.gen - -enum PathPartKind : unsigned char { - PK_None, - PK_RootSep, - PK_Filename, - PK_Dot, - PK_DotDot, - PK_TrailingSep -}; - -static PathPartKind ClassifyPathPart(string_view_t Part) { - if (Part.empty()) - return PK_TrailingSep; - if (Part == PS(".")) - return PK_Dot; - if (Part == PS("..")) - return PK_DotDot; - if (Part == PS("/")) - return PK_RootSep; -#if defined(_LIBCPP_WIN32API) - if (Part == PS("\\")) - return PK_RootSep; -#endif - return PK_Filename; -} - -path path::lexically_normal() const { - if (__pn_.empty()) - return *this; - - using PartKindPair = pair<string_view_t, PathPartKind>; - vector<PartKindPair> Parts; - // Guess as to how many elements the path has to avoid reallocating. - Parts.reserve(32); - - // Track the total size of the parts as we collect them. This allows the - // resulting path to reserve the correct amount of memory. - size_t NewPathSize = 0; - auto AddPart = [&](PathPartKind K, string_view_t P) { - NewPathSize += P.size(); - Parts.emplace_back(P, K); - }; - auto LastPartKind = [&]() { - if (Parts.empty()) - return PK_None; - return Parts.back().second; - }; - - bool MaybeNeedTrailingSep = false; - // Build a stack containing the remaining elements of the path, popping off - // elements which occur before a '..' entry. - for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) { - auto Part = *PP; - PathPartKind Kind = ClassifyPathPart(Part); - switch (Kind) { - case PK_Filename: - case PK_RootSep: { - // Add all non-dot and non-dot-dot elements to the stack of elements. - AddPart(Kind, Part); - MaybeNeedTrailingSep = false; - break; - } - case PK_DotDot: { - // Only push a ".." element if there are no elements preceding the "..", - // or if the preceding element is itself "..". - auto LastKind = LastPartKind(); - if (LastKind == PK_Filename) { - NewPathSize -= Parts.back().first.size(); - Parts.pop_back(); - } else if (LastKind != PK_RootSep) - AddPart(PK_DotDot, PS("..")); - MaybeNeedTrailingSep = LastKind == PK_Filename; - break; - } - case PK_Dot: - case PK_TrailingSep: { - MaybeNeedTrailingSep = true; - break; - } - case PK_None: - _LIBCPP_UNREACHABLE(); - } - } - // [fs.path.generic]p6.8: If the path is empty, add a dot. - if (Parts.empty()) - return PS("."); - - // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any - // trailing directory-separator. - bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename; - - path Result; - Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep); - for (auto& PK : Parts) - Result /= PK.first; - - if (NeedTrailingSep) - Result /= PS(""); - - Result.make_preferred(); - return Result; -} - -static int DetermineLexicalElementCount(PathParser PP) { - int Count = 0; - for (; PP; ++PP) { - auto Elem = *PP; - if (Elem == PS("..")) - --Count; - else if (Elem != PS(".") && Elem != PS("")) - ++Count; - } - return Count; -} - -path path::lexically_relative(const path& base) const { - { // perform root-name/root-directory mismatch checks - auto PP = PathParser::CreateBegin(__pn_); - auto PPBase = PathParser::CreateBegin(base.__pn_); - auto CheckIterMismatchAtBase = [&]() { - return PP.State != PPBase.State && - (PP.inRootPath() || PPBase.inRootPath()); - }; + while (PP->State <= PathParser::PS_InRootDir) + ++(*PP); + return PP->State == PathParser::PS_AtEnd; +} + +string_view_t path::__relative_path() const { + auto PP = PathParser::CreateBegin(__pn_); + if (ConsumeRootDir(&PP)) + return {}; + return createView(PP.RawEntry.data(), &__pn_.back()); +} + +string_view_t path::__parent_path() const { + if (empty()) + return {}; + // Determine if we have a root path but not a relative path. In that case + // return *this. + { + auto PP = PathParser::CreateBegin(__pn_); + if (ConsumeRootDir(&PP)) + return __pn_; + } + // Otherwise remove a single element from the end of the path, and return + // a string representing that path + { + auto PP = PathParser::CreateEnd(__pn_); + --PP; + if (PP.RawEntry.data() == __pn_.data()) + return {}; + --PP; + return createView(__pn_.data(), &PP.RawEntry.back()); + } +} + +string_view_t path::__filename() const { + if (empty()) + return {}; + { + PathParser PP = PathParser::CreateBegin(__pn_); + if (ConsumeRootDir(&PP)) + return {}; + } + return *(--PathParser::CreateEnd(__pn_)); +} + +string_view_t path::__stem() const { + return parser::separate_filename(__filename()).first; +} + +string_view_t path::__extension() const { + return parser::separate_filename(__filename()).second; +} + +//////////////////////////////////////////////////////////////////////////// +// path.gen + +enum PathPartKind : unsigned char { + PK_None, + PK_RootSep, + PK_Filename, + PK_Dot, + PK_DotDot, + PK_TrailingSep +}; + +static PathPartKind ClassifyPathPart(string_view_t Part) { + if (Part.empty()) + return PK_TrailingSep; + if (Part == PS(".")) + return PK_Dot; + if (Part == PS("..")) + return PK_DotDot; + if (Part == PS("/")) + return PK_RootSep; +#if defined(_LIBCPP_WIN32API) + if (Part == PS("\\")) + return PK_RootSep; +#endif + return PK_Filename; +} + +path path::lexically_normal() const { + if (__pn_.empty()) + return *this; + + using PartKindPair = pair<string_view_t, PathPartKind>; + vector<PartKindPair> Parts; + // Guess as to how many elements the path has to avoid reallocating. + Parts.reserve(32); + + // Track the total size of the parts as we collect them. This allows the + // resulting path to reserve the correct amount of memory. + size_t NewPathSize = 0; + auto AddPart = [&](PathPartKind K, string_view_t P) { + NewPathSize += P.size(); + Parts.emplace_back(P, K); + }; + auto LastPartKind = [&]() { + if (Parts.empty()) + return PK_None; + return Parts.back().second; + }; + + bool MaybeNeedTrailingSep = false; + // Build a stack containing the remaining elements of the path, popping off + // elements which occur before a '..' entry. + for (auto PP = PathParser::CreateBegin(__pn_); PP; ++PP) { + auto Part = *PP; + PathPartKind Kind = ClassifyPathPart(Part); + switch (Kind) { + case PK_Filename: + case PK_RootSep: { + // Add all non-dot and non-dot-dot elements to the stack of elements. + AddPart(Kind, Part); + MaybeNeedTrailingSep = false; + break; + } + case PK_DotDot: { + // Only push a ".." element if there are no elements preceding the "..", + // or if the preceding element is itself "..". + auto LastKind = LastPartKind(); + if (LastKind == PK_Filename) { + NewPathSize -= Parts.back().first.size(); + Parts.pop_back(); + } else if (LastKind != PK_RootSep) + AddPart(PK_DotDot, PS("..")); + MaybeNeedTrailingSep = LastKind == PK_Filename; + break; + } + case PK_Dot: + case PK_TrailingSep: { + MaybeNeedTrailingSep = true; + break; + } + case PK_None: + _LIBCPP_UNREACHABLE(); + } + } + // [fs.path.generic]p6.8: If the path is empty, add a dot. + if (Parts.empty()) + return PS("."); + + // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any + // trailing directory-separator. + bool NeedTrailingSep = MaybeNeedTrailingSep && LastPartKind() == PK_Filename; + + path Result; + Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep); + for (auto& PK : Parts) + Result /= PK.first; + + if (NeedTrailingSep) + Result /= PS(""); + + Result.make_preferred(); + return Result; +} + +static int DetermineLexicalElementCount(PathParser PP) { + int Count = 0; + for (; PP; ++PP) { + auto Elem = *PP; + if (Elem == PS("..")) + --Count; + else if (Elem != PS(".") && Elem != PS("")) + ++Count; + } + return Count; +} + +path path::lexically_relative(const path& base) const { + { // perform root-name/root-directory mismatch checks + auto PP = PathParser::CreateBegin(__pn_); + auto PPBase = PathParser::CreateBegin(base.__pn_); + auto CheckIterMismatchAtBase = [&]() { + return PP.State != PPBase.State && + (PP.inRootPath() || PPBase.inRootPath()); + }; if (PP.inRootName() && PPBase.inRootName()) { - if (*PP != *PPBase) - return {}; - } else if (CheckIterMismatchAtBase()) - return {}; - - if (PP.inRootPath()) - ++PP; - if (PPBase.inRootPath()) - ++PPBase; - if (CheckIterMismatchAtBase()) - return {}; - } - - // Find the first mismatching element - auto PP = PathParser::CreateBegin(__pn_); - auto PPBase = PathParser::CreateBegin(base.__pn_); - while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) { - ++PP; - ++PPBase; - } - - // If there is no mismatch, return ".". - if (!PP && !PPBase) - return "."; - - // Otherwise, determine the number of elements, 'n', which are not dot or - // dot-dot minus the number of dot-dot elements. - int ElemCount = DetermineLexicalElementCount(PPBase); - if (ElemCount < 0) - return {}; - + if (*PP != *PPBase) + return {}; + } else if (CheckIterMismatchAtBase()) + return {}; + + if (PP.inRootPath()) + ++PP; + if (PPBase.inRootPath()) + ++PPBase; + if (CheckIterMismatchAtBase()) + return {}; + } + + // Find the first mismatching element + auto PP = PathParser::CreateBegin(__pn_); + auto PPBase = PathParser::CreateBegin(base.__pn_); + while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) { + ++PP; + ++PPBase; + } + + // If there is no mismatch, return ".". + if (!PP && !PPBase) + return "."; + + // Otherwise, determine the number of elements, 'n', which are not dot or + // dot-dot minus the number of dot-dot elements. + int ElemCount = DetermineLexicalElementCount(PPBase); + if (ElemCount < 0) + return {}; + // if n == 0 and (a == end() || a->empty()), returns path("."); otherwise - if (ElemCount == 0 && (PP.atEnd() || *PP == PS(""))) - return PS("."); - - // return a path constructed with 'n' dot-dot elements, followed by the the - // elements of '*this' after the mismatch. - path Result; - // FIXME: Reserve enough room in Result that it won't have to re-allocate. - while (ElemCount--) - Result /= PS(".."); - for (; PP; ++PP) - Result /= *PP; - return Result; -} - -//////////////////////////////////////////////////////////////////////////// -// path.comparisons + if (ElemCount == 0 && (PP.atEnd() || *PP == PS(""))) + return PS("."); + + // return a path constructed with 'n' dot-dot elements, followed by the the + // elements of '*this' after the mismatch. + path Result; + // FIXME: Reserve enough room in Result that it won't have to re-allocate. + while (ElemCount--) + Result /= PS(".."); + for (; PP; ++PP) + Result /= *PP; + return Result; +} + +//////////////////////////////////////////////////////////////////////////// +// path.comparisons static int CompareRootName(PathParser *LHS, PathParser *RHS) { if (!LHS->inRootName() && !RHS->inRootName()) return 0; auto GetRootName = [](PathParser *Parser) -> string_view_t { - return Parser->inRootName() ? **Parser : PS(""); + return Parser->inRootName() ? **Parser : PS(""); }; int res = GetRootName(LHS).compare(GetRootName(RHS)); ConsumeRootName(LHS); @@ -1820,25 +1820,25 @@ static int CompareRootDir(PathParser *LHS, PathParser *RHS) { static int CompareRelative(PathParser *LHSPtr, PathParser *RHSPtr) { auto &LHS = *LHSPtr; auto &RHS = *RHSPtr; - + int res; while (LHS && RHS) { if ((res = (*LHS).compare(*RHS)) != 0) - return res; + return res; ++LHS; ++RHS; - } + } return 0; } static int CompareEndState(PathParser *LHS, PathParser *RHS) { if (LHS->atEnd() && !RHS->atEnd()) - return -1; + return -1; else if (!LHS->atEnd() && RHS->atEnd()) return 1; return 0; -} - +} + int path::__compare(string_view_t __s) const { auto LHS = PathParser::CreateBegin(__pn_); auto RHS = PathParser::CreateBegin(__s); @@ -1856,142 +1856,142 @@ int path::__compare(string_view_t __s) const { return CompareEndState(&LHS, &RHS); } -//////////////////////////////////////////////////////////////////////////// -// path.nonmembers -size_t hash_value(const path& __p) noexcept { - auto PP = PathParser::CreateBegin(__p.native()); - size_t hash_value = 0; - hash<string_view_t> hasher; - while (PP) { - hash_value = __hash_combine(hash_value, hasher(*PP)); - ++PP; - } - return hash_value; -} - -//////////////////////////////////////////////////////////////////////////// -// path.itr -path::iterator path::begin() const { - auto PP = PathParser::CreateBegin(__pn_); - iterator it; - it.__path_ptr_ = this; - it.__state_ = static_cast<path::iterator::_ParserState>(PP.State); - it.__entry_ = PP.RawEntry; - it.__stashed_elem_.__assign_view(*PP); - return it; -} - -path::iterator path::end() const { - iterator it{}; - it.__state_ = path::iterator::_AtEnd; - it.__path_ptr_ = this; - return it; -} - -path::iterator& path::iterator::__increment() { - PathParser PP(__path_ptr_->native(), __entry_, __state_); - ++PP; - __state_ = static_cast<_ParserState>(PP.State); - __entry_ = PP.RawEntry; - __stashed_elem_.__assign_view(*PP); - return *this; -} - -path::iterator& path::iterator::__decrement() { - PathParser PP(__path_ptr_->native(), __entry_, __state_); - --PP; - __state_ = static_cast<_ParserState>(PP.State); - __entry_ = PP.RawEntry; - __stashed_elem_.__assign_view(*PP); - return *this; -} - -#if defined(_LIBCPP_WIN32API) -//////////////////////////////////////////////////////////////////////////// -// Windows path conversions -size_t __wide_to_char(const wstring &str, char *out, size_t outlen) { - if (str.empty()) - return 0; - ErrorHandler<size_t> err("__wide_to_char", nullptr); - UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; - BOOL used_default = FALSE; - int ret = WideCharToMultiByte(codepage, 0, str.data(), str.size(), out, - outlen, nullptr, &used_default); - if (ret <= 0 || used_default) - return err.report(errc::illegal_byte_sequence); - return ret; -} - -size_t __char_to_wide(const string &str, wchar_t *out, size_t outlen) { - if (str.empty()) - return 0; - ErrorHandler<size_t> err("__char_to_wide", nullptr); - UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; - int ret = MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, str.data(), - str.size(), out, outlen); - if (ret <= 0) - return err.report(errc::illegal_byte_sequence); - return ret; -} -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// directory entry definitions -/////////////////////////////////////////////////////////////////////////////// - -error_code directory_entry::__do_refresh() noexcept { - __data_.__reset(); - error_code failure_ec; - - StatT full_st; - file_status st = detail::posix_lstat(__p_, full_st, &failure_ec); - if (!status_known(st)) { - __data_.__reset(); - return failure_ec; - } - - if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) { - __data_.__cache_type_ = directory_entry::_RefreshNonSymlink; - __data_.__type_ = st.type(); - __data_.__non_sym_perms_ = st.permissions(); - } else { // we have a symlink - __data_.__sym_perms_ = st.permissions(); - // Get the information about the linked entity. - // Ignore errors from stat, since we don't want errors regarding symlink - // resolution to be reported to the user. - error_code ignored_ec; - st = detail::posix_stat(__p_, full_st, &ignored_ec); - - __data_.__type_ = st.type(); - __data_.__non_sym_perms_ = st.permissions(); - - // If we failed to resolve the link, then only partially populate the - // cache. - if (!status_known(st)) { - __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved; - return error_code{}; - } - // Otherwise, we resolved the link, potentially as not existing. - // That's OK. - __data_.__cache_type_ = directory_entry::_RefreshSymlink; - } - - if (_VSTD_FS::is_regular_file(st)) - __data_.__size_ = static_cast<uintmax_t>(full_st.st_size); - - if (_VSTD_FS::exists(st)) { - __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink); - - // Attempt to extract the mtime, and fail if it's not representable using - // file_time_type. For now we ignore the error, as we'll report it when - // the value is actually used. - error_code ignored_ec; - __data_.__write_time_ = - __extract_last_write_time(__p_, full_st, &ignored_ec); - } - - return failure_ec; -} - -_LIBCPP_END_NAMESPACE_FILESYSTEM +//////////////////////////////////////////////////////////////////////////// +// path.nonmembers +size_t hash_value(const path& __p) noexcept { + auto PP = PathParser::CreateBegin(__p.native()); + size_t hash_value = 0; + hash<string_view_t> hasher; + while (PP) { + hash_value = __hash_combine(hash_value, hasher(*PP)); + ++PP; + } + return hash_value; +} + +//////////////////////////////////////////////////////////////////////////// +// path.itr +path::iterator path::begin() const { + auto PP = PathParser::CreateBegin(__pn_); + iterator it; + it.__path_ptr_ = this; + it.__state_ = static_cast<path::iterator::_ParserState>(PP.State); + it.__entry_ = PP.RawEntry; + it.__stashed_elem_.__assign_view(*PP); + return it; +} + +path::iterator path::end() const { + iterator it{}; + it.__state_ = path::iterator::_AtEnd; + it.__path_ptr_ = this; + return it; +} + +path::iterator& path::iterator::__increment() { + PathParser PP(__path_ptr_->native(), __entry_, __state_); + ++PP; + __state_ = static_cast<_ParserState>(PP.State); + __entry_ = PP.RawEntry; + __stashed_elem_.__assign_view(*PP); + return *this; +} + +path::iterator& path::iterator::__decrement() { + PathParser PP(__path_ptr_->native(), __entry_, __state_); + --PP; + __state_ = static_cast<_ParserState>(PP.State); + __entry_ = PP.RawEntry; + __stashed_elem_.__assign_view(*PP); + return *this; +} + +#if defined(_LIBCPP_WIN32API) +//////////////////////////////////////////////////////////////////////////// +// Windows path conversions +size_t __wide_to_char(const wstring &str, char *out, size_t outlen) { + if (str.empty()) + return 0; + ErrorHandler<size_t> err("__wide_to_char", nullptr); + UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + BOOL used_default = FALSE; + int ret = WideCharToMultiByte(codepage, 0, str.data(), str.size(), out, + outlen, nullptr, &used_default); + if (ret <= 0 || used_default) + return err.report(errc::illegal_byte_sequence); + return ret; +} + +size_t __char_to_wide(const string &str, wchar_t *out, size_t outlen) { + if (str.empty()) + return 0; + ErrorHandler<size_t> err("__char_to_wide", nullptr); + UINT codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + int ret = MultiByteToWideChar(codepage, MB_ERR_INVALID_CHARS, str.data(), + str.size(), out, outlen); + if (ret <= 0) + return err.report(errc::illegal_byte_sequence); + return ret; +} +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// directory entry definitions +/////////////////////////////////////////////////////////////////////////////// + +error_code directory_entry::__do_refresh() noexcept { + __data_.__reset(); + error_code failure_ec; + + StatT full_st; + file_status st = detail::posix_lstat(__p_, full_st, &failure_ec); + if (!status_known(st)) { + __data_.__reset(); + return failure_ec; + } + + if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) { + __data_.__cache_type_ = directory_entry::_RefreshNonSymlink; + __data_.__type_ = st.type(); + __data_.__non_sym_perms_ = st.permissions(); + } else { // we have a symlink + __data_.__sym_perms_ = st.permissions(); + // Get the information about the linked entity. + // Ignore errors from stat, since we don't want errors regarding symlink + // resolution to be reported to the user. + error_code ignored_ec; + st = detail::posix_stat(__p_, full_st, &ignored_ec); + + __data_.__type_ = st.type(); + __data_.__non_sym_perms_ = st.permissions(); + + // If we failed to resolve the link, then only partially populate the + // cache. + if (!status_known(st)) { + __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved; + return error_code{}; + } + // Otherwise, we resolved the link, potentially as not existing. + // That's OK. + __data_.__cache_type_ = directory_entry::_RefreshSymlink; + } + + if (_VSTD_FS::is_regular_file(st)) + __data_.__size_ = static_cast<uintmax_t>(full_st.st_size); + + if (_VSTD_FS::exists(st)) { + __data_.__nlink_ = static_cast<uintmax_t>(full_st.st_nlink); + + // Attempt to extract the mtime, and fail if it's not representable using + // file_time_type. For now we ignore the error, as we'll report it when + // the value is actually used. + error_code ignored_ec; + __data_.__write_time_ = + __extract_last_write_time(__p_, full_st, &ignored_ec); + } + + return failure_ec; +} + +_LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/contrib/libs/cxxsupp/libcxx/src/filesystem/posix_compat.h b/contrib/libs/cxxsupp/libcxx/src/filesystem/posix_compat.h index 083c2ba258..f5c8ec39df 100644 --- a/contrib/libs/cxxsupp/libcxx/src/filesystem/posix_compat.h +++ b/contrib/libs/cxxsupp/libcxx/src/filesystem/posix_compat.h @@ -1,521 +1,521 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -// -// POSIX-like portability helper functions. -// -// These generally behave like the proper posix functions, with these -// exceptions: -// On Windows, they take paths in wchar_t* form, instead of char* form. -// The symlink() function is split into two frontends, symlink_file() -// and symlink_dir(). -// -// These are provided within an anonymous namespace within the detail -// namespace - callers need to include this header and call them as -// detail::function(), regardless of platform. -// - -#ifndef POSIX_COMPAT_H -#define POSIX_COMPAT_H - -#include "filesystem" - -#include "filesystem_common.h" - -#if defined(_LIBCPP_WIN32API) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# include <windows.h> -# include <io.h> -# include <winioctl.h> -#else -# include <unistd.h> -# include <sys/stat.h> -# include <sys/statvfs.h> -#endif -#include <time.h> - -#if defined(_LIBCPP_WIN32API) -// This struct isn't defined in the normal Windows SDK, but only in the -// Windows Driver Kit. -struct LIBCPP_REPARSE_DATA_BUFFER { - unsigned long ReparseTag; - unsigned short ReparseDataLength; - unsigned short Reserved; - union { - struct { - unsigned short SubstituteNameOffset; - unsigned short SubstituteNameLength; - unsigned short PrintNameOffset; - unsigned short PrintNameLength; - unsigned long Flags; - wchar_t PathBuffer[1]; - } SymbolicLinkReparseBuffer; - struct { - unsigned short SubstituteNameOffset; - unsigned short SubstituteNameLength; - unsigned short PrintNameOffset; - unsigned short PrintNameLength; - wchar_t PathBuffer[1]; - } MountPointReparseBuffer; - struct { - unsigned char DataBuffer[1]; - } GenericReparseBuffer; - }; -}; -#endif - -_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM - -namespace detail { -namespace { - -#if defined(_LIBCPP_WIN32API) - -// Various C runtime header sets provide more or less of these. As we -// provide our own implementation, undef all potential defines from the -// C runtime headers and provide a complete set of macros of our own. - -#undef _S_IFMT -#undef _S_IFDIR -#undef _S_IFCHR -#undef _S_IFIFO -#undef _S_IFREG -#undef _S_IFBLK -#undef _S_IFLNK -#undef _S_IFSOCK - -#define _S_IFMT 0xF000 -#define _S_IFDIR 0x4000 -#define _S_IFCHR 0x2000 -#define _S_IFIFO 0x1000 -#define _S_IFREG 0x8000 -#define _S_IFBLK 0x6000 -#define _S_IFLNK 0xA000 -#define _S_IFSOCK 0xC000 - -#undef S_ISDIR -#undef S_ISFIFO -#undef S_ISCHR -#undef S_ISREG -#undef S_ISLNK -#undef S_ISBLK -#undef S_ISSOCK - -#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) -#define S_ISCHR(m) (((m) & _S_IFMT) == _S_IFCHR) -#define S_ISFIFO(m) (((m) & _S_IFMT) == _S_IFIFO) -#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) -#define S_ISBLK(m) (((m) & _S_IFMT) == _S_IFBLK) -#define S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK) -#define S_ISSOCK(m) (((m) & _S_IFMT) == _S_IFSOCK) - -#define O_NONBLOCK 0 - - -// There were 369 years and 89 leap days from the Windows epoch -// (1601) to the Unix epoch (1970). -#define FILE_TIME_OFFSET_SECS (uint64_t(369 * 365 + 89) * (24 * 60 * 60)) - -TimeSpec filetime_to_timespec(LARGE_INTEGER li) { - TimeSpec ret; - ret.tv_sec = li.QuadPart / 10000000 - FILE_TIME_OFFSET_SECS; - ret.tv_nsec = (li.QuadPart % 10000000) * 100; - return ret; -} - -TimeSpec filetime_to_timespec(FILETIME ft) { - LARGE_INTEGER li; - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - return filetime_to_timespec(li); -} - -FILETIME timespec_to_filetime(TimeSpec ts) { - LARGE_INTEGER li; - li.QuadPart = - ts.tv_nsec / 100 + (ts.tv_sec + FILE_TIME_OFFSET_SECS) * 10000000; - FILETIME ft; - ft.dwLowDateTime = li.LowPart; - ft.dwHighDateTime = li.HighPart; - return ft; -} - -int set_errno(int e = GetLastError()) { - errno = static_cast<int>(__win_err_to_errc(e)); - return -1; -} - -class WinHandle { -public: - WinHandle(const wchar_t *p, DWORD access, DWORD flags) { - h = CreateFileW( - p, access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | flags, nullptr); - } - ~WinHandle() { - if (h != INVALID_HANDLE_VALUE) - CloseHandle(h); - } - operator HANDLE() const { return h; } - operator bool() const { return h != INVALID_HANDLE_VALUE; } - -private: - HANDLE h; -}; - -int stat_handle(HANDLE h, StatT *buf) { - FILE_BASIC_INFO basic; - if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic))) - return set_errno(); - memset(buf, 0, sizeof(*buf)); - buf->st_mtim = filetime_to_timespec(basic.LastWriteTime); - buf->st_atim = filetime_to_timespec(basic.LastAccessTime); - buf->st_mode = 0555; // Read-only - if (!(basic.FileAttributes & FILE_ATTRIBUTE_READONLY)) - buf->st_mode |= 0222; // Write - if (basic.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - buf->st_mode |= _S_IFDIR; - } else { - buf->st_mode |= _S_IFREG; - } - if (basic.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - FILE_ATTRIBUTE_TAG_INFO tag; - if (!GetFileInformationByHandleEx(h, FileAttributeTagInfo, &tag, - sizeof(tag))) - return set_errno(); - if (tag.ReparseTag == IO_REPARSE_TAG_SYMLINK) - buf->st_mode = (buf->st_mode & ~_S_IFMT) | _S_IFLNK; - } - FILE_STANDARD_INFO standard; - if (!GetFileInformationByHandleEx(h, FileStandardInfo, &standard, - sizeof(standard))) - return set_errno(); - buf->st_nlink = standard.NumberOfLinks; - buf->st_size = standard.EndOfFile.QuadPart; - BY_HANDLE_FILE_INFORMATION info; - if (!GetFileInformationByHandle(h, &info)) - return set_errno(); - buf->st_dev = info.dwVolumeSerialNumber; - memcpy(&buf->st_ino.id[0], &info.nFileIndexHigh, 4); - memcpy(&buf->st_ino.id[4], &info.nFileIndexLow, 4); - return 0; -} - -int stat_file(const wchar_t *path, StatT *buf, DWORD flags) { - WinHandle h(path, FILE_READ_ATTRIBUTES, flags); - if (!h) - return set_errno(); - int ret = stat_handle(h, buf); - return ret; -} - -int stat(const wchar_t *path, StatT *buf) { return stat_file(path, buf, 0); } - -int lstat(const wchar_t *path, StatT *buf) { - return stat_file(path, buf, FILE_FLAG_OPEN_REPARSE_POINT); -} - -int fstat(int fd, StatT *buf) { - HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); - return stat_handle(h, buf); -} - -int mkdir(const wchar_t *path, int permissions) { - (void)permissions; - return _wmkdir(path); -} - -int symlink_file_dir(const wchar_t *oldname, const wchar_t *newname, - bool is_dir) { - path dest(oldname); - dest.make_preferred(); - oldname = dest.c_str(); - DWORD flags = is_dir ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; - if (CreateSymbolicLinkW(newname, oldname, - flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) - return 0; - int e = GetLastError(); - if (e != ERROR_INVALID_PARAMETER) - return set_errno(e); - if (CreateSymbolicLinkW(newname, oldname, flags)) - return 0; - return set_errno(); -} - -int symlink_file(const wchar_t *oldname, const wchar_t *newname) { - return symlink_file_dir(oldname, newname, false); -} - -int symlink_dir(const wchar_t *oldname, const wchar_t *newname) { - return symlink_file_dir(oldname, newname, true); -} - -int link(const wchar_t *oldname, const wchar_t *newname) { - if (CreateHardLinkW(newname, oldname, nullptr)) - return 0; - return set_errno(); -} - -int remove(const wchar_t *path) { - detail::WinHandle h(path, DELETE, FILE_FLAG_OPEN_REPARSE_POINT); - if (!h) - return set_errno(); - FILE_DISPOSITION_INFO info; - info.DeleteFile = TRUE; - if (!SetFileInformationByHandle(h, FileDispositionInfo, &info, sizeof(info))) - return set_errno(); - return 0; -} - -int truncate_handle(HANDLE h, off_t length) { - LARGE_INTEGER size_param; - size_param.QuadPart = length; - if (!SetFilePointerEx(h, size_param, 0, FILE_BEGIN)) - return set_errno(); - if (!SetEndOfFile(h)) - return set_errno(); - return 0; -} - -int ftruncate(int fd, off_t length) { - HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); - return truncate_handle(h, length); -} - -int truncate(const wchar_t *path, off_t length) { - detail::WinHandle h(path, GENERIC_WRITE, 0); - if (!h) - return set_errno(); - return truncate_handle(h, length); -} - -int rename(const wchar_t *from, const wchar_t *to) { - if (!(MoveFileExW(from, to, - MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | - MOVEFILE_WRITE_THROUGH))) - return set_errno(); - return 0; -} - -template <class... Args> int open(const wchar_t *filename, Args... args) { - return _wopen(filename, args...); -} -int close(int fd) { return _close(fd); } -int chdir(const wchar_t *path) { return _wchdir(path); } - -struct StatVFS { - uint64_t f_frsize; - uint64_t f_blocks; - uint64_t f_bfree; - uint64_t f_bavail; -}; - -int statvfs(const wchar_t *p, StatVFS *buf) { - path dir = p; - while (true) { - error_code local_ec; - const file_status st = status(dir, local_ec); - if (!exists(st) || is_directory(st)) - break; - path parent = dir.parent_path(); - if (parent == dir) { - errno = ENOENT; - return -1; - } - dir = parent; - } - ULARGE_INTEGER free_bytes_available_to_caller, total_number_of_bytes, - total_number_of_free_bytes; - if (!GetDiskFreeSpaceExW(dir.c_str(), &free_bytes_available_to_caller, - &total_number_of_bytes, &total_number_of_free_bytes)) - return set_errno(); - buf->f_frsize = 1; - buf->f_blocks = total_number_of_bytes.QuadPart; - buf->f_bfree = total_number_of_free_bytes.QuadPart; - buf->f_bavail = free_bytes_available_to_caller.QuadPart; - return 0; -} - -wchar_t *getcwd(wchar_t *buff, size_t size) { return _wgetcwd(buff, size); } - -wchar_t *realpath(const wchar_t *path, wchar_t *resolved_name) { - // Only expected to be used with us allocating the buffer. - _LIBCPP_ASSERT(resolved_name == nullptr, - "Windows realpath() assumes a null resolved_name"); - - WinHandle h(path, FILE_READ_ATTRIBUTES, 0); - if (!h) { - set_errno(); - return nullptr; - } - size_t buff_size = MAX_PATH + 10; - std::unique_ptr<wchar_t, decltype(&::free)> buff( - static_cast<wchar_t *>(malloc(buff_size * sizeof(wchar_t))), &::free); - DWORD retval = GetFinalPathNameByHandleW( - h, buff.get(), buff_size, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); - if (retval > buff_size) { - buff_size = retval; - buff.reset(static_cast<wchar_t *>(malloc(buff_size * sizeof(wchar_t)))); - retval = GetFinalPathNameByHandleW(h, buff.get(), buff_size, - FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); - } - if (!retval) { - set_errno(); - return nullptr; - } - wchar_t *ptr = buff.get(); - if (!wcsncmp(ptr, L"\\\\?\\", 4)) { - if (ptr[5] == ':') { // \\?\X: -> X: - memmove(&ptr[0], &ptr[4], (wcslen(&ptr[4]) + 1) * sizeof(wchar_t)); - } else if (!wcsncmp(&ptr[4], L"UNC\\", 4)) { // \\?\UNC\server -> \\server - wcscpy(&ptr[0], L"\\\\"); - memmove(&ptr[2], &ptr[8], (wcslen(&ptr[8]) + 1) * sizeof(wchar_t)); - } - } - return buff.release(); -} - -#define AT_FDCWD -1 -#define AT_SYMLINK_NOFOLLOW 1 -using ModeT = int; - -int fchmod_handle(HANDLE h, int perms) { - FILE_BASIC_INFO basic; - if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic))) - return set_errno(); - DWORD orig_attributes = basic.FileAttributes; - basic.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; - if ((perms & 0222) == 0) - basic.FileAttributes |= FILE_ATTRIBUTE_READONLY; - if (basic.FileAttributes != orig_attributes && - !SetFileInformationByHandle(h, FileBasicInfo, &basic, sizeof(basic))) - return set_errno(); - return 0; -} - -int fchmodat(int fd, const wchar_t *path, int perms, int flag) { - DWORD attributes = GetFileAttributesW(path); - if (attributes == INVALID_FILE_ATTRIBUTES) - return set_errno(); - if (attributes & FILE_ATTRIBUTE_REPARSE_POINT && - !(flag & AT_SYMLINK_NOFOLLOW)) { - // If the file is a symlink, and we are supposed to operate on the target - // of the symlink, we need to open a handle to it, without the - // FILE_FLAG_OPEN_REPARSE_POINT flag, to open the destination of the - // symlink, and operate on it via the handle. - detail::WinHandle h(path, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, 0); - if (!h) - return set_errno(); - return fchmod_handle(h, perms); - } else { - // For a non-symlink, or if operating on the symlink itself instead of - // its target, we can use SetFileAttributesW, saving a few calls. - DWORD orig_attributes = attributes; - attributes &= ~FILE_ATTRIBUTE_READONLY; - if ((perms & 0222) == 0) - attributes |= FILE_ATTRIBUTE_READONLY; - if (attributes != orig_attributes && !SetFileAttributesW(path, attributes)) - return set_errno(); - } - return 0; -} - -int fchmod(int fd, int perms) { - HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); - return fchmod_handle(h, perms); -} - -#define MAX_SYMLINK_SIZE MAXIMUM_REPARSE_DATA_BUFFER_SIZE -using SSizeT = ::int64_t; - -SSizeT readlink(const wchar_t *path, wchar_t *ret_buf, size_t bufsize) { - uint8_t buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - detail::WinHandle h(path, FILE_READ_ATTRIBUTES, FILE_FLAG_OPEN_REPARSE_POINT); - if (!h) - return set_errno(); - DWORD out; - if (!DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, nullptr, 0, buf, sizeof(buf), - &out, 0)) - return set_errno(); - const auto *reparse = reinterpret_cast<LIBCPP_REPARSE_DATA_BUFFER *>(buf); - size_t path_buf_offset = offsetof(LIBCPP_REPARSE_DATA_BUFFER, - SymbolicLinkReparseBuffer.PathBuffer[0]); - if (out < path_buf_offset) { - errno = EINVAL; - return -1; - } - if (reparse->ReparseTag != IO_REPARSE_TAG_SYMLINK) { - errno = EINVAL; - return -1; - } - const auto &symlink = reparse->SymbolicLinkReparseBuffer; - unsigned short name_offset, name_length; - if (symlink.PrintNameLength == 0) { - name_offset = symlink.SubstituteNameOffset; - name_length = symlink.SubstituteNameLength; - } else { - name_offset = symlink.PrintNameOffset; - name_length = symlink.PrintNameLength; - } - // name_offset/length are expressed in bytes, not in wchar_t - if (path_buf_offset + name_offset + name_length > out) { - errno = EINVAL; - return -1; - } - if (name_length / sizeof(wchar_t) > bufsize) { - errno = ENOMEM; - return -1; - } - memcpy(ret_buf, &symlink.PathBuffer[name_offset / sizeof(wchar_t)], - name_length); - return name_length / sizeof(wchar_t); -} - -#else -int symlink_file(const char *oldname, const char *newname) { - return ::symlink(oldname, newname); -} -int symlink_dir(const char *oldname, const char *newname) { - return ::symlink(oldname, newname); -} -using ::chdir; -using ::close; -using ::fchmod; -#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) -using ::fchmodat; -#endif -using ::fstat; -using ::ftruncate; -using ::getcwd; -using ::link; -using ::lstat; -using ::mkdir; -using ::open; -using ::readlink; -using ::realpath; -using ::remove; -using ::rename; -using ::stat; -using ::statvfs; -using ::truncate; - -#define O_BINARY 0 - -using StatVFS = struct statvfs; -using ModeT = ::mode_t; -using SSizeT = ::ssize_t; - -#endif - -} // namespace -} // end namespace detail - -_LIBCPP_END_NAMESPACE_FILESYSTEM - -#endif // POSIX_COMPAT_H +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// +// POSIX-like portability helper functions. +// +// These generally behave like the proper posix functions, with these +// exceptions: +// On Windows, they take paths in wchar_t* form, instead of char* form. +// The symlink() function is split into two frontends, symlink_file() +// and symlink_dir(). +// +// These are provided within an anonymous namespace within the detail +// namespace - callers need to include this header and call them as +// detail::function(), regardless of platform. +// + +#ifndef POSIX_COMPAT_H +#define POSIX_COMPAT_H + +#include "filesystem" + +#include "filesystem_common.h" + +#if defined(_LIBCPP_WIN32API) +# define WIN32_LEAN_AND_MEAN +# define NOMINMAX +# include <windows.h> +# include <io.h> +# include <winioctl.h> +#else +# include <unistd.h> +# include <sys/stat.h> +# include <sys/statvfs.h> +#endif +#include <time.h> + +#if defined(_LIBCPP_WIN32API) +// This struct isn't defined in the normal Windows SDK, but only in the +// Windows Driver Kit. +struct LIBCPP_REPARSE_DATA_BUFFER { + unsigned long ReparseTag; + unsigned short ReparseDataLength; + unsigned short Reserved; + union { + struct { + unsigned short SubstituteNameOffset; + unsigned short SubstituteNameLength; + unsigned short PrintNameOffset; + unsigned short PrintNameLength; + unsigned long Flags; + wchar_t PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + unsigned short SubstituteNameOffset; + unsigned short SubstituteNameLength; + unsigned short PrintNameOffset; + unsigned short PrintNameLength; + wchar_t PathBuffer[1]; + } MountPointReparseBuffer; + struct { + unsigned char DataBuffer[1]; + } GenericReparseBuffer; + }; +}; +#endif + +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM + +namespace detail { +namespace { + +#if defined(_LIBCPP_WIN32API) + +// Various C runtime header sets provide more or less of these. As we +// provide our own implementation, undef all potential defines from the +// C runtime headers and provide a complete set of macros of our own. + +#undef _S_IFMT +#undef _S_IFDIR +#undef _S_IFCHR +#undef _S_IFIFO +#undef _S_IFREG +#undef _S_IFBLK +#undef _S_IFLNK +#undef _S_IFSOCK + +#define _S_IFMT 0xF000 +#define _S_IFDIR 0x4000 +#define _S_IFCHR 0x2000 +#define _S_IFIFO 0x1000 +#define _S_IFREG 0x8000 +#define _S_IFBLK 0x6000 +#define _S_IFLNK 0xA000 +#define _S_IFSOCK 0xC000 + +#undef S_ISDIR +#undef S_ISFIFO +#undef S_ISCHR +#undef S_ISREG +#undef S_ISLNK +#undef S_ISBLK +#undef S_ISSOCK + +#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) +#define S_ISCHR(m) (((m) & _S_IFMT) == _S_IFCHR) +#define S_ISFIFO(m) (((m) & _S_IFMT) == _S_IFIFO) +#define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) +#define S_ISBLK(m) (((m) & _S_IFMT) == _S_IFBLK) +#define S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK) +#define S_ISSOCK(m) (((m) & _S_IFMT) == _S_IFSOCK) + +#define O_NONBLOCK 0 + + +// There were 369 years and 89 leap days from the Windows epoch +// (1601) to the Unix epoch (1970). +#define FILE_TIME_OFFSET_SECS (uint64_t(369 * 365 + 89) * (24 * 60 * 60)) + +TimeSpec filetime_to_timespec(LARGE_INTEGER li) { + TimeSpec ret; + ret.tv_sec = li.QuadPart / 10000000 - FILE_TIME_OFFSET_SECS; + ret.tv_nsec = (li.QuadPart % 10000000) * 100; + return ret; +} + +TimeSpec filetime_to_timespec(FILETIME ft) { + LARGE_INTEGER li; + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + return filetime_to_timespec(li); +} + +FILETIME timespec_to_filetime(TimeSpec ts) { + LARGE_INTEGER li; + li.QuadPart = + ts.tv_nsec / 100 + (ts.tv_sec + FILE_TIME_OFFSET_SECS) * 10000000; + FILETIME ft; + ft.dwLowDateTime = li.LowPart; + ft.dwHighDateTime = li.HighPart; + return ft; +} + +int set_errno(int e = GetLastError()) { + errno = static_cast<int>(__win_err_to_errc(e)); + return -1; +} + +class WinHandle { +public: + WinHandle(const wchar_t *p, DWORD access, DWORD flags) { + h = CreateFileW( + p, access, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | flags, nullptr); + } + ~WinHandle() { + if (h != INVALID_HANDLE_VALUE) + CloseHandle(h); + } + operator HANDLE() const { return h; } + operator bool() const { return h != INVALID_HANDLE_VALUE; } + +private: + HANDLE h; +}; + +int stat_handle(HANDLE h, StatT *buf) { + FILE_BASIC_INFO basic; + if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic))) + return set_errno(); + memset(buf, 0, sizeof(*buf)); + buf->st_mtim = filetime_to_timespec(basic.LastWriteTime); + buf->st_atim = filetime_to_timespec(basic.LastAccessTime); + buf->st_mode = 0555; // Read-only + if (!(basic.FileAttributes & FILE_ATTRIBUTE_READONLY)) + buf->st_mode |= 0222; // Write + if (basic.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + buf->st_mode |= _S_IFDIR; + } else { + buf->st_mode |= _S_IFREG; + } + if (basic.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + FILE_ATTRIBUTE_TAG_INFO tag; + if (!GetFileInformationByHandleEx(h, FileAttributeTagInfo, &tag, + sizeof(tag))) + return set_errno(); + if (tag.ReparseTag == IO_REPARSE_TAG_SYMLINK) + buf->st_mode = (buf->st_mode & ~_S_IFMT) | _S_IFLNK; + } + FILE_STANDARD_INFO standard; + if (!GetFileInformationByHandleEx(h, FileStandardInfo, &standard, + sizeof(standard))) + return set_errno(); + buf->st_nlink = standard.NumberOfLinks; + buf->st_size = standard.EndOfFile.QuadPart; + BY_HANDLE_FILE_INFORMATION info; + if (!GetFileInformationByHandle(h, &info)) + return set_errno(); + buf->st_dev = info.dwVolumeSerialNumber; + memcpy(&buf->st_ino.id[0], &info.nFileIndexHigh, 4); + memcpy(&buf->st_ino.id[4], &info.nFileIndexLow, 4); + return 0; +} + +int stat_file(const wchar_t *path, StatT *buf, DWORD flags) { + WinHandle h(path, FILE_READ_ATTRIBUTES, flags); + if (!h) + return set_errno(); + int ret = stat_handle(h, buf); + return ret; +} + +int stat(const wchar_t *path, StatT *buf) { return stat_file(path, buf, 0); } + +int lstat(const wchar_t *path, StatT *buf) { + return stat_file(path, buf, FILE_FLAG_OPEN_REPARSE_POINT); +} + +int fstat(int fd, StatT *buf) { + HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); + return stat_handle(h, buf); +} + +int mkdir(const wchar_t *path, int permissions) { + (void)permissions; + return _wmkdir(path); +} + +int symlink_file_dir(const wchar_t *oldname, const wchar_t *newname, + bool is_dir) { + path dest(oldname); + dest.make_preferred(); + oldname = dest.c_str(); + DWORD flags = is_dir ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; + if (CreateSymbolicLinkW(newname, oldname, + flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) + return 0; + int e = GetLastError(); + if (e != ERROR_INVALID_PARAMETER) + return set_errno(e); + if (CreateSymbolicLinkW(newname, oldname, flags)) + return 0; + return set_errno(); +} + +int symlink_file(const wchar_t *oldname, const wchar_t *newname) { + return symlink_file_dir(oldname, newname, false); +} + +int symlink_dir(const wchar_t *oldname, const wchar_t *newname) { + return symlink_file_dir(oldname, newname, true); +} + +int link(const wchar_t *oldname, const wchar_t *newname) { + if (CreateHardLinkW(newname, oldname, nullptr)) + return 0; + return set_errno(); +} + +int remove(const wchar_t *path) { + detail::WinHandle h(path, DELETE, FILE_FLAG_OPEN_REPARSE_POINT); + if (!h) + return set_errno(); + FILE_DISPOSITION_INFO info; + info.DeleteFile = TRUE; + if (!SetFileInformationByHandle(h, FileDispositionInfo, &info, sizeof(info))) + return set_errno(); + return 0; +} + +int truncate_handle(HANDLE h, off_t length) { + LARGE_INTEGER size_param; + size_param.QuadPart = length; + if (!SetFilePointerEx(h, size_param, 0, FILE_BEGIN)) + return set_errno(); + if (!SetEndOfFile(h)) + return set_errno(); + return 0; +} + +int ftruncate(int fd, off_t length) { + HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); + return truncate_handle(h, length); +} + +int truncate(const wchar_t *path, off_t length) { + detail::WinHandle h(path, GENERIC_WRITE, 0); + if (!h) + return set_errno(); + return truncate_handle(h, length); +} + +int rename(const wchar_t *from, const wchar_t *to) { + if (!(MoveFileExW(from, to, + MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | + MOVEFILE_WRITE_THROUGH))) + return set_errno(); + return 0; +} + +template <class... Args> int open(const wchar_t *filename, Args... args) { + return _wopen(filename, args...); +} +int close(int fd) { return _close(fd); } +int chdir(const wchar_t *path) { return _wchdir(path); } + +struct StatVFS { + uint64_t f_frsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; +}; + +int statvfs(const wchar_t *p, StatVFS *buf) { + path dir = p; + while (true) { + error_code local_ec; + const file_status st = status(dir, local_ec); + if (!exists(st) || is_directory(st)) + break; + path parent = dir.parent_path(); + if (parent == dir) { + errno = ENOENT; + return -1; + } + dir = parent; + } + ULARGE_INTEGER free_bytes_available_to_caller, total_number_of_bytes, + total_number_of_free_bytes; + if (!GetDiskFreeSpaceExW(dir.c_str(), &free_bytes_available_to_caller, + &total_number_of_bytes, &total_number_of_free_bytes)) + return set_errno(); + buf->f_frsize = 1; + buf->f_blocks = total_number_of_bytes.QuadPart; + buf->f_bfree = total_number_of_free_bytes.QuadPart; + buf->f_bavail = free_bytes_available_to_caller.QuadPart; + return 0; +} + +wchar_t *getcwd(wchar_t *buff, size_t size) { return _wgetcwd(buff, size); } + +wchar_t *realpath(const wchar_t *path, wchar_t *resolved_name) { + // Only expected to be used with us allocating the buffer. + _LIBCPP_ASSERT(resolved_name == nullptr, + "Windows realpath() assumes a null resolved_name"); + + WinHandle h(path, FILE_READ_ATTRIBUTES, 0); + if (!h) { + set_errno(); + return nullptr; + } + size_t buff_size = MAX_PATH + 10; + std::unique_ptr<wchar_t, decltype(&::free)> buff( + static_cast<wchar_t *>(malloc(buff_size * sizeof(wchar_t))), &::free); + DWORD retval = GetFinalPathNameByHandleW( + h, buff.get(), buff_size, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); + if (retval > buff_size) { + buff_size = retval; + buff.reset(static_cast<wchar_t *>(malloc(buff_size * sizeof(wchar_t)))); + retval = GetFinalPathNameByHandleW(h, buff.get(), buff_size, + FILE_NAME_NORMALIZED | VOLUME_NAME_DOS); + } + if (!retval) { + set_errno(); + return nullptr; + } + wchar_t *ptr = buff.get(); + if (!wcsncmp(ptr, L"\\\\?\\", 4)) { + if (ptr[5] == ':') { // \\?\X: -> X: + memmove(&ptr[0], &ptr[4], (wcslen(&ptr[4]) + 1) * sizeof(wchar_t)); + } else if (!wcsncmp(&ptr[4], L"UNC\\", 4)) { // \\?\UNC\server -> \\server + wcscpy(&ptr[0], L"\\\\"); + memmove(&ptr[2], &ptr[8], (wcslen(&ptr[8]) + 1) * sizeof(wchar_t)); + } + } + return buff.release(); +} + +#define AT_FDCWD -1 +#define AT_SYMLINK_NOFOLLOW 1 +using ModeT = int; + +int fchmod_handle(HANDLE h, int perms) { + FILE_BASIC_INFO basic; + if (!GetFileInformationByHandleEx(h, FileBasicInfo, &basic, sizeof(basic))) + return set_errno(); + DWORD orig_attributes = basic.FileAttributes; + basic.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; + if ((perms & 0222) == 0) + basic.FileAttributes |= FILE_ATTRIBUTE_READONLY; + if (basic.FileAttributes != orig_attributes && + !SetFileInformationByHandle(h, FileBasicInfo, &basic, sizeof(basic))) + return set_errno(); + return 0; +} + +int fchmodat(int fd, const wchar_t *path, int perms, int flag) { + DWORD attributes = GetFileAttributesW(path); + if (attributes == INVALID_FILE_ATTRIBUTES) + return set_errno(); + if (attributes & FILE_ATTRIBUTE_REPARSE_POINT && + !(flag & AT_SYMLINK_NOFOLLOW)) { + // If the file is a symlink, and we are supposed to operate on the target + // of the symlink, we need to open a handle to it, without the + // FILE_FLAG_OPEN_REPARSE_POINT flag, to open the destination of the + // symlink, and operate on it via the handle. + detail::WinHandle h(path, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, 0); + if (!h) + return set_errno(); + return fchmod_handle(h, perms); + } else { + // For a non-symlink, or if operating on the symlink itself instead of + // its target, we can use SetFileAttributesW, saving a few calls. + DWORD orig_attributes = attributes; + attributes &= ~FILE_ATTRIBUTE_READONLY; + if ((perms & 0222) == 0) + attributes |= FILE_ATTRIBUTE_READONLY; + if (attributes != orig_attributes && !SetFileAttributesW(path, attributes)) + return set_errno(); + } + return 0; +} + +int fchmod(int fd, int perms) { + HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); + return fchmod_handle(h, perms); +} + +#define MAX_SYMLINK_SIZE MAXIMUM_REPARSE_DATA_BUFFER_SIZE +using SSizeT = ::int64_t; + +SSizeT readlink(const wchar_t *path, wchar_t *ret_buf, size_t bufsize) { + uint8_t buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + detail::WinHandle h(path, FILE_READ_ATTRIBUTES, FILE_FLAG_OPEN_REPARSE_POINT); + if (!h) + return set_errno(); + DWORD out; + if (!DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, nullptr, 0, buf, sizeof(buf), + &out, 0)) + return set_errno(); + const auto *reparse = reinterpret_cast<LIBCPP_REPARSE_DATA_BUFFER *>(buf); + size_t path_buf_offset = offsetof(LIBCPP_REPARSE_DATA_BUFFER, + SymbolicLinkReparseBuffer.PathBuffer[0]); + if (out < path_buf_offset) { + errno = EINVAL; + return -1; + } + if (reparse->ReparseTag != IO_REPARSE_TAG_SYMLINK) { + errno = EINVAL; + return -1; + } + const auto &symlink = reparse->SymbolicLinkReparseBuffer; + unsigned short name_offset, name_length; + if (symlink.PrintNameLength == 0) { + name_offset = symlink.SubstituteNameOffset; + name_length = symlink.SubstituteNameLength; + } else { + name_offset = symlink.PrintNameOffset; + name_length = symlink.PrintNameLength; + } + // name_offset/length are expressed in bytes, not in wchar_t + if (path_buf_offset + name_offset + name_length > out) { + errno = EINVAL; + return -1; + } + if (name_length / sizeof(wchar_t) > bufsize) { + errno = ENOMEM; + return -1; + } + memcpy(ret_buf, &symlink.PathBuffer[name_offset / sizeof(wchar_t)], + name_length); + return name_length / sizeof(wchar_t); +} + +#else +int symlink_file(const char *oldname, const char *newname) { + return ::symlink(oldname, newname); +} +int symlink_dir(const char *oldname, const char *newname) { + return ::symlink(oldname, newname); +} +using ::chdir; +using ::close; +using ::fchmod; +#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) +using ::fchmodat; +#endif +using ::fstat; +using ::ftruncate; +using ::getcwd; +using ::link; +using ::lstat; +using ::mkdir; +using ::open; +using ::readlink; +using ::realpath; +using ::remove; +using ::rename; +using ::stat; +using ::statvfs; +using ::truncate; + +#define O_BINARY 0 + +using StatVFS = struct statvfs; +using ModeT = ::mode_t; +using SSizeT = ::ssize_t; + +#endif + +} // namespace +} // end namespace detail + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // POSIX_COMPAT_H diff --git a/contrib/libs/cxxsupp/libcxx/src/format.cpp b/contrib/libs/cxxsupp/libcxx/src/format.cpp index 730eca7ec7..c36c20e60a 100644 --- a/contrib/libs/cxxsupp/libcxx/src/format.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/format.cpp @@ -1,19 +1,19 @@ -//===------------------------- format.cpp ---------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "format" - -_LIBCPP_BEGIN_NAMESPACE_STD - -#if _LIBCPP_STD_VER > 17 - -format_error::~format_error() noexcept = default; - -#endif //_LIBCPP_STD_VER > 17 - -_LIBCPP_END_NAMESPACE_STD +//===------------------------- format.cpp ---------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "format" + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +format_error::~format_error() noexcept = default; + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/functional.cpp b/contrib/libs/cxxsupp/libcxx/src/functional.cpp index f420f92aa8..cc5f43a9f2 100644 --- a/contrib/libs/cxxsupp/libcxx/src/functional.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/functional.cpp @@ -1,25 +1,25 @@ -//===----------------------- functional.cpp -------------------------------===// -// +//===----------------------- functional.cpp -------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "functional" - -_LIBCPP_BEGIN_NAMESPACE_STD - -#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION -bad_function_call::~bad_function_call() noexcept -{ -} - -const char* -bad_function_call::what() const noexcept -{ - return "std::bad_function_call"; -} -#endif - -_LIBCPP_END_NAMESPACE_STD +// +//===----------------------------------------------------------------------===// + +#include "functional" + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION +bad_function_call::~bad_function_call() noexcept +{ +} + +const char* +bad_function_call::what() const noexcept +{ + return "std::bad_function_call"; +} +#endif + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/future.cpp b/contrib/libs/cxxsupp/libcxx/src/future.cpp index d4749bd08c..4c59f89e56 100644 --- a/contrib/libs/cxxsupp/libcxx/src/future.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/future.cpp @@ -1,277 +1,277 @@ -//===------------------------- future.cpp ---------------------------------===// -// +//===------------------------- future.cpp ---------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "__config" - -#ifndef _LIBCPP_HAS_NO_THREADS - -#include "future" -#include "string" - -_LIBCPP_BEGIN_NAMESPACE_STD - -class _LIBCPP_HIDDEN __future_error_category - : public __do_message -{ -public: - virtual const char* name() const noexcept; - virtual string message(int ev) const; -}; - -const char* -__future_error_category::name() const noexcept -{ - return "future"; -} - -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wswitch" -#elif defined(__GNUC__) || defined(__GNUG__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wswitch" -#endif - -string -__future_error_category::message(int ev) const -{ - switch (static_cast<future_errc>(ev)) - { - case future_errc(0): // For backwards compatibility with C++11 (LWG 2056) - case future_errc::broken_promise: - return string("The associated promise has been destructed prior " - "to the associated state becoming ready."); - case future_errc::future_already_retrieved: - return string("The future has already been retrieved from " - "the promise or packaged_task."); - case future_errc::promise_already_satisfied: - return string("The state of the promise has already been set."); - case future_errc::no_state: - return string("Operation not permitted on an object without " - "an associated state."); - } - return string("unspecified future_errc value\n"); -} - -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) || defined(__GNUG__) -#pragma GCC diagnostic pop -#endif - -const error_category& -future_category() noexcept -{ - static __future_error_category __f; - return __f; -} - -future_error::future_error(error_code __ec) - : logic_error(__ec.message()), - __ec_(__ec) -{ -} - -future_error::~future_error() noexcept -{ -} - -void -__assoc_sub_state::__on_zero_shared() noexcept -{ - delete this; -} - -void -__assoc_sub_state::set_value() -{ - unique_lock<mutex> __lk(__mut_); - if (__has_value()) +// +//===----------------------------------------------------------------------===// + +#include "__config" + +#ifndef _LIBCPP_HAS_NO_THREADS + +#include "future" +#include "string" + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_HIDDEN __future_error_category + : public __do_message +{ +public: + virtual const char* name() const noexcept; + virtual string message(int ev) const; +}; + +const char* +__future_error_category::name() const noexcept +{ + return "future"; +} + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wswitch" +#elif defined(__GNUC__) || defined(__GNUG__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wswitch" +#endif + +string +__future_error_category::message(int ev) const +{ + switch (static_cast<future_errc>(ev)) + { + case future_errc(0): // For backwards compatibility with C++11 (LWG 2056) + case future_errc::broken_promise: + return string("The associated promise has been destructed prior " + "to the associated state becoming ready."); + case future_errc::future_already_retrieved: + return string("The future has already been retrieved from " + "the promise or packaged_task."); + case future_errc::promise_already_satisfied: + return string("The state of the promise has already been set."); + case future_errc::no_state: + return string("Operation not permitted on an object without " + "an associated state."); + } + return string("unspecified future_errc value\n"); +} + +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) || defined(__GNUG__) +#pragma GCC diagnostic pop +#endif + +const error_category& +future_category() noexcept +{ + static __future_error_category __f; + return __f; +} + +future_error::future_error(error_code __ec) + : logic_error(__ec.message()), + __ec_(__ec) +{ +} + +future_error::~future_error() noexcept +{ +} + +void +__assoc_sub_state::__on_zero_shared() noexcept +{ + delete this; +} + +void +__assoc_sub_state::set_value() +{ + unique_lock<mutex> __lk(__mut_); + if (__has_value()) __throw_future_error(future_errc::promise_already_satisfied); - __state_ |= __constructed | ready; - __cv_.notify_all(); -} - -void -__assoc_sub_state::set_value_at_thread_exit() -{ - unique_lock<mutex> __lk(__mut_); - if (__has_value()) + __state_ |= __constructed | ready; + __cv_.notify_all(); +} + +void +__assoc_sub_state::set_value_at_thread_exit() +{ + unique_lock<mutex> __lk(__mut_); + if (__has_value()) __throw_future_error(future_errc::promise_already_satisfied); - __state_ |= __constructed; - __thread_local_data()->__make_ready_at_thread_exit(this); -} - -void -__assoc_sub_state::set_exception(exception_ptr __p) -{ - unique_lock<mutex> __lk(__mut_); - if (__has_value()) + __state_ |= __constructed; + __thread_local_data()->__make_ready_at_thread_exit(this); +} + +void +__assoc_sub_state::set_exception(exception_ptr __p) +{ + unique_lock<mutex> __lk(__mut_); + if (__has_value()) __throw_future_error(future_errc::promise_already_satisfied); - __exception_ = __p; - __state_ |= ready; - __cv_.notify_all(); -} - -void -__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) -{ - unique_lock<mutex> __lk(__mut_); - if (__has_value()) + __exception_ = __p; + __state_ |= ready; + __cv_.notify_all(); +} + +void +__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) +{ + unique_lock<mutex> __lk(__mut_); + if (__has_value()) __throw_future_error(future_errc::promise_already_satisfied); - __exception_ = __p; - __thread_local_data()->__make_ready_at_thread_exit(this); -} - -void -__assoc_sub_state::__make_ready() -{ - unique_lock<mutex> __lk(__mut_); - __state_ |= ready; - __cv_.notify_all(); -} - -void -__assoc_sub_state::copy() -{ - unique_lock<mutex> __lk(__mut_); - __sub_wait(__lk); - if (__exception_ != nullptr) - rethrow_exception(__exception_); -} - -void -__assoc_sub_state::wait() -{ - unique_lock<mutex> __lk(__mut_); - __sub_wait(__lk); -} - -void -__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) -{ - if (!__is_ready()) - { - if (__state_ & static_cast<unsigned>(deferred)) - { - __state_ &= ~static_cast<unsigned>(deferred); - __lk.unlock(); - __execute(); - } - else - while (!__is_ready()) - __cv_.wait(__lk); - } -} - -void -__assoc_sub_state::__execute() -{ + __exception_ = __p; + __thread_local_data()->__make_ready_at_thread_exit(this); +} + +void +__assoc_sub_state::__make_ready() +{ + unique_lock<mutex> __lk(__mut_); + __state_ |= ready; + __cv_.notify_all(); +} + +void +__assoc_sub_state::copy() +{ + unique_lock<mutex> __lk(__mut_); + __sub_wait(__lk); + if (__exception_ != nullptr) + rethrow_exception(__exception_); +} + +void +__assoc_sub_state::wait() +{ + unique_lock<mutex> __lk(__mut_); + __sub_wait(__lk); +} + +void +__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) +{ + if (!__is_ready()) + { + if (__state_ & static_cast<unsigned>(deferred)) + { + __state_ &= ~static_cast<unsigned>(deferred); + __lk.unlock(); + __execute(); + } + else + while (!__is_ready()) + __cv_.wait(__lk); + } +} + +void +__assoc_sub_state::__execute() +{ __throw_future_error(future_errc::no_state); -} - -future<void>::future(__assoc_sub_state* __state) - : __state_(__state) -{ +} + +future<void>::future(__assoc_sub_state* __state) + : __state_(__state) +{ __state_->__attach_future(); -} - -future<void>::~future() -{ - if (__state_) - __state_->__release_shared(); -} - -void -future<void>::get() -{ - unique_ptr<__shared_count, __release_shared_count> __(__state_); - __assoc_sub_state* __s = __state_; - __state_ = nullptr; - __s->copy(); -} - -promise<void>::promise() - : __state_(new __assoc_sub_state) -{ -} - -promise<void>::~promise() -{ - if (__state_) - { -#ifndef _LIBCPP_NO_EXCEPTIONS - if (!__state_->__has_value() && __state_->use_count() > 1) - __state_->set_exception(make_exception_ptr( - future_error(make_error_code(future_errc::broken_promise)) - )); -#endif // _LIBCPP_NO_EXCEPTIONS - __state_->__release_shared(); - } -} - -future<void> -promise<void>::get_future() -{ - if (__state_ == nullptr) +} + +future<void>::~future() +{ + if (__state_) + __state_->__release_shared(); +} + +void +future<void>::get() +{ + unique_ptr<__shared_count, __release_shared_count> __(__state_); + __assoc_sub_state* __s = __state_; + __state_ = nullptr; + __s->copy(); +} + +promise<void>::promise() + : __state_(new __assoc_sub_state) +{ +} + +promise<void>::~promise() +{ + if (__state_) + { +#ifndef _LIBCPP_NO_EXCEPTIONS + if (!__state_->__has_value() && __state_->use_count() > 1) + __state_->set_exception(make_exception_ptr( + future_error(make_error_code(future_errc::broken_promise)) + )); +#endif // _LIBCPP_NO_EXCEPTIONS + __state_->__release_shared(); + } +} + +future<void> +promise<void>::get_future() +{ + if (__state_ == nullptr) __throw_future_error(future_errc::no_state); - return future<void>(__state_); -} - -void -promise<void>::set_value() -{ - if (__state_ == nullptr) + return future<void>(__state_); +} + +void +promise<void>::set_value() +{ + if (__state_ == nullptr) __throw_future_error(future_errc::no_state); - __state_->set_value(); -} - -void -promise<void>::set_exception(exception_ptr __p) -{ - if (__state_ == nullptr) + __state_->set_value(); +} + +void +promise<void>::set_exception(exception_ptr __p) +{ + if (__state_ == nullptr) __throw_future_error(future_errc::no_state); - __state_->set_exception(__p); -} - -void -promise<void>::set_value_at_thread_exit() -{ - if (__state_ == nullptr) + __state_->set_exception(__p); +} + +void +promise<void>::set_value_at_thread_exit() +{ + if (__state_ == nullptr) __throw_future_error(future_errc::no_state); - __state_->set_value_at_thread_exit(); -} - -void -promise<void>::set_exception_at_thread_exit(exception_ptr __p) -{ - if (__state_ == nullptr) + __state_->set_value_at_thread_exit(); +} + +void +promise<void>::set_exception_at_thread_exit(exception_ptr __p) +{ + if (__state_ == nullptr) __throw_future_error(future_errc::no_state); - __state_->set_exception_at_thread_exit(__p); -} - -shared_future<void>::~shared_future() -{ - if (__state_) - __state_->__release_shared(); -} - -shared_future<void>& -shared_future<void>::operator=(const shared_future& __rhs) -{ - if (__rhs.__state_) - __rhs.__state_->__add_shared(); - if (__state_) - __state_->__release_shared(); - __state_ = __rhs.__state_; - return *this; -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !_LIBCPP_HAS_NO_THREADS + __state_->set_exception_at_thread_exit(__p); +} + +shared_future<void>::~shared_future() +{ + if (__state_) + __state_->__release_shared(); +} + +shared_future<void>& +shared_future<void>::operator=(const shared_future& __rhs) +{ + if (__rhs.__state_) + __rhs.__state_->__add_shared(); + if (__state_) + __state_->__release_shared(); + __state_ = __rhs.__state_; + return *this; +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !_LIBCPP_HAS_NO_THREADS diff --git a/contrib/libs/cxxsupp/libcxx/src/hash.cpp b/contrib/libs/cxxsupp/libcxx/src/hash.cpp index fec31a6fba..89bb736c86 100644 --- a/contrib/libs/cxxsupp/libcxx/src/hash.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/hash.cpp @@ -1,561 +1,561 @@ -//===-------------------------- hash.cpp ----------------------------------===// -// +//===-------------------------- hash.cpp ----------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "__hash_table" -#include "algorithm" -#include "stdexcept" -#include "type_traits" - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -namespace { - -// handle all next_prime(i) for i in [1, 210), special case 0 -const unsigned small_primes[] = -{ - 0, - 2, - 3, - 5, - 7, - 11, - 13, - 17, - 19, - 23, - 29, - 31, - 37, - 41, - 43, - 47, - 53, - 59, - 61, - 67, - 71, - 73, - 79, - 83, - 89, - 97, - 101, - 103, - 107, - 109, - 113, - 127, - 131, - 137, - 139, - 149, - 151, - 157, - 163, - 167, - 173, - 179, - 181, - 191, - 193, - 197, - 199, - 211 -}; - -// potential primes = 210*k + indices[i], k >= 1 -// these numbers are not divisible by 2, 3, 5 or 7 -// (or any integer 2 <= j <= 10 for that matter). -const unsigned indices[] = -{ - 1, - 11, - 13, - 17, - 19, - 23, - 29, - 31, - 37, - 41, - 43, - 47, - 53, - 59, - 61, - 67, - 71, - 73, - 79, - 83, - 89, - 97, - 101, - 103, - 107, - 109, - 113, - 121, - 127, - 131, - 137, - 139, - 143, - 149, - 151, - 157, - 163, - 167, - 169, - 173, - 179, - 181, - 187, - 191, - 193, - 197, - 199, - 209 -}; - -} - -// Returns: If n == 0, returns 0. Else returns the lowest prime number that -// is greater than or equal to n. -// -// The algorithm creates a list of small primes, plus an open-ended list of -// potential primes. All prime numbers are potential prime numbers. However -// some potential prime numbers are not prime. In an ideal world, all potential -// prime numbers would be prime. Candidate prime numbers are chosen as the next -// highest potential prime. Then this number is tested for prime by dividing it -// by all potential prime numbers less than the sqrt of the candidate. -// -// This implementation defines potential primes as those numbers not divisible -// by 2, 3, 5, and 7. Other (common) implementations define potential primes -// as those not divisible by 2. A few other implementations define potential -// primes as those not divisible by 2 or 3. By raising the number of small -// primes which the potential prime is not divisible by, the set of potential -// primes more closely approximates the set of prime numbers. And thus there -// are fewer potential primes to search, and fewer potential primes to divide -// against. - -template <size_t _Sz = sizeof(size_t)> -inline _LIBCPP_INLINE_VISIBILITY -typename enable_if<_Sz == 4, void>::type -__check_for_overflow(size_t N) -{ - if (N > 0xFFFFFFFB) - __throw_overflow_error("__next_prime overflow"); -} - -template <size_t _Sz = sizeof(size_t)> -inline _LIBCPP_INLINE_VISIBILITY -typename enable_if<_Sz == 8, void>::type -__check_for_overflow(size_t N) -{ - if (N > 0xFFFFFFFFFFFFFFC5ull) - __throw_overflow_error("__next_prime overflow"); -} - -size_t -__next_prime(size_t n) -{ - const size_t L = 210; - const size_t N = sizeof(small_primes) / sizeof(small_primes[0]); - // If n is small enough, search in small_primes - if (n <= small_primes[N-1]) - return *std::lower_bound(small_primes, small_primes + N, n); - // Else n > largest small_primes - // Check for overflow - __check_for_overflow(n); - // Start searching list of potential primes: L * k0 + indices[in] - const size_t M = sizeof(indices) / sizeof(indices[0]); - // Select first potential prime >= n - // Known a-priori n >= L - size_t k0 = n / L; - size_t in = static_cast<size_t>(std::lower_bound(indices, indices + M, n - k0 * L) - - indices); - n = L * k0 + indices[in]; - while (true) - { - // Divide n by all primes or potential primes (i) until: - // 1. The division is even, so try next potential prime. - // 2. The i > sqrt(n), in which case n is prime. - // It is known a-priori that n is not divisible by 2, 3, 5 or 7, - // so don't test those (j == 5 -> divide by 11 first). And the - // potential primes start with 211, so don't test against the last - // small prime. - for (size_t j = 5; j < N - 1; ++j) - { - const std::size_t p = small_primes[j]; - const std::size_t q = n / p; - if (q < p) - return n; - if (n == q * p) - goto next; - } - // n wasn't divisible by small primes, try potential primes - { - size_t i = 211; - while (true) - { - std::size_t q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 10; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 8; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 8; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 6; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 4; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 2; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - i += 10; - q = n / i; - if (q < i) - return n; - if (n == q * i) - break; - - // This will loop i to the next "plane" of potential primes - i += 2; - } - } -next: - // n is not prime. Increment n to next potential prime. - if (++in == M) - { - ++k0; - in = 0; - } - n = L * k0 + indices[in]; - } -} - -_LIBCPP_END_NAMESPACE_STD +// +//===----------------------------------------------------------------------===// + +#include "__hash_table" +#include "algorithm" +#include "stdexcept" +#include "type_traits" + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace { + +// handle all next_prime(i) for i in [1, 210), special case 0 +const unsigned small_primes[] = +{ + 0, + 2, + 3, + 5, + 7, + 11, + 13, + 17, + 19, + 23, + 29, + 31, + 37, + 41, + 43, + 47, + 53, + 59, + 61, + 67, + 71, + 73, + 79, + 83, + 89, + 97, + 101, + 103, + 107, + 109, + 113, + 127, + 131, + 137, + 139, + 149, + 151, + 157, + 163, + 167, + 173, + 179, + 181, + 191, + 193, + 197, + 199, + 211 +}; + +// potential primes = 210*k + indices[i], k >= 1 +// these numbers are not divisible by 2, 3, 5 or 7 +// (or any integer 2 <= j <= 10 for that matter). +const unsigned indices[] = +{ + 1, + 11, + 13, + 17, + 19, + 23, + 29, + 31, + 37, + 41, + 43, + 47, + 53, + 59, + 61, + 67, + 71, + 73, + 79, + 83, + 89, + 97, + 101, + 103, + 107, + 109, + 113, + 121, + 127, + 131, + 137, + 139, + 143, + 149, + 151, + 157, + 163, + 167, + 169, + 173, + 179, + 181, + 187, + 191, + 193, + 197, + 199, + 209 +}; + +} + +// Returns: If n == 0, returns 0. Else returns the lowest prime number that +// is greater than or equal to n. +// +// The algorithm creates a list of small primes, plus an open-ended list of +// potential primes. All prime numbers are potential prime numbers. However +// some potential prime numbers are not prime. In an ideal world, all potential +// prime numbers would be prime. Candidate prime numbers are chosen as the next +// highest potential prime. Then this number is tested for prime by dividing it +// by all potential prime numbers less than the sqrt of the candidate. +// +// This implementation defines potential primes as those numbers not divisible +// by 2, 3, 5, and 7. Other (common) implementations define potential primes +// as those not divisible by 2. A few other implementations define potential +// primes as those not divisible by 2 or 3. By raising the number of small +// primes which the potential prime is not divisible by, the set of potential +// primes more closely approximates the set of prime numbers. And thus there +// are fewer potential primes to search, and fewer potential primes to divide +// against. + +template <size_t _Sz = sizeof(size_t)> +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if<_Sz == 4, void>::type +__check_for_overflow(size_t N) +{ + if (N > 0xFFFFFFFB) + __throw_overflow_error("__next_prime overflow"); +} + +template <size_t _Sz = sizeof(size_t)> +inline _LIBCPP_INLINE_VISIBILITY +typename enable_if<_Sz == 8, void>::type +__check_for_overflow(size_t N) +{ + if (N > 0xFFFFFFFFFFFFFFC5ull) + __throw_overflow_error("__next_prime overflow"); +} + +size_t +__next_prime(size_t n) +{ + const size_t L = 210; + const size_t N = sizeof(small_primes) / sizeof(small_primes[0]); + // If n is small enough, search in small_primes + if (n <= small_primes[N-1]) + return *std::lower_bound(small_primes, small_primes + N, n); + // Else n > largest small_primes + // Check for overflow + __check_for_overflow(n); + // Start searching list of potential primes: L * k0 + indices[in] + const size_t M = sizeof(indices) / sizeof(indices[0]); + // Select first potential prime >= n + // Known a-priori n >= L + size_t k0 = n / L; + size_t in = static_cast<size_t>(std::lower_bound(indices, indices + M, n - k0 * L) + - indices); + n = L * k0 + indices[in]; + while (true) + { + // Divide n by all primes or potential primes (i) until: + // 1. The division is even, so try next potential prime. + // 2. The i > sqrt(n), in which case n is prime. + // It is known a-priori that n is not divisible by 2, 3, 5 or 7, + // so don't test those (j == 5 -> divide by 11 first). And the + // potential primes start with 211, so don't test against the last + // small prime. + for (size_t j = 5; j < N - 1; ++j) + { + const std::size_t p = small_primes[j]; + const std::size_t q = n / p; + if (q < p) + return n; + if (n == q * p) + goto next; + } + // n wasn't divisible by small primes, try potential primes + { + size_t i = 211; + while (true) + { + std::size_t q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 10; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 8; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 8; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 6; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 4; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 2; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + i += 10; + q = n / i; + if (q < i) + return n; + if (n == q * i) + break; + + // This will loop i to the next "plane" of potential primes + i += 2; + } + } +next: + // n is not prime. Increment n to next potential prime. + if (++in == M) + { + ++k0; + in = 0; + } + n = L * k0 + indices[in]; + } +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/include/apple_availability.h b/contrib/libs/cxxsupp/libcxx/src/include/apple_availability.h index c12d346a2d..0f999d3fea 100644 --- a/contrib/libs/cxxsupp/libcxx/src/include/apple_availability.h +++ b/contrib/libs/cxxsupp/libcxx/src/include/apple_availability.h @@ -1,51 +1,51 @@ -//===------------------------ apple_availability.h ------------------------===// -// +//===------------------------ apple_availability.h ------------------------===// +// // 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_SRC_INCLUDE_APPLE_AVAILABILITY_H -#define _LIBCPP_SRC_INCLUDE_APPLE_AVAILABILITY_H - -#if defined(__APPLE__) - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101300 -#define _LIBCPP_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 110000 -#define _LIBCPP_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 110000 -#define _LIBCPP_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 40000 -#define _LIBCPP_USE_UTIMENSAT -#endif -#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101500 -#define _LIBCPP_USE_ULOCK -#endif -#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 130000 -#define _LIBCPP_USE_ULOCK -#endif -#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 130000 -#define _LIBCPP_USE_ULOCK -#endif -#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 60000 -#define _LIBCPP_USE_ULOCK -#endif -#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ - -#endif // __APPLE__ - -#endif // _LIBCPP_SRC_INCLUDE_APPLE_AVAILABILITY_H +// +//===----------------------------------------------------------------------===// +#ifndef _LIBCPP_SRC_INCLUDE_APPLE_AVAILABILITY_H +#define _LIBCPP_SRC_INCLUDE_APPLE_AVAILABILITY_H + +#if defined(__APPLE__) + +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101300 +#define _LIBCPP_USE_UTIMENSAT +#endif +#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 110000 +#define _LIBCPP_USE_UTIMENSAT +#endif +#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 110000 +#define _LIBCPP_USE_UTIMENSAT +#endif +#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 40000 +#define _LIBCPP_USE_UTIMENSAT +#endif +#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ + +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101500 +#define _LIBCPP_USE_ULOCK +#endif +#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 130000 +#define _LIBCPP_USE_ULOCK +#endif +#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 130000 +#define _LIBCPP_USE_ULOCK +#endif +#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 60000 +#define _LIBCPP_USE_ULOCK +#endif +#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ + +#endif // __APPLE__ + +#endif // _LIBCPP_SRC_INCLUDE_APPLE_AVAILABILITY_H diff --git a/contrib/libs/cxxsupp/libcxx/src/include/atomic_support.h b/contrib/libs/cxxsupp/libcxx/src/include/atomic_support.h index 6785232fe0..5a745a2f00 100644 --- a/contrib/libs/cxxsupp/libcxx/src/include/atomic_support.h +++ b/contrib/libs/cxxsupp/libcxx/src/include/atomic_support.h @@ -1,176 +1,176 @@ -//===----------------------------------------------------------------------===//// -// +//===----------------------------------------------------------------------===//// +// // 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 ATOMIC_SUPPORT_H -#define ATOMIC_SUPPORT_H - -#include "__config" -#include "memory" // for __libcpp_relaxed_load - -#if defined(__clang__) && __has_builtin(__atomic_load_n) \ - && __has_builtin(__atomic_store_n) \ - && __has_builtin(__atomic_add_fetch) \ - && __has_builtin(__atomic_exchange_n) \ - && __has_builtin(__atomic_compare_exchange_n) \ - && defined(__ATOMIC_RELAXED) \ - && defined(__ATOMIC_CONSUME) \ - && defined(__ATOMIC_ACQUIRE) \ - && defined(__ATOMIC_RELEASE) \ - && defined(__ATOMIC_ACQ_REL) \ - && defined(__ATOMIC_SEQ_CST) -# define _LIBCPP_HAS_ATOMIC_BUILTINS -#elif defined(_LIBCPP_COMPILER_GCC) -# define _LIBCPP_HAS_ATOMIC_BUILTINS -#endif - -#if !defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS) -# if defined(_LIBCPP_WARNING) - _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported") -# else -# warning Building libc++ without __atomic builtins is unsupported -# endif -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -namespace { - -#if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS) - -enum __libcpp_atomic_order { - _AO_Relaxed = __ATOMIC_RELAXED, - _AO_Consume = __ATOMIC_CONSUME, - _AO_Acquire = __ATOMIC_ACQUIRE, - _AO_Release = __ATOMIC_RELEASE, - _AO_Acq_Rel = __ATOMIC_ACQ_REL, - _AO_Seq = __ATOMIC_SEQ_CST -}; - -template <class _ValueType, class _FromType> -inline _LIBCPP_INLINE_VISIBILITY -void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, - int __order = _AO_Seq) -{ - __atomic_store_n(__dest, __val, __order); -} - -template <class _ValueType, class _FromType> -inline _LIBCPP_INLINE_VISIBILITY -void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) -{ - __atomic_store_n(__dest, __val, _AO_Relaxed); -} - -template <class _ValueType> -inline _LIBCPP_INLINE_VISIBILITY -_ValueType __libcpp_atomic_load(_ValueType const* __val, - int __order = _AO_Seq) -{ - return __atomic_load_n(__val, __order); -} - -template <class _ValueType, class _AddType> -inline _LIBCPP_INLINE_VISIBILITY -_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, - int __order = _AO_Seq) -{ - return __atomic_add_fetch(__val, __a, __order); -} - -template <class _ValueType> -inline _LIBCPP_INLINE_VISIBILITY -_ValueType __libcpp_atomic_exchange(_ValueType* __target, - _ValueType __value, int __order = _AO_Seq) -{ - return __atomic_exchange_n(__target, __value, __order); -} - -template <class _ValueType> -inline _LIBCPP_INLINE_VISIBILITY -bool __libcpp_atomic_compare_exchange(_ValueType* __val, - _ValueType* __expected, _ValueType __after, - int __success_order = _AO_Seq, - int __fail_order = _AO_Seq) -{ - return __atomic_compare_exchange_n(__val, __expected, __after, true, - __success_order, __fail_order); -} - -#else // _LIBCPP_HAS_NO_THREADS - -enum __libcpp_atomic_order { - _AO_Relaxed, - _AO_Consume, - _AO_Acquire, - _AO_Release, - _AO_Acq_Rel, - _AO_Seq -}; - -template <class _ValueType, class _FromType> -inline _LIBCPP_INLINE_VISIBILITY -void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, - int = 0) -{ - *__dest = __val; -} - -template <class _ValueType, class _FromType> -inline _LIBCPP_INLINE_VISIBILITY -void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) -{ - *__dest = __val; -} - -template <class _ValueType> -inline _LIBCPP_INLINE_VISIBILITY -_ValueType __libcpp_atomic_load(_ValueType const* __val, - int = 0) -{ - return *__val; -} - -template <class _ValueType, class _AddType> -inline _LIBCPP_INLINE_VISIBILITY -_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, - int = 0) -{ - return *__val += __a; -} - -template <class _ValueType> -inline _LIBCPP_INLINE_VISIBILITY -_ValueType __libcpp_atomic_exchange(_ValueType* __target, - _ValueType __value, int = _AO_Seq) -{ - _ValueType old = *__target; - *__target = __value; - return old; -} - -template <class _ValueType> -inline _LIBCPP_INLINE_VISIBILITY -bool __libcpp_atomic_compare_exchange(_ValueType* __val, - _ValueType* __expected, _ValueType __after, - int = 0, int = 0) -{ - if (*__val == *__expected) { - *__val = __after; - return true; - } - *__expected = *__val; - return false; -} - -#endif // _LIBCPP_HAS_NO_THREADS - -} // end namespace - -_LIBCPP_END_NAMESPACE_STD - -#endif // ATOMIC_SUPPORT_H +// +//===----------------------------------------------------------------------===//// + +#ifndef ATOMIC_SUPPORT_H +#define ATOMIC_SUPPORT_H + +#include "__config" +#include "memory" // for __libcpp_relaxed_load + +#if defined(__clang__) && __has_builtin(__atomic_load_n) \ + && __has_builtin(__atomic_store_n) \ + && __has_builtin(__atomic_add_fetch) \ + && __has_builtin(__atomic_exchange_n) \ + && __has_builtin(__atomic_compare_exchange_n) \ + && defined(__ATOMIC_RELAXED) \ + && defined(__ATOMIC_CONSUME) \ + && defined(__ATOMIC_ACQUIRE) \ + && defined(__ATOMIC_RELEASE) \ + && defined(__ATOMIC_ACQ_REL) \ + && defined(__ATOMIC_SEQ_CST) +# define _LIBCPP_HAS_ATOMIC_BUILTINS +#elif defined(_LIBCPP_COMPILER_GCC) +# define _LIBCPP_HAS_ATOMIC_BUILTINS +#endif + +#if !defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS) +# if defined(_LIBCPP_WARNING) + _LIBCPP_WARNING("Building libc++ without __atomic builtins is unsupported") +# else +# warning Building libc++ without __atomic builtins is unsupported +# endif +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace { + +#if defined(_LIBCPP_HAS_ATOMIC_BUILTINS) && !defined(_LIBCPP_HAS_NO_THREADS) + +enum __libcpp_atomic_order { + _AO_Relaxed = __ATOMIC_RELAXED, + _AO_Consume = __ATOMIC_CONSUME, + _AO_Acquire = __ATOMIC_ACQUIRE, + _AO_Release = __ATOMIC_RELEASE, + _AO_Acq_Rel = __ATOMIC_ACQ_REL, + _AO_Seq = __ATOMIC_SEQ_CST +}; + +template <class _ValueType, class _FromType> +inline _LIBCPP_INLINE_VISIBILITY +void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, + int __order = _AO_Seq) +{ + __atomic_store_n(__dest, __val, __order); +} + +template <class _ValueType, class _FromType> +inline _LIBCPP_INLINE_VISIBILITY +void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) +{ + __atomic_store_n(__dest, __val, _AO_Relaxed); +} + +template <class _ValueType> +inline _LIBCPP_INLINE_VISIBILITY +_ValueType __libcpp_atomic_load(_ValueType const* __val, + int __order = _AO_Seq) +{ + return __atomic_load_n(__val, __order); +} + +template <class _ValueType, class _AddType> +inline _LIBCPP_INLINE_VISIBILITY +_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, + int __order = _AO_Seq) +{ + return __atomic_add_fetch(__val, __a, __order); +} + +template <class _ValueType> +inline _LIBCPP_INLINE_VISIBILITY +_ValueType __libcpp_atomic_exchange(_ValueType* __target, + _ValueType __value, int __order = _AO_Seq) +{ + return __atomic_exchange_n(__target, __value, __order); +} + +template <class _ValueType> +inline _LIBCPP_INLINE_VISIBILITY +bool __libcpp_atomic_compare_exchange(_ValueType* __val, + _ValueType* __expected, _ValueType __after, + int __success_order = _AO_Seq, + int __fail_order = _AO_Seq) +{ + return __atomic_compare_exchange_n(__val, __expected, __after, true, + __success_order, __fail_order); +} + +#else // _LIBCPP_HAS_NO_THREADS + +enum __libcpp_atomic_order { + _AO_Relaxed, + _AO_Consume, + _AO_Acquire, + _AO_Release, + _AO_Acq_Rel, + _AO_Seq +}; + +template <class _ValueType, class _FromType> +inline _LIBCPP_INLINE_VISIBILITY +void __libcpp_atomic_store(_ValueType* __dest, _FromType __val, + int = 0) +{ + *__dest = __val; +} + +template <class _ValueType, class _FromType> +inline _LIBCPP_INLINE_VISIBILITY +void __libcpp_relaxed_store(_ValueType* __dest, _FromType __val) +{ + *__dest = __val; +} + +template <class _ValueType> +inline _LIBCPP_INLINE_VISIBILITY +_ValueType __libcpp_atomic_load(_ValueType const* __val, + int = 0) +{ + return *__val; +} + +template <class _ValueType, class _AddType> +inline _LIBCPP_INLINE_VISIBILITY +_ValueType __libcpp_atomic_add(_ValueType* __val, _AddType __a, + int = 0) +{ + return *__val += __a; +} + +template <class _ValueType> +inline _LIBCPP_INLINE_VISIBILITY +_ValueType __libcpp_atomic_exchange(_ValueType* __target, + _ValueType __value, int = _AO_Seq) +{ + _ValueType old = *__target; + *__target = __value; + return old; +} + +template <class _ValueType> +inline _LIBCPP_INLINE_VISIBILITY +bool __libcpp_atomic_compare_exchange(_ValueType* __val, + _ValueType* __expected, _ValueType __after, + int = 0, int = 0) +{ + if (*__val == *__expected) { + *__val = __after; + return true; + } + *__expected = *__val; + return false; +} + +#endif // _LIBCPP_HAS_NO_THREADS + +} // end namespace + +_LIBCPP_END_NAMESPACE_STD + +#endif // ATOMIC_SUPPORT_H diff --git a/contrib/libs/cxxsupp/libcxx/src/include/config_elast.h b/contrib/libs/cxxsupp/libcxx/src/include/config_elast.h index 6798ea30c0..7880c733fb 100644 --- a/contrib/libs/cxxsupp/libcxx/src/include/config_elast.h +++ b/contrib/libs/cxxsupp/libcxx/src/include/config_elast.h @@ -1,49 +1,49 @@ -//===----------------------- config_elast.h -------------------------------===// -// +//===----------------------- config_elast.h -------------------------------===// +// // 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_CONFIG_ELAST -#define _LIBCPP_CONFIG_ELAST - -#include <__config> - -#if defined(_LIBCPP_MSVCRT_LIKE) -#include <stdlib.h> -#else -#include <errno.h> -#endif - -// Note: _LIBCPP_ELAST needs to be defined only on platforms -// where strerror/strerror_r can't handle out-of-range errno values. -#if defined(ELAST) -#define _LIBCPP_ELAST ELAST -#elif defined(_NEWLIB_VERSION) -#define _LIBCPP_ELAST __ELASTERROR -#elif defined(__NuttX__) -// No _LIBCPP_ELAST needed on NuttX -#elif defined(__Fuchsia__) -// No _LIBCPP_ELAST needed on Fuchsia -#elif defined(__wasi__) -// No _LIBCPP_ELAST needed on WASI -#elif defined(__linux__) || defined(_LIBCPP_HAS_MUSL_LIBC) -#define _LIBCPP_ELAST 4095 -#elif defined(__APPLE__) -// No _LIBCPP_ELAST needed on Apple -#elif defined(__sun__) -#define _LIBCPP_ELAST ESTALE -#elif defined(__MVS__) -#define _LIBCPP_ELAST 1160 -#elif defined(_LIBCPP_MSVCRT_LIKE) -#define _LIBCPP_ELAST (_sys_nerr - 1) -#elif defined(_AIX) -#define _LIBCPP_ELAST 127 -#else -// Warn here so that the person doing the libcxx port has an easier time: -#warning ELAST for this platform not yet implemented -#endif - -#endif // _LIBCPP_CONFIG_ELAST +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_CONFIG_ELAST +#define _LIBCPP_CONFIG_ELAST + +#include <__config> + +#if defined(_LIBCPP_MSVCRT_LIKE) +#include <stdlib.h> +#else +#include <errno.h> +#endif + +// Note: _LIBCPP_ELAST needs to be defined only on platforms +// where strerror/strerror_r can't handle out-of-range errno values. +#if defined(ELAST) +#define _LIBCPP_ELAST ELAST +#elif defined(_NEWLIB_VERSION) +#define _LIBCPP_ELAST __ELASTERROR +#elif defined(__NuttX__) +// No _LIBCPP_ELAST needed on NuttX +#elif defined(__Fuchsia__) +// No _LIBCPP_ELAST needed on Fuchsia +#elif defined(__wasi__) +// No _LIBCPP_ELAST needed on WASI +#elif defined(__linux__) || defined(_LIBCPP_HAS_MUSL_LIBC) +#define _LIBCPP_ELAST 4095 +#elif defined(__APPLE__) +// No _LIBCPP_ELAST needed on Apple +#elif defined(__sun__) +#define _LIBCPP_ELAST ESTALE +#elif defined(__MVS__) +#define _LIBCPP_ELAST 1160 +#elif defined(_LIBCPP_MSVCRT_LIKE) +#define _LIBCPP_ELAST (_sys_nerr - 1) +#elif defined(_AIX) +#define _LIBCPP_ELAST 127 +#else +// Warn here so that the person doing the libcxx port has an easier time: +#warning ELAST for this platform not yet implemented +#endif + +#endif // _LIBCPP_CONFIG_ELAST diff --git a/contrib/libs/cxxsupp/libcxx/src/include/refstring.h b/contrib/libs/cxxsupp/libcxx/src/include/refstring.h index d3cec926f7..3edd240a5d 100644 --- a/contrib/libs/cxxsupp/libcxx/src/include/refstring.h +++ b/contrib/libs/cxxsupp/libcxx/src/include/refstring.h @@ -1,167 +1,167 @@ -//===------------------------ __refstring ---------------------------------===// -// +//===------------------------ __refstring ---------------------------------===// +// // 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_REFSTRING_H -#define _LIBCPP_REFSTRING_H - -#include <__config> -#include <stdexcept> -#include <cstddef> -#include <cstring> - -#if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_USE_ATOMIC) -#define _LIBCPP_USE_ATOMIC -#include <atomic> -#else -#include "atomic_support.h" -#endif - -// MacOS and iOS used to ship with libstdc++, and still support old applications -// linking against libstdc++. The libc++ and libstdc++ exceptions are supposed -// to be ABI compatible, such that they can be thrown from one library and caught -// in the other. -// -// For that reason, we must look for libstdc++ in the same process and if found, -// check the string stored in the exception object to see if it is the GCC empty -// string singleton before manipulating the reference count. This is done so that -// if an exception is created with a zero-length string in libstdc++, libc++abi -// won't try to delete the memory. -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \ - defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -# define _LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_REFSTRING_H +#define _LIBCPP_REFSTRING_H + +#include <__config> +#include <stdexcept> +#include <cstddef> +#include <cstring> + +#if !defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_USE_ATOMIC) +#define _LIBCPP_USE_ATOMIC +#include <atomic> +#else +#include "atomic_support.h" +#endif + +// MacOS and iOS used to ship with libstdc++, and still support old applications +// linking against libstdc++. The libc++ and libstdc++ exceptions are supposed +// to be ABI compatible, such that they can be thrown from one library and caught +// in the other. +// +// For that reason, we must look for libstdc++ in the same process and if found, +// check the string stored in the exception object to see if it is the GCC empty +// string singleton before manipulating the reference count. This is done so that +// if an exception is created with a zero-length string in libstdc++, libc++abi +// won't try to delete the memory. +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \ + defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) +# define _LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE # include <dlfcn.h> # include <mach-o/dyld.h> -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -namespace __refstring_imp { namespace { -typedef int count_t; - -struct _Rep_base { - std::size_t len; - std::size_t cap; -#ifdef _LIBCPP_USE_ATOMIC - std::atomic<count_t> count; -#else - count_t count; -#endif -}; - -inline _Rep_base* rep_from_data(const char *data_) noexcept { - char *data = const_cast<char *>(data_); - return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); -} - -inline char * data_from_rep(_Rep_base *rep) noexcept { - char *data = reinterpret_cast<char *>(rep); - return data + sizeof(*rep); -} - -#if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE) -inline -const char* compute_gcc_empty_string_storage() noexcept -{ - void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); - if (handle == nullptr) - return nullptr; - void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); - if (sym == nullptr) - return nullptr; - return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); -} - -inline -const char* -get_gcc_empty_string_storage() noexcept -{ - static const char* p = compute_gcc_empty_string_storage(); - return p; -} -#endif - -}} // namespace __refstring_imp - -using namespace __refstring_imp; - -inline -__libcpp_refstring::__libcpp_refstring(const char* msg) { - std::size_t len = strlen(msg); - _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); - rep->len = len; - rep->cap = len; - rep->count = 0; - char *data = data_from_rep(rep); - std::memcpy(data, msg, len + 1); - __imp_ = data; -} - -inline -__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) noexcept - : __imp_(s.__imp_) -{ - if (__uses_refcount()) -#ifdef _LIBCPP_USE_ATOMIC - rep_from_data(__imp_)->count.fetch_add(1); -#else - __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); -#endif -} - -inline -__libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) noexcept { - bool adjust_old_count = __uses_refcount(); - struct _Rep_base *old_rep = rep_from_data(__imp_); - __imp_ = s.__imp_; - if (__uses_refcount()) -#ifdef _LIBCPP_USE_ATOMIC - rep_from_data(__imp_)->count.fetch_add(1); -#else - __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); -#endif - - if (adjust_old_count) - { -#ifdef _LIBCPP_USE_ATOMIC - if (old_rep->count.fetch_sub(1) == 0) -#else - if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0) -#endif - { - ::operator delete(old_rep); - } - } - return *this; -} - -inline -__libcpp_refstring::~__libcpp_refstring() { - if (__uses_refcount()) { - _Rep_base* rep = rep_from_data(__imp_); -#ifdef _LIBCPP_USE_ATOMIC - if (rep->count.fetch_sub(1) == 0) { -#else - if (__sync_add_and_fetch(&rep->count, count_t(-1)) < 0) { -#endif - ::operator delete(rep); - } - } -} - -inline -bool __libcpp_refstring::__uses_refcount() const { -#if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE) - return __imp_ != get_gcc_empty_string_storage(); -#else - return true; -#endif -} - -_LIBCPP_END_NAMESPACE_STD - -#endif //_LIBCPP_REFSTRING_H +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __refstring_imp { namespace { +typedef int count_t; + +struct _Rep_base { + std::size_t len; + std::size_t cap; +#ifdef _LIBCPP_USE_ATOMIC + std::atomic<count_t> count; +#else + count_t count; +#endif +}; + +inline _Rep_base* rep_from_data(const char *data_) noexcept { + char *data = const_cast<char *>(data_); + return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); +} + +inline char * data_from_rep(_Rep_base *rep) noexcept { + char *data = reinterpret_cast<char *>(rep); + return data + sizeof(*rep); +} + +#if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE) +inline +const char* compute_gcc_empty_string_storage() noexcept +{ + void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); + if (handle == nullptr) + return nullptr; + void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); + if (sym == nullptr) + return nullptr; + return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); +} + +inline +const char* +get_gcc_empty_string_storage() noexcept +{ + static const char* p = compute_gcc_empty_string_storage(); + return p; +} +#endif + +}} // namespace __refstring_imp + +using namespace __refstring_imp; + +inline +__libcpp_refstring::__libcpp_refstring(const char* msg) { + std::size_t len = strlen(msg); + _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); + rep->len = len; + rep->cap = len; + rep->count = 0; + char *data = data_from_rep(rep); + std::memcpy(data, msg, len + 1); + __imp_ = data; +} + +inline +__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) noexcept + : __imp_(s.__imp_) +{ + if (__uses_refcount()) +#ifdef _LIBCPP_USE_ATOMIC + rep_from_data(__imp_)->count.fetch_add(1); +#else + __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); +#endif +} + +inline +__libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) noexcept { + bool adjust_old_count = __uses_refcount(); + struct _Rep_base *old_rep = rep_from_data(__imp_); + __imp_ = s.__imp_; + if (__uses_refcount()) +#ifdef _LIBCPP_USE_ATOMIC + rep_from_data(__imp_)->count.fetch_add(1); +#else + __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); +#endif + + if (adjust_old_count) + { +#ifdef _LIBCPP_USE_ATOMIC + if (old_rep->count.fetch_sub(1) == 0) +#else + if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0) +#endif + { + ::operator delete(old_rep); + } + } + return *this; +} + +inline +__libcpp_refstring::~__libcpp_refstring() { + if (__uses_refcount()) { + _Rep_base* rep = rep_from_data(__imp_); +#ifdef _LIBCPP_USE_ATOMIC + if (rep->count.fetch_sub(1) == 0) { +#else + if (__sync_add_and_fetch(&rep->count, count_t(-1)) < 0) { +#endif + ::operator delete(rep); + } + } +} + +inline +bool __libcpp_refstring::__uses_refcount() const { +#if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE) + return __imp_ != get_gcc_empty_string_storage(); +#else + return true; +#endif +} + +_LIBCPP_END_NAMESPACE_STD + +#endif //_LIBCPP_REFSTRING_H diff --git a/contrib/libs/cxxsupp/libcxx/src/include/sso_allocator.h b/contrib/libs/cxxsupp/libcxx/src/include/sso_allocator.h index 9590bac79c..2baf599c5c 100644 --- a/contrib/libs/cxxsupp/libcxx/src/include/sso_allocator.h +++ b/contrib/libs/cxxsupp/libcxx/src/include/sso_allocator.h @@ -1,77 +1,77 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// // 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_SSO_ALLOCATOR_H -#define _LIBCPP_SSO_ALLOCATOR_H - -#include <__config> -#include <memory> -#include <new> -#include <type_traits> - -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -#pragma GCC system_header -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -template <class _Tp, size_t _Np> class _LIBCPP_HIDDEN __sso_allocator; - -template <size_t _Np> -class _LIBCPP_HIDDEN __sso_allocator<void, _Np> -{ -public: - typedef const void* const_pointer; - typedef void value_type; -}; - -template <class _Tp, size_t _Np> -class _LIBCPP_HIDDEN __sso_allocator -{ - typename aligned_storage<sizeof(_Tp) * _Np>::type buf_; - bool __allocated_; -public: - typedef size_t size_type; - typedef _Tp* pointer; - typedef _Tp value_type; - - _LIBCPP_INLINE_VISIBILITY __sso_allocator() throw() : __allocated_(false) {} - _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator&) throw() : __allocated_(false) {} - template <class _Up> _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator<_Up, _Np>&) throw() - : __allocated_(false) {} -private: - __sso_allocator& operator=(const __sso_allocator&); -public: - _LIBCPP_INLINE_VISIBILITY pointer allocate(size_type __n, typename __sso_allocator<void, _Np>::const_pointer = nullptr) - { - if (!__allocated_ && __n <= _Np) - { - __allocated_ = true; - return (pointer)&buf_; - } - return allocator<_Tp>().allocate(__n); - } +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_SSO_ALLOCATOR_H +#define _LIBCPP_SSO_ALLOCATOR_H + +#include <__config> +#include <memory> +#include <new> +#include <type_traits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp, size_t _Np> class _LIBCPP_HIDDEN __sso_allocator; + +template <size_t _Np> +class _LIBCPP_HIDDEN __sso_allocator<void, _Np> +{ +public: + typedef const void* const_pointer; + typedef void value_type; +}; + +template <class _Tp, size_t _Np> +class _LIBCPP_HIDDEN __sso_allocator +{ + typename aligned_storage<sizeof(_Tp) * _Np>::type buf_; + bool __allocated_; +public: + typedef size_t size_type; + typedef _Tp* pointer; + typedef _Tp value_type; + + _LIBCPP_INLINE_VISIBILITY __sso_allocator() throw() : __allocated_(false) {} + _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator&) throw() : __allocated_(false) {} + template <class _Up> _LIBCPP_INLINE_VISIBILITY __sso_allocator(const __sso_allocator<_Up, _Np>&) throw() + : __allocated_(false) {} +private: + __sso_allocator& operator=(const __sso_allocator&); +public: + _LIBCPP_INLINE_VISIBILITY pointer allocate(size_type __n, typename __sso_allocator<void, _Np>::const_pointer = nullptr) + { + if (!__allocated_ && __n <= _Np) + { + __allocated_ = true; + return (pointer)&buf_; + } + return allocator<_Tp>().allocate(__n); + } _LIBCPP_INLINE_VISIBILITY void deallocate(pointer __p, size_type __n) - { - if (__p == (pointer)&buf_) - __allocated_ = false; - else - allocator<_Tp>().deallocate(__p, __n); - } - _LIBCPP_INLINE_VISIBILITY size_type max_size() const throw() {return size_type(~0) / sizeof(_Tp);} - - _LIBCPP_INLINE_VISIBILITY - bool operator==(const __sso_allocator& __a) const {return &buf_ == &__a.buf_;} - _LIBCPP_INLINE_VISIBILITY - bool operator!=(const __sso_allocator& __a) const {return &buf_ != &__a.buf_;} -}; - -_LIBCPP_END_NAMESPACE_STD - -#endif // _LIBCPP_SSO_ALLOCATOR_H + { + if (__p == (pointer)&buf_) + __allocated_ = false; + else + allocator<_Tp>().deallocate(__p, __n); + } + _LIBCPP_INLINE_VISIBILITY size_type max_size() const throw() {return size_type(~0) / sizeof(_Tp);} + + _LIBCPP_INLINE_VISIBILITY + bool operator==(const __sso_allocator& __a) const {return &buf_ == &__a.buf_;} + _LIBCPP_INLINE_VISIBILITY + bool operator!=(const __sso_allocator& __a) const {return &buf_ != &__a.buf_;} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_SSO_ALLOCATOR_H diff --git a/contrib/libs/cxxsupp/libcxx/src/ios.cpp b/contrib/libs/cxxsupp/libcxx/src/ios.cpp index b4c797eae9..a8a99015a9 100644 --- a/contrib/libs/cxxsupp/libcxx/src/ios.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/ios.cpp @@ -1,441 +1,441 @@ -//===-------------------------- ios.cpp -----------------------------------===// -// +//===-------------------------- ios.cpp -----------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "__config" - -#include "ios" - -#include <stdlib.h> - -#include "__locale" -#include "algorithm" -#include "include/config_elast.h" -#include "limits" -#include "memory" -#include "new" -#include "string" -#include "__undef_macros" - -_LIBCPP_BEGIN_NAMESPACE_STD - -class _LIBCPP_HIDDEN __iostream_category - : public __do_message -{ -public: - virtual const char* name() const noexcept; - virtual string message(int ev) const; -}; - -const char* -__iostream_category::name() const noexcept -{ - return "iostream"; -} - -string -__iostream_category::message(int ev) const -{ - if (ev != static_cast<int>(io_errc::stream) -#ifdef _LIBCPP_ELAST - && ev <= _LIBCPP_ELAST -#endif // _LIBCPP_ELAST - ) - return __do_message::message(ev); - return string("unspecified iostream_category error"); -} - -const error_category& -iostream_category() noexcept -{ - static __iostream_category s; - return s; -} - -// ios_base::failure - -ios_base::failure::failure(const string& msg, const error_code& ec) - : system_error(ec, msg) -{ -} - -ios_base::failure::failure(const char* msg, const error_code& ec) - : system_error(ec, msg) -{ -} - +// +//===----------------------------------------------------------------------===// + +#include "__config" + +#include "ios" + +#include <stdlib.h> + +#include "__locale" +#include "algorithm" +#include "include/config_elast.h" +#include "limits" +#include "memory" +#include "new" +#include "string" +#include "__undef_macros" + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_HIDDEN __iostream_category + : public __do_message +{ +public: + virtual const char* name() const noexcept; + virtual string message(int ev) const; +}; + +const char* +__iostream_category::name() const noexcept +{ + return "iostream"; +} + +string +__iostream_category::message(int ev) const +{ + if (ev != static_cast<int>(io_errc::stream) +#ifdef _LIBCPP_ELAST + && ev <= _LIBCPP_ELAST +#endif // _LIBCPP_ELAST + ) + return __do_message::message(ev); + return string("unspecified iostream_category error"); +} + +const error_category& +iostream_category() noexcept +{ + static __iostream_category s; + return s; +} + +// ios_base::failure + +ios_base::failure::failure(const string& msg, const error_code& ec) + : system_error(ec, msg) +{ +} + +ios_base::failure::failure(const char* msg, const error_code& ec) + : system_error(ec, msg) +{ +} + ios_base::failure::~failure() throw() -{ -} - -// ios_base locale - -const ios_base::fmtflags ios_base::boolalpha; -const ios_base::fmtflags ios_base::dec; -const ios_base::fmtflags ios_base::fixed; -const ios_base::fmtflags ios_base::hex; -const ios_base::fmtflags ios_base::internal; -const ios_base::fmtflags ios_base::left; -const ios_base::fmtflags ios_base::oct; -const ios_base::fmtflags ios_base::right; -const ios_base::fmtflags ios_base::scientific; -const ios_base::fmtflags ios_base::showbase; -const ios_base::fmtflags ios_base::showpoint; -const ios_base::fmtflags ios_base::showpos; -const ios_base::fmtflags ios_base::skipws; -const ios_base::fmtflags ios_base::unitbuf; -const ios_base::fmtflags ios_base::uppercase; -const ios_base::fmtflags ios_base::adjustfield; -const ios_base::fmtflags ios_base::basefield; -const ios_base::fmtflags ios_base::floatfield; - -const ios_base::iostate ios_base::badbit; -const ios_base::iostate ios_base::eofbit; -const ios_base::iostate ios_base::failbit; -const ios_base::iostate ios_base::goodbit; - -const ios_base::openmode ios_base::app; -const ios_base::openmode ios_base::ate; -const ios_base::openmode ios_base::binary; -const ios_base::openmode ios_base::in; -const ios_base::openmode ios_base::out; -const ios_base::openmode ios_base::trunc; - -void -ios_base::__call_callbacks(event ev) -{ - for (size_t i = __event_size_; i;) - { - --i; - __fn_[i](ev, *this, __index_[i]); - } -} - -// locale - -locale -ios_base::imbue(const locale& newloc) -{ - static_assert(sizeof(locale) == sizeof(__loc_), ""); - locale& loc_storage = *reinterpret_cast<locale*>(&__loc_); - locale oldloc = loc_storage; - loc_storage = newloc; - __call_callbacks(imbue_event); - return oldloc; -} - -locale -ios_base::getloc() const -{ - const locale& loc_storage = *reinterpret_cast<const locale*>(&__loc_); - return loc_storage; -} - -// xalloc -#if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS) -atomic<int> ios_base::__xindex_ = ATOMIC_VAR_INIT(0); -#else -int ios_base::__xindex_ = 0; -#endif - -template <typename _Tp> -static size_t __ios_new_cap(size_t __req_size, size_t __current_cap) -{ // Precondition: __req_size > __current_cap +{ +} + +// ios_base locale + +const ios_base::fmtflags ios_base::boolalpha; +const ios_base::fmtflags ios_base::dec; +const ios_base::fmtflags ios_base::fixed; +const ios_base::fmtflags ios_base::hex; +const ios_base::fmtflags ios_base::internal; +const ios_base::fmtflags ios_base::left; +const ios_base::fmtflags ios_base::oct; +const ios_base::fmtflags ios_base::right; +const ios_base::fmtflags ios_base::scientific; +const ios_base::fmtflags ios_base::showbase; +const ios_base::fmtflags ios_base::showpoint; +const ios_base::fmtflags ios_base::showpos; +const ios_base::fmtflags ios_base::skipws; +const ios_base::fmtflags ios_base::unitbuf; +const ios_base::fmtflags ios_base::uppercase; +const ios_base::fmtflags ios_base::adjustfield; +const ios_base::fmtflags ios_base::basefield; +const ios_base::fmtflags ios_base::floatfield; + +const ios_base::iostate ios_base::badbit; +const ios_base::iostate ios_base::eofbit; +const ios_base::iostate ios_base::failbit; +const ios_base::iostate ios_base::goodbit; + +const ios_base::openmode ios_base::app; +const ios_base::openmode ios_base::ate; +const ios_base::openmode ios_base::binary; +const ios_base::openmode ios_base::in; +const ios_base::openmode ios_base::out; +const ios_base::openmode ios_base::trunc; + +void +ios_base::__call_callbacks(event ev) +{ + for (size_t i = __event_size_; i;) + { + --i; + __fn_[i](ev, *this, __index_[i]); + } +} + +// locale + +locale +ios_base::imbue(const locale& newloc) +{ + static_assert(sizeof(locale) == sizeof(__loc_), ""); + locale& loc_storage = *reinterpret_cast<locale*>(&__loc_); + locale oldloc = loc_storage; + loc_storage = newloc; + __call_callbacks(imbue_event); + return oldloc; +} + +locale +ios_base::getloc() const +{ + const locale& loc_storage = *reinterpret_cast<const locale*>(&__loc_); + return loc_storage; +} + +// xalloc +#if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS) +atomic<int> ios_base::__xindex_ = ATOMIC_VAR_INIT(0); +#else +int ios_base::__xindex_ = 0; +#endif + +template <typename _Tp> +static size_t __ios_new_cap(size_t __req_size, size_t __current_cap) +{ // Precondition: __req_size > __current_cap const size_t mx = std::numeric_limits<size_t>::max() / sizeof(_Tp); if (__req_size < mx/2) return _VSTD::max(2 * __current_cap, __req_size); else return mx; -} - -int -ios_base::xalloc() -{ - return __xindex_++; -} - -long& -ios_base::iword(int index) -{ - size_t req_size = static_cast<size_t>(index)+1; - if (req_size > __iarray_cap_) - { - size_t newcap = __ios_new_cap<long>(req_size, __iarray_cap_); - long* iarray = static_cast<long*>(realloc(__iarray_, newcap * sizeof(long))); - if (iarray == 0) - { - setstate(badbit); - static long error; - error = 0; - return error; - } - __iarray_ = iarray; - for (long* p = __iarray_ + __iarray_size_; p < __iarray_ + newcap; ++p) - *p = 0; - __iarray_cap_ = newcap; - } - __iarray_size_ = max<size_t>(__iarray_size_, req_size); - return __iarray_[index]; -} - -void*& -ios_base::pword(int index) -{ - size_t req_size = static_cast<size_t>(index)+1; - if (req_size > __parray_cap_) - { - size_t newcap = __ios_new_cap<void *>(req_size, __iarray_cap_); - void** parray = static_cast<void**>(realloc(__parray_, newcap * sizeof(void *))); - if (parray == 0) - { - setstate(badbit); - static void* error; - error = 0; - return error; - } - __parray_ = parray; - for (void** p = __parray_ + __parray_size_; p < __parray_ + newcap; ++p) - *p = 0; - __parray_cap_ = newcap; - } - __parray_size_ = max<size_t>(__parray_size_, req_size); - return __parray_[index]; -} - -// register_callback - -void -ios_base::register_callback(event_callback fn, int index) -{ - size_t req_size = __event_size_ + 1; - if (req_size > __event_cap_) - { - size_t newcap = __ios_new_cap<event_callback>(req_size, __event_cap_); - event_callback* fns = static_cast<event_callback*>(realloc(__fn_, newcap * sizeof(event_callback))); - if (fns == 0) - setstate(badbit); - __fn_ = fns; - int* indxs = static_cast<int *>(realloc(__index_, newcap * sizeof(int))); - if (indxs == 0) - setstate(badbit); - __index_ = indxs; - __event_cap_ = newcap; - } - __fn_[__event_size_] = fn; - __index_[__event_size_] = index; - ++__event_size_; -} - -ios_base::~ios_base() -{ - __call_callbacks(erase_event); - locale& loc_storage = *reinterpret_cast<locale*>(&__loc_); - loc_storage.~locale(); - free(__fn_); - free(__index_); - free(__iarray_); - free(__parray_); -} - -// iostate - -void -ios_base::clear(iostate state) -{ - if (__rdbuf_) - __rdstate_ = state; - else - __rdstate_ = state | badbit; - - if (((state | (__rdbuf_ ? goodbit : badbit)) & __exceptions_) != 0) - __throw_failure("ios_base::clear"); -} - -// init - -void -ios_base::init(void* sb) -{ - __rdbuf_ = sb; - __rdstate_ = __rdbuf_ ? goodbit : badbit; - __exceptions_ = goodbit; - __fmtflags_ = skipws | dec; - __width_ = 0; - __precision_ = 6; - __fn_ = 0; - __index_ = 0; - __event_size_ = 0; - __event_cap_ = 0; - __iarray_ = 0; - __iarray_size_ = 0; - __iarray_cap_ = 0; - __parray_ = 0; - __parray_size_ = 0; - __parray_cap_ = 0; - ::new(&__loc_) locale; -} - -void -ios_base::copyfmt(const ios_base& rhs) -{ - // If we can't acquire the needed resources, throw bad_alloc (can't set badbit) - // Don't alter *this until all needed resources are acquired - unique_ptr<event_callback, void (*)(void*)> new_callbacks(0, free); - unique_ptr<int, void (*)(void*)> new_ints(0, free); - unique_ptr<long, void (*)(void*)> new_longs(0, free); - unique_ptr<void*, void (*)(void*)> new_pointers(0, free); - if (__event_cap_ < rhs.__event_size_) - { - size_t newesize = sizeof(event_callback) * rhs.__event_size_; - new_callbacks.reset(static_cast<event_callback*>(malloc(newesize))); - if (!new_callbacks) - __throw_bad_alloc(); - - size_t newisize = sizeof(int) * rhs.__event_size_; - new_ints.reset(static_cast<int *>(malloc(newisize))); - if (!new_ints) - __throw_bad_alloc(); - } - if (__iarray_cap_ < rhs.__iarray_size_) - { - size_t newsize = sizeof(long) * rhs.__iarray_size_; - new_longs.reset(static_cast<long*>(malloc(newsize))); - if (!new_longs) - __throw_bad_alloc(); - } - if (__parray_cap_ < rhs.__parray_size_) - { - size_t newsize = sizeof(void*) * rhs.__parray_size_; - new_pointers.reset(static_cast<void**>(malloc(newsize))); - if (!new_pointers) - __throw_bad_alloc(); - } - // Got everything we need. Copy everything but __rdstate_, __rdbuf_ and __exceptions_ - __fmtflags_ = rhs.__fmtflags_; - __precision_ = rhs.__precision_; - __width_ = rhs.__width_; - locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_); - const locale& rhs_loc = *reinterpret_cast<const locale*>(&rhs.__loc_); - lhs_loc = rhs_loc; - if (__event_cap_ < rhs.__event_size_) - { - free(__fn_); - __fn_ = new_callbacks.release(); - free(__index_); - __index_ = new_ints.release(); - __event_cap_ = rhs.__event_size_; - } - for (__event_size_ = 0; __event_size_ < rhs.__event_size_; ++__event_size_) - { - __fn_[__event_size_] = rhs.__fn_[__event_size_]; - __index_[__event_size_] = rhs.__index_[__event_size_]; - } - if (__iarray_cap_ < rhs.__iarray_size_) - { - free(__iarray_); - __iarray_ = new_longs.release(); - __iarray_cap_ = rhs.__iarray_size_; - } - for (__iarray_size_ = 0; __iarray_size_ < rhs.__iarray_size_; ++__iarray_size_) - __iarray_[__iarray_size_] = rhs.__iarray_[__iarray_size_]; - if (__parray_cap_ < rhs.__parray_size_) - { - free(__parray_); - __parray_ = new_pointers.release(); - __parray_cap_ = rhs.__parray_size_; - } - for (__parray_size_ = 0; __parray_size_ < rhs.__parray_size_; ++__parray_size_) - __parray_[__parray_size_] = rhs.__parray_[__parray_size_]; -} - -void -ios_base::move(ios_base& rhs) -{ - // *this is uninitialized - __fmtflags_ = rhs.__fmtflags_; - __precision_ = rhs.__precision_; - __width_ = rhs.__width_; - __rdstate_ = rhs.__rdstate_; - __exceptions_ = rhs.__exceptions_; - __rdbuf_ = 0; - locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_); - ::new(&__loc_) locale(rhs_loc); - __fn_ = rhs.__fn_; - rhs.__fn_ = 0; - __index_ = rhs.__index_; - rhs.__index_ = 0; - __event_size_ = rhs.__event_size_; - rhs.__event_size_ = 0; - __event_cap_ = rhs.__event_cap_; - rhs.__event_cap_ = 0; - __iarray_ = rhs.__iarray_; - rhs.__iarray_ = 0; - __iarray_size_ = rhs.__iarray_size_; - rhs.__iarray_size_ = 0; - __iarray_cap_ = rhs.__iarray_cap_; - rhs.__iarray_cap_ = 0; - __parray_ = rhs.__parray_; - rhs.__parray_ = 0; - __parray_size_ = rhs.__parray_size_; - rhs.__parray_size_ = 0; - __parray_cap_ = rhs.__parray_cap_; - rhs.__parray_cap_ = 0; -} - -void -ios_base::swap(ios_base& rhs) noexcept -{ - _VSTD::swap(__fmtflags_, rhs.__fmtflags_); - _VSTD::swap(__precision_, rhs.__precision_); - _VSTD::swap(__width_, rhs.__width_); - _VSTD::swap(__rdstate_, rhs.__rdstate_); - _VSTD::swap(__exceptions_, rhs.__exceptions_); - locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_); - locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_); - _VSTD::swap(lhs_loc, rhs_loc); - _VSTD::swap(__fn_, rhs.__fn_); - _VSTD::swap(__index_, rhs.__index_); - _VSTD::swap(__event_size_, rhs.__event_size_); - _VSTD::swap(__event_cap_, rhs.__event_cap_); - _VSTD::swap(__iarray_, rhs.__iarray_); - _VSTD::swap(__iarray_size_, rhs.__iarray_size_); - _VSTD::swap(__iarray_cap_, rhs.__iarray_cap_); - _VSTD::swap(__parray_, rhs.__parray_); - _VSTD::swap(__parray_size_, rhs.__parray_size_); - _VSTD::swap(__parray_cap_, rhs.__parray_cap_); -} - -void -ios_base::__set_badbit_and_consider_rethrow() -{ - __rdstate_ |= badbit; -#ifndef _LIBCPP_NO_EXCEPTIONS - if (__exceptions_ & badbit) - throw; -#endif // _LIBCPP_NO_EXCEPTIONS -} - -void -ios_base::__set_failbit_and_consider_rethrow() -{ - __rdstate_ |= failbit; -#ifndef _LIBCPP_NO_EXCEPTIONS - if (__exceptions_ & failbit) - throw; -#endif // _LIBCPP_NO_EXCEPTIONS -} - -bool -ios_base::sync_with_stdio(bool sync) -{ - static bool previous_state = true; - bool r = previous_state; - previous_state = sync; - return r; -} - -_LIBCPP_END_NAMESPACE_STD +} + +int +ios_base::xalloc() +{ + return __xindex_++; +} + +long& +ios_base::iword(int index) +{ + size_t req_size = static_cast<size_t>(index)+1; + if (req_size > __iarray_cap_) + { + size_t newcap = __ios_new_cap<long>(req_size, __iarray_cap_); + long* iarray = static_cast<long*>(realloc(__iarray_, newcap * sizeof(long))); + if (iarray == 0) + { + setstate(badbit); + static long error; + error = 0; + return error; + } + __iarray_ = iarray; + for (long* p = __iarray_ + __iarray_size_; p < __iarray_ + newcap; ++p) + *p = 0; + __iarray_cap_ = newcap; + } + __iarray_size_ = max<size_t>(__iarray_size_, req_size); + return __iarray_[index]; +} + +void*& +ios_base::pword(int index) +{ + size_t req_size = static_cast<size_t>(index)+1; + if (req_size > __parray_cap_) + { + size_t newcap = __ios_new_cap<void *>(req_size, __iarray_cap_); + void** parray = static_cast<void**>(realloc(__parray_, newcap * sizeof(void *))); + if (parray == 0) + { + setstate(badbit); + static void* error; + error = 0; + return error; + } + __parray_ = parray; + for (void** p = __parray_ + __parray_size_; p < __parray_ + newcap; ++p) + *p = 0; + __parray_cap_ = newcap; + } + __parray_size_ = max<size_t>(__parray_size_, req_size); + return __parray_[index]; +} + +// register_callback + +void +ios_base::register_callback(event_callback fn, int index) +{ + size_t req_size = __event_size_ + 1; + if (req_size > __event_cap_) + { + size_t newcap = __ios_new_cap<event_callback>(req_size, __event_cap_); + event_callback* fns = static_cast<event_callback*>(realloc(__fn_, newcap * sizeof(event_callback))); + if (fns == 0) + setstate(badbit); + __fn_ = fns; + int* indxs = static_cast<int *>(realloc(__index_, newcap * sizeof(int))); + if (indxs == 0) + setstate(badbit); + __index_ = indxs; + __event_cap_ = newcap; + } + __fn_[__event_size_] = fn; + __index_[__event_size_] = index; + ++__event_size_; +} + +ios_base::~ios_base() +{ + __call_callbacks(erase_event); + locale& loc_storage = *reinterpret_cast<locale*>(&__loc_); + loc_storage.~locale(); + free(__fn_); + free(__index_); + free(__iarray_); + free(__parray_); +} + +// iostate + +void +ios_base::clear(iostate state) +{ + if (__rdbuf_) + __rdstate_ = state; + else + __rdstate_ = state | badbit; + + if (((state | (__rdbuf_ ? goodbit : badbit)) & __exceptions_) != 0) + __throw_failure("ios_base::clear"); +} + +// init + +void +ios_base::init(void* sb) +{ + __rdbuf_ = sb; + __rdstate_ = __rdbuf_ ? goodbit : badbit; + __exceptions_ = goodbit; + __fmtflags_ = skipws | dec; + __width_ = 0; + __precision_ = 6; + __fn_ = 0; + __index_ = 0; + __event_size_ = 0; + __event_cap_ = 0; + __iarray_ = 0; + __iarray_size_ = 0; + __iarray_cap_ = 0; + __parray_ = 0; + __parray_size_ = 0; + __parray_cap_ = 0; + ::new(&__loc_) locale; +} + +void +ios_base::copyfmt(const ios_base& rhs) +{ + // If we can't acquire the needed resources, throw bad_alloc (can't set badbit) + // Don't alter *this until all needed resources are acquired + unique_ptr<event_callback, void (*)(void*)> new_callbacks(0, free); + unique_ptr<int, void (*)(void*)> new_ints(0, free); + unique_ptr<long, void (*)(void*)> new_longs(0, free); + unique_ptr<void*, void (*)(void*)> new_pointers(0, free); + if (__event_cap_ < rhs.__event_size_) + { + size_t newesize = sizeof(event_callback) * rhs.__event_size_; + new_callbacks.reset(static_cast<event_callback*>(malloc(newesize))); + if (!new_callbacks) + __throw_bad_alloc(); + + size_t newisize = sizeof(int) * rhs.__event_size_; + new_ints.reset(static_cast<int *>(malloc(newisize))); + if (!new_ints) + __throw_bad_alloc(); + } + if (__iarray_cap_ < rhs.__iarray_size_) + { + size_t newsize = sizeof(long) * rhs.__iarray_size_; + new_longs.reset(static_cast<long*>(malloc(newsize))); + if (!new_longs) + __throw_bad_alloc(); + } + if (__parray_cap_ < rhs.__parray_size_) + { + size_t newsize = sizeof(void*) * rhs.__parray_size_; + new_pointers.reset(static_cast<void**>(malloc(newsize))); + if (!new_pointers) + __throw_bad_alloc(); + } + // Got everything we need. Copy everything but __rdstate_, __rdbuf_ and __exceptions_ + __fmtflags_ = rhs.__fmtflags_; + __precision_ = rhs.__precision_; + __width_ = rhs.__width_; + locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_); + const locale& rhs_loc = *reinterpret_cast<const locale*>(&rhs.__loc_); + lhs_loc = rhs_loc; + if (__event_cap_ < rhs.__event_size_) + { + free(__fn_); + __fn_ = new_callbacks.release(); + free(__index_); + __index_ = new_ints.release(); + __event_cap_ = rhs.__event_size_; + } + for (__event_size_ = 0; __event_size_ < rhs.__event_size_; ++__event_size_) + { + __fn_[__event_size_] = rhs.__fn_[__event_size_]; + __index_[__event_size_] = rhs.__index_[__event_size_]; + } + if (__iarray_cap_ < rhs.__iarray_size_) + { + free(__iarray_); + __iarray_ = new_longs.release(); + __iarray_cap_ = rhs.__iarray_size_; + } + for (__iarray_size_ = 0; __iarray_size_ < rhs.__iarray_size_; ++__iarray_size_) + __iarray_[__iarray_size_] = rhs.__iarray_[__iarray_size_]; + if (__parray_cap_ < rhs.__parray_size_) + { + free(__parray_); + __parray_ = new_pointers.release(); + __parray_cap_ = rhs.__parray_size_; + } + for (__parray_size_ = 0; __parray_size_ < rhs.__parray_size_; ++__parray_size_) + __parray_[__parray_size_] = rhs.__parray_[__parray_size_]; +} + +void +ios_base::move(ios_base& rhs) +{ + // *this is uninitialized + __fmtflags_ = rhs.__fmtflags_; + __precision_ = rhs.__precision_; + __width_ = rhs.__width_; + __rdstate_ = rhs.__rdstate_; + __exceptions_ = rhs.__exceptions_; + __rdbuf_ = 0; + locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_); + ::new(&__loc_) locale(rhs_loc); + __fn_ = rhs.__fn_; + rhs.__fn_ = 0; + __index_ = rhs.__index_; + rhs.__index_ = 0; + __event_size_ = rhs.__event_size_; + rhs.__event_size_ = 0; + __event_cap_ = rhs.__event_cap_; + rhs.__event_cap_ = 0; + __iarray_ = rhs.__iarray_; + rhs.__iarray_ = 0; + __iarray_size_ = rhs.__iarray_size_; + rhs.__iarray_size_ = 0; + __iarray_cap_ = rhs.__iarray_cap_; + rhs.__iarray_cap_ = 0; + __parray_ = rhs.__parray_; + rhs.__parray_ = 0; + __parray_size_ = rhs.__parray_size_; + rhs.__parray_size_ = 0; + __parray_cap_ = rhs.__parray_cap_; + rhs.__parray_cap_ = 0; +} + +void +ios_base::swap(ios_base& rhs) noexcept +{ + _VSTD::swap(__fmtflags_, rhs.__fmtflags_); + _VSTD::swap(__precision_, rhs.__precision_); + _VSTD::swap(__width_, rhs.__width_); + _VSTD::swap(__rdstate_, rhs.__rdstate_); + _VSTD::swap(__exceptions_, rhs.__exceptions_); + locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_); + locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_); + _VSTD::swap(lhs_loc, rhs_loc); + _VSTD::swap(__fn_, rhs.__fn_); + _VSTD::swap(__index_, rhs.__index_); + _VSTD::swap(__event_size_, rhs.__event_size_); + _VSTD::swap(__event_cap_, rhs.__event_cap_); + _VSTD::swap(__iarray_, rhs.__iarray_); + _VSTD::swap(__iarray_size_, rhs.__iarray_size_); + _VSTD::swap(__iarray_cap_, rhs.__iarray_cap_); + _VSTD::swap(__parray_, rhs.__parray_); + _VSTD::swap(__parray_size_, rhs.__parray_size_); + _VSTD::swap(__parray_cap_, rhs.__parray_cap_); +} + +void +ios_base::__set_badbit_and_consider_rethrow() +{ + __rdstate_ |= badbit; +#ifndef _LIBCPP_NO_EXCEPTIONS + if (__exceptions_ & badbit) + throw; +#endif // _LIBCPP_NO_EXCEPTIONS +} + +void +ios_base::__set_failbit_and_consider_rethrow() +{ + __rdstate_ |= failbit; +#ifndef _LIBCPP_NO_EXCEPTIONS + if (__exceptions_ & failbit) + throw; +#endif // _LIBCPP_NO_EXCEPTIONS +} + +bool +ios_base::sync_with_stdio(bool sync) +{ + static bool previous_state = true; + bool r = previous_state; + previous_state = sync; + return r; +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/ios.instantiations.cpp b/contrib/libs/cxxsupp/libcxx/src/ios.instantiations.cpp index 70eb5c61f0..e1189d0b5b 100644 --- a/contrib/libs/cxxsupp/libcxx/src/ios.instantiations.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/ios.instantiations.cpp @@ -1,46 +1,46 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "__config" -#include "fstream" -#include "ios" -#include "istream" -#include "ostream" -#include "sstream" -#include "streambuf" - - -_LIBCPP_BEGIN_NAMESPACE_STD - -// Original explicit instantiations provided in the library -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios<char>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf<char>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream<char>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream<char>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_iostream<char>; - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios<wchar_t>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf<wchar_t>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream<wchar_t>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream<wchar_t>; -#endif - -// Additional instantiations added later. Whether programs rely on these being -// available is protected by _LIBCPP_ABI_ENABLE_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1. -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_stringbuf<char>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_stringstream<char>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostringstream<char>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istringstream<char>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ifstream<char>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ofstream<char>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_filebuf<char>; - -// Add more here if needed... - -_LIBCPP_END_NAMESPACE_STD +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "__config" +#include "fstream" +#include "ios" +#include "istream" +#include "ostream" +#include "sstream" +#include "streambuf" + + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Original explicit instantiations provided in the library +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios<char>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf<char>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream<char>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream<char>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_iostream<char>; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios<wchar_t>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf<wchar_t>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream<wchar_t>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream<wchar_t>; +#endif + +// Additional instantiations added later. Whether programs rely on these being +// available is protected by _LIBCPP_ABI_ENABLE_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1. +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_stringbuf<char>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_stringstream<char>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostringstream<char>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istringstream<char>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ifstream<char>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ofstream<char>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_filebuf<char>; + +// Add more here if needed... + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/iostream.cpp b/contrib/libs/cxxsupp/libcxx/src/iostream.cpp index a41d643ab5..5c1f5ed9ee 100644 --- a/contrib/libs/cxxsupp/libcxx/src/iostream.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/iostream.cpp @@ -1,211 +1,211 @@ -//===------------------------ iostream.cpp --------------------------------===// -// +//===------------------------ iostream.cpp --------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "__std_stream" -#include "__locale" -#include "string" -#include "new" - -#define _str(s) #s -#define str(s) _str(s) +// +//===----------------------------------------------------------------------===// + +#include "__std_stream" +#include "__locale" +#include "string" +#include "new" + +#define _str(s) #s +#define str(s) _str(s) #define _LIBCPP_ABI_NAMESPACE_STR str(_LIBCPP_ABI_NAMESPACE) - -_LIBCPP_BEGIN_NAMESPACE_STD - -#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) -_ALIGNAS_TYPE (istream) char _cin [sizeof(istream)]; -_LIBCPP_FUNC_VIS istream& cin = *reinterpret_cast<istream*>(_cin); -#else -_ALIGNAS_TYPE (istream) _LIBCPP_FUNC_VIS char cin[sizeof(istream)] -#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) +_ALIGNAS_TYPE (istream) char _cin [sizeof(istream)]; +_LIBCPP_FUNC_VIS istream& cin = *reinterpret_cast<istream*>(_cin); +#else +_ALIGNAS_TYPE (istream) _LIBCPP_FUNC_VIS char cin[sizeof(istream)] +#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?cin@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_istream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") -#endif -; -#endif -_ALIGNAS_TYPE (__stdinbuf<char> ) static char __cin[sizeof(__stdinbuf <char>)]; -static mbstate_t mb_cin; - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) -_ALIGNAS_TYPE (wistream) char _wcin [sizeof(wistream)]; -_LIBCPP_FUNC_VIS wistream& wcin = *reinterpret_cast<wistream*>(_wcin); -#else -_ALIGNAS_TYPE (wistream) _LIBCPP_FUNC_VIS char wcin[sizeof(wistream)] -#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) +#endif +; +#endif +_ALIGNAS_TYPE (__stdinbuf<char> ) static char __cin[sizeof(__stdinbuf <char>)]; +static mbstate_t mb_cin; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) +_ALIGNAS_TYPE (wistream) char _wcin [sizeof(wistream)]; +_LIBCPP_FUNC_VIS wistream& wcin = *reinterpret_cast<wistream*>(_wcin); +#else +_ALIGNAS_TYPE (wistream) _LIBCPP_FUNC_VIS char wcin[sizeof(wistream)] +#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?wcin@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_istream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") -#endif -; -#endif -_ALIGNAS_TYPE (__stdinbuf<wchar_t> ) static char __wcin[sizeof(__stdinbuf <wchar_t>)]; -static mbstate_t mb_wcin; -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) -_ALIGNAS_TYPE (ostream) char _cout[sizeof(ostream)]; -_LIBCPP_FUNC_VIS ostream& cout = *reinterpret_cast<ostream*>(_cout); -#else -_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cout[sizeof(ostream)] -#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) +#endif +; +#endif +_ALIGNAS_TYPE (__stdinbuf<wchar_t> ) static char __wcin[sizeof(__stdinbuf <wchar_t>)]; +static mbstate_t mb_wcin; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) +_ALIGNAS_TYPE (ostream) char _cout[sizeof(ostream)]; +_LIBCPP_FUNC_VIS ostream& cout = *reinterpret_cast<ostream*>(_cout); +#else +_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cout[sizeof(ostream)] +#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?cout@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") -#endif -; -#endif -_ALIGNAS_TYPE (__stdoutbuf<char>) static char __cout[sizeof(__stdoutbuf<char>)]; -static mbstate_t mb_cout; - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) -_ALIGNAS_TYPE (wostream) char _wcout[sizeof(wostream)]; -_LIBCPP_FUNC_VIS wostream& wcout = *reinterpret_cast<wostream*>(_wcout); -#else -_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcout[sizeof(wostream)] -#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) +#endif +; +#endif +_ALIGNAS_TYPE (__stdoutbuf<char>) static char __cout[sizeof(__stdoutbuf<char>)]; +static mbstate_t mb_cout; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) +_ALIGNAS_TYPE (wostream) char _wcout[sizeof(wostream)]; +_LIBCPP_FUNC_VIS wostream& wcout = *reinterpret_cast<wostream*>(_wcout); +#else +_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcout[sizeof(wostream)] +#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?wcout@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") -#endif -; -#endif -_ALIGNAS_TYPE (__stdoutbuf<wchar_t>) static char __wcout[sizeof(__stdoutbuf<wchar_t>)]; -static mbstate_t mb_wcout; -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) -_ALIGNAS_TYPE (ostream) char _cerr[sizeof(ostream)]; -_LIBCPP_FUNC_VIS ostream& cerr = *reinterpret_cast<ostream*>(_cerr); -#else -_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cerr[sizeof(ostream)] -#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) +#endif +; +#endif +_ALIGNAS_TYPE (__stdoutbuf<wchar_t>) static char __wcout[sizeof(__stdoutbuf<wchar_t>)]; +static mbstate_t mb_wcout; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) +_ALIGNAS_TYPE (ostream) char _cerr[sizeof(ostream)]; +_LIBCPP_FUNC_VIS ostream& cerr = *reinterpret_cast<ostream*>(_cerr); +#else +_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cerr[sizeof(ostream)] +#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?cerr@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") -#endif -; -#endif -_ALIGNAS_TYPE (__stdoutbuf<char>) static char __cerr[sizeof(__stdoutbuf<char>)]; -static mbstate_t mb_cerr; - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) -_ALIGNAS_TYPE (wostream) char _wcerr[sizeof(wostream)]; -_LIBCPP_FUNC_VIS wostream& wcerr = *reinterpret_cast<wostream*>(_wcerr); -#else -_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcerr[sizeof(wostream)] -#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) +#endif +; +#endif +_ALIGNAS_TYPE (__stdoutbuf<char>) static char __cerr[sizeof(__stdoutbuf<char>)]; +static mbstate_t mb_cerr; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) +_ALIGNAS_TYPE (wostream) char _wcerr[sizeof(wostream)]; +_LIBCPP_FUNC_VIS wostream& wcerr = *reinterpret_cast<wostream*>(_wcerr); +#else +_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcerr[sizeof(wostream)] +#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?wcerr@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") -#endif -; -#endif -_ALIGNAS_TYPE (__stdoutbuf<wchar_t>) static char __wcerr[sizeof(__stdoutbuf<wchar_t>)]; -static mbstate_t mb_wcerr; -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) -_ALIGNAS_TYPE (ostream) char _clog[sizeof(ostream)]; -_LIBCPP_FUNC_VIS ostream& clog = *reinterpret_cast<ostream*>(_clog); -#else -_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char clog[sizeof(ostream)] -#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) +#endif +; +#endif +_ALIGNAS_TYPE (__stdoutbuf<wchar_t>) static char __wcerr[sizeof(__stdoutbuf<wchar_t>)]; +static mbstate_t mb_wcerr; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) +_ALIGNAS_TYPE (ostream) char _clog[sizeof(ostream)]; +_LIBCPP_FUNC_VIS ostream& clog = *reinterpret_cast<ostream*>(_clog); +#else +_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char clog[sizeof(ostream)] +#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?clog@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") -#endif -; -#endif - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) -_ALIGNAS_TYPE (wostream) char _wclog[sizeof(wostream)]; -_LIBCPP_FUNC_VIS wostream& wclog = *reinterpret_cast<wostream*>(_wclog); -#else -_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wclog[sizeof(wostream)] -#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) +#endif +; +#endif + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(__clang__) +_ALIGNAS_TYPE (wostream) char _wclog[sizeof(wostream)]; +_LIBCPP_FUNC_VIS wostream& wclog = *reinterpret_cast<wostream*>(_wclog); +#else +_ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wclog[sizeof(wostream)] +#if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) __asm__("?wclog@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR "@std@@@12@A") -#endif -; -#endif -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -// Hacky way to make the compiler believe that we're inside a system header so -// it doesn't flag the use of the init_priority attribute with a value that's -// reserved for the implementation (we're the implementation). -#ifndef _LIBCPP_COMPILER_MSVC -# 80 "iostream.cpp" 1 3 -#endif -_LIBCPP_HIDDEN ios_base::Init __start_std_streams _LIBCPP_INIT_PRIORITY_MAX; -#ifndef _LIBCPP_COMPILER_MSVC -# 82 "iostream.cpp" 2 -#endif - -// On Windows the TLS storage for locales needs to be initialized before we create -// the standard streams, otherwise it may not be alive during program termination -// when we flush the streams. -static void force_locale_initialization() { -#if defined(_LIBCPP_MSVCRT_LIKE) - static bool once = []() { - auto loc = newlocale(LC_ALL_MASK, "C", 0); - { - __libcpp_locale_guard g(loc); // forces initialization of locale TLS - ((void)g); - } - freelocale(loc); - return true; - }(); - ((void)once); -#endif -} - -class DoIOSInit { -public: +#endif +; +#endif +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// Hacky way to make the compiler believe that we're inside a system header so +// it doesn't flag the use of the init_priority attribute with a value that's +// reserved for the implementation (we're the implementation). +#ifndef _LIBCPP_COMPILER_MSVC +# 80 "iostream.cpp" 1 3 +#endif +_LIBCPP_HIDDEN ios_base::Init __start_std_streams _LIBCPP_INIT_PRIORITY_MAX; +#ifndef _LIBCPP_COMPILER_MSVC +# 82 "iostream.cpp" 2 +#endif + +// On Windows the TLS storage for locales needs to be initialized before we create +// the standard streams, otherwise it may not be alive during program termination +// when we flush the streams. +static void force_locale_initialization() { +#if defined(_LIBCPP_MSVCRT_LIKE) + static bool once = []() { + auto loc = newlocale(LC_ALL_MASK, "C", 0); + { + __libcpp_locale_guard g(loc); // forces initialization of locale TLS + ((void)g); + } + freelocale(loc); + return true; + }(); + ((void)once); +#endif +} + +class DoIOSInit { +public: DoIOSInit(); ~DoIOSInit(); -}; - -DoIOSInit::DoIOSInit() -{ - force_locale_initialization(); - - istream* cin_ptr = ::new(&cin) istream(::new(__cin) __stdinbuf <char>(stdin, &mb_cin)); - ostream* cout_ptr = ::new(&cout) ostream(::new(__cout) __stdoutbuf<char>(stdout, &mb_cout)); - ostream* cerr_ptr = ::new(&cerr) ostream(::new(__cerr) __stdoutbuf<char>(stderr, &mb_cerr)); - ::new(&clog) ostream(cerr_ptr->rdbuf()); - cin_ptr->tie(cout_ptr); - _VSTD::unitbuf(*cerr_ptr); - cerr_ptr->tie(cout_ptr); - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - wistream* wcin_ptr = ::new(&wcin) wistream(::new(__wcin) __stdinbuf <wchar_t>(stdin, &mb_wcin)); - wostream* wcout_ptr = ::new(&wcout) wostream(::new(__wcout) __stdoutbuf<wchar_t>(stdout, &mb_wcout)); - wostream* wcerr_ptr = ::new(&wcerr) wostream(::new(__wcerr) __stdoutbuf<wchar_t>(stderr, &mb_wcerr)); - ::new(&wclog) wostream(wcerr_ptr->rdbuf()); - - wcin_ptr->tie(wcout_ptr); - _VSTD::unitbuf(*wcerr_ptr); - wcerr_ptr->tie(wcout_ptr); -#endif -} - -DoIOSInit::~DoIOSInit() -{ - ostream* cout_ptr = reinterpret_cast<ostream*>(&cout); - cout_ptr->flush(); - ostream* clog_ptr = reinterpret_cast<ostream*>(&clog); - clog_ptr->flush(); - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - wostream* wcout_ptr = reinterpret_cast<wostream*>(&wcout); - wcout_ptr->flush(); - wostream* wclog_ptr = reinterpret_cast<wostream*>(&wclog); - wclog_ptr->flush(); -#endif -} - -ios_base::Init::Init() -{ - static DoIOSInit init_the_streams; // gets initialized once -} - -ios_base::Init::~Init() -{ -} - -_LIBCPP_END_NAMESPACE_STD +}; + +DoIOSInit::DoIOSInit() +{ + force_locale_initialization(); + + istream* cin_ptr = ::new(&cin) istream(::new(__cin) __stdinbuf <char>(stdin, &mb_cin)); + ostream* cout_ptr = ::new(&cout) ostream(::new(__cout) __stdoutbuf<char>(stdout, &mb_cout)); + ostream* cerr_ptr = ::new(&cerr) ostream(::new(__cerr) __stdoutbuf<char>(stderr, &mb_cerr)); + ::new(&clog) ostream(cerr_ptr->rdbuf()); + cin_ptr->tie(cout_ptr); + _VSTD::unitbuf(*cerr_ptr); + cerr_ptr->tie(cout_ptr); + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + wistream* wcin_ptr = ::new(&wcin) wistream(::new(__wcin) __stdinbuf <wchar_t>(stdin, &mb_wcin)); + wostream* wcout_ptr = ::new(&wcout) wostream(::new(__wcout) __stdoutbuf<wchar_t>(stdout, &mb_wcout)); + wostream* wcerr_ptr = ::new(&wcerr) wostream(::new(__wcerr) __stdoutbuf<wchar_t>(stderr, &mb_wcerr)); + ::new(&wclog) wostream(wcerr_ptr->rdbuf()); + + wcin_ptr->tie(wcout_ptr); + _VSTD::unitbuf(*wcerr_ptr); + wcerr_ptr->tie(wcout_ptr); +#endif +} + +DoIOSInit::~DoIOSInit() +{ + ostream* cout_ptr = reinterpret_cast<ostream*>(&cout); + cout_ptr->flush(); + ostream* clog_ptr = reinterpret_cast<ostream*>(&clog); + clog_ptr->flush(); + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + wostream* wcout_ptr = reinterpret_cast<wostream*>(&wcout); + wcout_ptr->flush(); + wostream* wclog_ptr = reinterpret_cast<wostream*>(&wclog); + wclog_ptr->flush(); +#endif +} + +ios_base::Init::Init() +{ + static DoIOSInit init_the_streams; // gets initialized once +} + +ios_base::Init::~Init() +{ +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/locale.cpp b/contrib/libs/cxxsupp/libcxx/src/locale.cpp index aa3a580ea4..42b5641b43 100644 --- a/contrib/libs/cxxsupp/libcxx/src/locale.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/locale.cpp @@ -1,6573 +1,6573 @@ -//===------------------------- locale.cpp ---------------------------------===// -// +//===------------------------- locale.cpp ---------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -// On Solaris, we need to define something to make the C99 parts of localeconv -// visible. -#ifdef __sun__ -#define _LCONV_C99 -#endif - -#include "clocale" -#include "codecvt" -#include "cstdio" -#include "cstdlib" -#include "cstring" -#include "locale" -#include "string" -#include "type_traits" -#include "typeinfo" -#include "vector" - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -# include "cwctype" -#endif - -#if defined(_AIX) -# include <sys/localedef.h> // for __lc_ctype_ptr -#endif - -#if defined(_LIBCPP_MSVCRT) -# define _CTYPE_DISABLE_MACROS -#endif -#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) -# include "__support/win32/locale_win32.h" -#elif !defined(__BIONIC__) && !defined(__NuttX__) -# include <langinfo.h> -#endif - -#include "atomic" -#include "include/sso_allocator.h" -#include "__undef_macros" - -// On Linux, wint_t and wchar_t have different signed-ness, and this causes -// lots of noise in the build log, but no bugs that I know of. -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wsign-conversion" -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -struct __libcpp_unique_locale { - __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {} - - ~__libcpp_unique_locale() { - if (__loc_) - freelocale(__loc_); - } - - explicit operator bool() const { return __loc_; } - - locale_t& get() { return __loc_; } - - locale_t __loc_; -private: - __libcpp_unique_locale(__libcpp_unique_locale const&); - __libcpp_unique_locale& operator=(__libcpp_unique_locale const&); -}; - -#ifdef __cloc_defined -locale_t __cloc() { - // In theory this could create a race condition. In practice - // the race condition is non-fatal since it will just create - // a little resource leak. Better approach would be appreciated. - static locale_t result = newlocale(LC_ALL_MASK, "C", 0); - return result; -} -#endif // __cloc_defined - -namespace { - -struct release -{ - void operator()(locale::facet* p) {p->__release_shared();} -}; - -template <class T, class ...Args> -T& make(Args ...args) -{ - static typename aligned_storage<sizeof(T)>::type buf; - auto *obj = ::new (&buf) T(args...); - return *obj; -} - -template <typename T, size_t N> -inline -_LIBCPP_CONSTEXPR -size_t -countof(const T (&)[N]) -{ - return N; -} - -template <typename T> -inline -_LIBCPP_CONSTEXPR -size_t -countof(const T * const begin, const T * const end) -{ - return static_cast<size_t>(end - begin); -} - -_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg) -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - throw runtime_error(msg); -#else - (void)msg; - _VSTD::abort(); -#endif -} - -} - -#if defined(_AIX) -// Set priority to INT_MIN + 256 + 150 -# pragma priority ( -2147483242 ) -#endif - -const locale::category locale::none; -const locale::category locale::collate; -const locale::category locale::ctype; -const locale::category locale::monetary; -const locale::category locale::numeric; -const locale::category locale::time; -const locale::category locale::messages; -const locale::category locale::all; - -class _LIBCPP_HIDDEN locale::__imp - : public facet -{ - enum {N = 30}; - vector<facet*, __sso_allocator<facet*, N> > facets_; - string name_; -public: - explicit __imp(size_t refs = 0); - explicit __imp(const string& name, size_t refs = 0); - __imp(const __imp&); - __imp(const __imp&, const string&, locale::category c); - __imp(const __imp& other, const __imp& one, locale::category c); - __imp(const __imp&, facet* f, long id); - ~__imp(); - - const string& name() const {return name_;} - bool has_facet(long id) const - {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];} - const locale::facet* use_facet(long id) const; - - static const locale& make_classic(); - static locale& make_global(); -private: - void install(facet* f, long id); - template <class F> void install(F* f) {install(f, f->id.__get());} - template <class F> void install_from(const __imp& other); -}; - -locale::__imp::__imp(size_t refs) - : facet(refs), - facets_(N), - name_("C") -{ - facets_.clear(); - install(&make<_VSTD::collate<char> >(1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<_VSTD::collate<wchar_t> >(1u)); -#endif - install(&make<_VSTD::ctype<char> >(nullptr, false, 1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<_VSTD::ctype<wchar_t> >(1u)); -#endif - install(&make<codecvt<char, char, mbstate_t> >(1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<codecvt<wchar_t, char, mbstate_t> >(1u)); -#endif -_LIBCPP_SUPPRESS_DEPRECATED_PUSH - install(&make<codecvt<char16_t, char, mbstate_t> >(1u)); - install(&make<codecvt<char32_t, char, mbstate_t> >(1u)); -_LIBCPP_SUPPRESS_DEPRECATED_POP -#ifndef _LIBCPP_HAS_NO_CHAR8_T - install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u)); - install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u)); -#endif - install(&make<numpunct<char> >(1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<numpunct<wchar_t> >(1u)); -#endif - install(&make<num_get<char> >(1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<num_get<wchar_t> >(1u)); -#endif - install(&make<num_put<char> >(1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<num_put<wchar_t> >(1u)); -#endif - install(&make<moneypunct<char, false> >(1u)); - install(&make<moneypunct<char, true> >(1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<moneypunct<wchar_t, false> >(1u)); - install(&make<moneypunct<wchar_t, true> >(1u)); -#endif - install(&make<money_get<char> >(1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<money_get<wchar_t> >(1u)); -#endif - install(&make<money_put<char> >(1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<money_put<wchar_t> >(1u)); -#endif - install(&make<time_get<char> >(1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<time_get<wchar_t> >(1u)); -#endif - install(&make<time_put<char> >(1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<time_put<wchar_t> >(1u)); -#endif - install(&make<_VSTD::messages<char> >(1u)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(&make<_VSTD::messages<wchar_t> >(1u)); -#endif -} - -locale::__imp::__imp(const string& name, size_t refs) - : facet(refs), - facets_(N), - name_(name) -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - facets_ = locale::classic().__locale_->facets_; - for (unsigned i = 0; i < facets_.size(); ++i) - if (facets_[i]) - facets_[i]->__add_shared(); - install(new collate_byname<char>(name_)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new collate_byname<wchar_t>(name_)); -#endif - install(new ctype_byname<char>(name_)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new ctype_byname<wchar_t>(name_)); -#endif - install(new codecvt_byname<char, char, mbstate_t>(name_)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new codecvt_byname<wchar_t, char, mbstate_t>(name_)); -#endif -_LIBCPP_SUPPRESS_DEPRECATED_PUSH - install(new codecvt_byname<char16_t, char, mbstate_t>(name_)); - install(new codecvt_byname<char32_t, char, mbstate_t>(name_)); -_LIBCPP_SUPPRESS_DEPRECATED_POP -#ifndef _LIBCPP_HAS_NO_CHAR8_T - install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_)); - install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_)); -#endif - install(new numpunct_byname<char>(name_)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new numpunct_byname<wchar_t>(name_)); -#endif - install(new moneypunct_byname<char, false>(name_)); - install(new moneypunct_byname<char, true>(name_)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new moneypunct_byname<wchar_t, false>(name_)); - install(new moneypunct_byname<wchar_t, true>(name_)); -#endif - install(new time_get_byname<char>(name_)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new time_get_byname<wchar_t>(name_)); -#endif - install(new time_put_byname<char>(name_)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new time_put_byname<wchar_t>(name_)); -#endif - install(new messages_byname<char>(name_)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new messages_byname<wchar_t>(name_)); -#endif -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - for (unsigned i = 0; i < facets_.size(); ++i) - if (facets_[i]) - facets_[i]->__release_shared(); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -locale::__imp::__imp(const __imp& other) - : facets_(max<size_t>(N, other.facets_.size())), - name_(other.name_) -{ - facets_ = other.facets_; - for (unsigned i = 0; i < facets_.size(); ++i) - if (facets_[i]) - facets_[i]->__add_shared(); -} - -locale::__imp::__imp(const __imp& other, const string& name, locale::category c) - : facets_(N), - name_("*") -{ - facets_ = other.facets_; - for (unsigned i = 0; i < facets_.size(); ++i) - if (facets_[i]) - facets_[i]->__add_shared(); -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - if (c & locale::collate) - { - install(new collate_byname<char>(name)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new collate_byname<wchar_t>(name)); -#endif - } - if (c & locale::ctype) - { - install(new ctype_byname<char>(name)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new ctype_byname<wchar_t>(name)); -#endif - install(new codecvt_byname<char, char, mbstate_t>(name)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new codecvt_byname<wchar_t, char, mbstate_t>(name)); -#endif -_LIBCPP_SUPPRESS_DEPRECATED_PUSH - install(new codecvt_byname<char16_t, char, mbstate_t>(name)); - install(new codecvt_byname<char32_t, char, mbstate_t>(name)); -_LIBCPP_SUPPRESS_DEPRECATED_POP -#ifndef _LIBCPP_HAS_NO_CHAR8_T - install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name)); - install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name)); -#endif - } - if (c & locale::monetary) - { - install(new moneypunct_byname<char, false>(name)); - install(new moneypunct_byname<char, true>(name)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new moneypunct_byname<wchar_t, false>(name)); - install(new moneypunct_byname<wchar_t, true>(name)); -#endif - } - if (c & locale::numeric) - { - install(new numpunct_byname<char>(name)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new numpunct_byname<wchar_t>(name)); -#endif - } - if (c & locale::time) - { - install(new time_get_byname<char>(name)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new time_get_byname<wchar_t>(name)); -#endif - install(new time_put_byname<char>(name)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new time_put_byname<wchar_t>(name)); -#endif - } - if (c & locale::messages) - { - install(new messages_byname<char>(name)); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install(new messages_byname<wchar_t>(name)); -#endif - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - for (unsigned i = 0; i < facets_.size(); ++i) - if (facets_[i]) - facets_[i]->__release_shared(); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -template<class F> -inline -void -locale::__imp::install_from(const locale::__imp& one) -{ - long id = F::id.__get(); - install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id); -} - -locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c) - : facets_(N), - name_("*") -{ - facets_ = other.facets_; - for (unsigned i = 0; i < facets_.size(); ++i) - if (facets_[i]) - facets_[i]->__add_shared(); -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - if (c & locale::collate) - { - install_from<_VSTD::collate<char> >(one); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<_VSTD::collate<wchar_t> >(one); -#endif - } - if (c & locale::ctype) - { - install_from<_VSTD::ctype<char> >(one); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<_VSTD::ctype<wchar_t> >(one); -#endif - install_from<_VSTD::codecvt<char, char, mbstate_t> >(one); -_LIBCPP_SUPPRESS_DEPRECATED_PUSH - install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one); - install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one); -_LIBCPP_SUPPRESS_DEPRECATED_POP -#ifndef _LIBCPP_HAS_NO_CHAR8_T - install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one); - install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one); -#endif -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one); -#endif - } - if (c & locale::monetary) - { - install_from<moneypunct<char, false> >(one); - install_from<moneypunct<char, true> >(one); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<moneypunct<wchar_t, false> >(one); - install_from<moneypunct<wchar_t, true> >(one); -#endif - install_from<money_get<char> >(one); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<money_get<wchar_t> >(one); -#endif - install_from<money_put<char> >(one); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<money_put<wchar_t> >(one); -#endif - } - if (c & locale::numeric) - { - install_from<numpunct<char> >(one); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<numpunct<wchar_t> >(one); -#endif - install_from<num_get<char> >(one); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<num_get<wchar_t> >(one); -#endif - install_from<num_put<char> >(one); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<num_put<wchar_t> >(one); -#endif - } - if (c & locale::time) - { - install_from<time_get<char> >(one); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<time_get<wchar_t> >(one); -#endif - install_from<time_put<char> >(one); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<time_put<wchar_t> >(one); -#endif - } - if (c & locale::messages) - { - install_from<_VSTD::messages<char> >(one); -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - install_from<_VSTD::messages<wchar_t> >(one); -#endif - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - for (unsigned i = 0; i < facets_.size(); ++i) - if (facets_[i]) - facets_[i]->__release_shared(); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -locale::__imp::__imp(const __imp& other, facet* f, long id) - : facets_(max<size_t>(N, other.facets_.size()+1)), - name_("*") -{ - f->__add_shared(); - unique_ptr<facet, release> hold(f); - facets_ = other.facets_; - for (unsigned i = 0; i < other.facets_.size(); ++i) - if (facets_[i]) - facets_[i]->__add_shared(); - install(hold.get(), id); -} - -locale::__imp::~__imp() -{ - for (unsigned i = 0; i < facets_.size(); ++i) - if (facets_[i]) - facets_[i]->__release_shared(); -} - -void -locale::__imp::install(facet* f, long id) -{ - f->__add_shared(); - unique_ptr<facet, release> hold(f); - if (static_cast<size_t>(id) >= facets_.size()) - facets_.resize(static_cast<size_t>(id+1)); - if (facets_[static_cast<size_t>(id)]) - facets_[static_cast<size_t>(id)]->__release_shared(); - facets_[static_cast<size_t>(id)] = hold.release(); -} - -const locale::facet* -locale::__imp::use_facet(long id) const -{ - if (!has_facet(id)) - __throw_bad_cast(); - return facets_[static_cast<size_t>(id)]; -} - -// locale - -const locale& -locale::__imp::make_classic() -{ - // only one thread can get in here and it only gets in once - static aligned_storage<sizeof(locale)>::type buf; - locale* c = reinterpret_cast<locale*>(&buf); - c->__locale_ = &make<__imp>(1u); - return *c; -} - -const locale& -locale::classic() -{ - static const locale& c = __imp::make_classic(); - return c; -} - -locale& -locale::__imp::make_global() -{ - // only one thread can get in here and it only gets in once - static aligned_storage<sizeof(locale)>::type buf; - auto *obj = ::new (&buf) locale(locale::classic()); - return *obj; -} - -locale& -locale::__global() -{ - static locale& g = __imp::make_global(); - return g; -} - -locale::locale() noexcept - : __locale_(__global().__locale_) -{ - __locale_->__add_shared(); -} - -locale::locale(const locale& l) noexcept - : __locale_(l.__locale_) -{ - __locale_->__add_shared(); -} - -locale::~locale() -{ - __locale_->__release_shared(); -} - -const locale& -locale::operator=(const locale& other) noexcept -{ - other.__locale_->__add_shared(); - __locale_->__release_shared(); - __locale_ = other.__locale_; - return *this; -} - -locale::locale(const char* name) - : __locale_(name ? new __imp(name) - : (__throw_runtime_error("locale constructed with null"), nullptr)) -{ - __locale_->__add_shared(); -} - -locale::locale(const string& name) - : __locale_(new __imp(name)) -{ - __locale_->__add_shared(); -} - -locale::locale(const locale& other, const char* name, category c) - : __locale_(name ? new __imp(*other.__locale_, name, c) - : (__throw_runtime_error("locale constructed with null"), nullptr)) -{ - __locale_->__add_shared(); -} - -locale::locale(const locale& other, const string& name, category c) - : __locale_(new __imp(*other.__locale_, name, c)) -{ - __locale_->__add_shared(); -} - -locale::locale(const locale& other, const locale& one, category c) - : __locale_(new __imp(*other.__locale_, *one.__locale_, c)) -{ - __locale_->__add_shared(); -} - -string -locale::name() const -{ - return __locale_->name(); -} - -void -locale::__install_ctor(const locale& other, facet* f, long id) -{ - if (f) - __locale_ = new __imp(*other.__locale_, f, id); - else - __locale_ = other.__locale_; - __locale_->__add_shared(); -} - -locale -locale::global(const locale& loc) -{ - locale& g = __global(); - locale r = g; - g = loc; - if (g.name() != "*") - setlocale(LC_ALL, g.name().c_str()); - return r; -} - -bool -locale::has_facet(id& x) const -{ - return __locale_->has_facet(x.__get()); -} - -const locale::facet* -locale::use_facet(id& x) const -{ - return __locale_->use_facet(x.__get()); -} - -bool -locale::operator==(const locale& y) const -{ - return (__locale_ == y.__locale_) - || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name()); -} - -// locale::facet - -locale::facet::~facet() -{ -} - -void -locale::facet::__on_zero_shared() noexcept -{ - delete this; -} - -// locale::id - -namespace -{ - -class __fake_bind -{ - locale::id* id_; - void (locale::id::* pmf_)(); -public: - __fake_bind(void (locale::id::* pmf)(), locale::id* id) - : id_(id), pmf_(pmf) {} - - void operator()() const - { - (id_->*pmf_)(); - } -}; - -} - -int32_t locale::id::__next_id; - -long -locale::id::__get() -{ - int32_t result = __id_.load(std::memory_order_acquire); - if (result == 0) { - static std::mutex m; - std::lock_guard<std::mutex> guard(m); - result = __id_.load(std::memory_order_acquire); - if (result == 0) { - result = ++__next_id; - __id_.store(result, std::memory_order_release); - } - } - return result - 1; -} - -// template <> class collate_byname<char> - -collate_byname<char>::collate_byname(const char* n, size_t refs) - : collate<char>(refs), - __l(newlocale(LC_ALL_MASK, n, 0)) -{ - if (__l == 0) - __throw_runtime_error("collate_byname<char>::collate_byname" - " failed to construct for " + string(n)); -} - -collate_byname<char>::collate_byname(const string& name, size_t refs) - : collate<char>(refs), - __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) -{ - if (__l == 0) - __throw_runtime_error("collate_byname<char>::collate_byname" - " failed to construct for " + name); -} - -collate_byname<char>::~collate_byname() -{ - freelocale(__l); -} - -int -collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1, - const char_type* __lo2, const char_type* __hi2) const -{ - string_type lhs(__lo1, __hi1); - string_type rhs(__lo2, __hi2); - int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l); - if (r < 0) - return -1; - if (r > 0) - return 1; - return r; -} - -collate_byname<char>::string_type -collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const -{ - const string_type in(lo, hi); - string_type out(strxfrm_l(0, in.c_str(), 0, __l), char()); - strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l); - return out; -} - -// template <> class collate_byname<wchar_t> - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -collate_byname<wchar_t>::collate_byname(const char* n, size_t refs) - : collate<wchar_t>(refs), - __l(newlocale(LC_ALL_MASK, n, 0)) -{ - if (__l == 0) - __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" - " failed to construct for " + string(n)); -} - -collate_byname<wchar_t>::collate_byname(const string& name, size_t refs) - : collate<wchar_t>(refs), - __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) -{ - if (__l == 0) - __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" - " failed to construct for " + name); -} - -collate_byname<wchar_t>::~collate_byname() -{ - freelocale(__l); -} - -int -collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1, - const char_type* __lo2, const char_type* __hi2) const -{ - string_type lhs(__lo1, __hi1); - string_type rhs(__lo2, __hi2); - int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l); - if (r < 0) - return -1; - if (r > 0) - return 1; - return r; -} - -collate_byname<wchar_t>::string_type -collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const -{ - const string_type in(lo, hi); - string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t()); - wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l); - return out; -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -const ctype_base::mask ctype_base::space; -const ctype_base::mask ctype_base::print; -const ctype_base::mask ctype_base::cntrl; -const ctype_base::mask ctype_base::upper; -const ctype_base::mask ctype_base::lower; -const ctype_base::mask ctype_base::alpha; -const ctype_base::mask ctype_base::digit; -const ctype_base::mask ctype_base::punct; -const ctype_base::mask ctype_base::xdigit; -const ctype_base::mask ctype_base::blank; -const ctype_base::mask ctype_base::alnum; -const ctype_base::mask ctype_base::graph; - -// template <> class ctype<wchar_t>; - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -locale::id ctype<wchar_t>::id; - -ctype<wchar_t>::~ctype() -{ -} - -bool -ctype<wchar_t>::do_is(mask m, char_type c) const -{ - return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false; -} - -const wchar_t* -ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const -{ - for (; low != high; ++low, ++vec) - *vec = static_cast<mask>(isascii(*low) ? - ctype<char>::classic_table()[*low] : 0); - return low; -} - -const wchar_t* -ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const -{ - for (; low != high; ++low) - if (isascii(*low) && (ctype<char>::classic_table()[*low] & m)) - break; - return low; -} - -const wchar_t* -ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const -{ - for (; low != high; ++low) - if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m))) - break; - return low; -} - -wchar_t -ctype<wchar_t>::do_toupper(char_type c) const -{ -#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE - return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c; -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ - defined(__NetBSD__) - return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c; -#else - return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c; -#endif -} - -const wchar_t* -ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const -{ - for (; low != high; ++low) -#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE - *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low; -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ - defined(__NetBSD__) - *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low] - : *low; -#else - *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low; -#endif - return low; -} - -wchar_t -ctype<wchar_t>::do_tolower(char_type c) const -{ -#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE - return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c; -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ - defined(__NetBSD__) - return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c; -#else - return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c; -#endif -} - -const wchar_t* -ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const -{ - for (; low != high; ++low) -#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE - *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low; -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ - defined(__NetBSD__) - *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low] - : *low; -#else - *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low; -#endif - return low; -} - -wchar_t -ctype<wchar_t>::do_widen(char c) const -{ - return c; -} - -const char* -ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const -{ - for (; low != high; ++low, ++dest) - *dest = *low; - return low; -} - -char -ctype<wchar_t>::do_narrow(char_type c, char dfault) const -{ - if (isascii(c)) - return static_cast<char>(c); - return dfault; -} - -const wchar_t* -ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const -{ - for (; low != high; ++low, ++dest) - if (isascii(*low)) - *dest = static_cast<char>(*low); - else - *dest = dfault; - return low; -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -// template <> class ctype<char>; - -locale::id ctype<char>::id; - -ctype<char>::ctype(const mask* tab, bool del, size_t refs) - : locale::facet(refs), - __tab_(tab), - __del_(del) -{ - if (__tab_ == 0) - __tab_ = classic_table(); -} - -ctype<char>::~ctype() -{ - if (__tab_ && __del_) - delete [] __tab_; -} - -char -ctype<char>::do_toupper(char_type c) const -{ -#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE - return isascii(c) ? - static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c; -#elif defined(__NetBSD__) - return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]); -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) - return isascii(c) ? - static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c; -#else - return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c; -#endif -} - -const char* -ctype<char>::do_toupper(char_type* low, const char_type* high) const -{ - for (; low != high; ++low) -#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE - *low = isascii(*low) ? - static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low; -#elif defined(__NetBSD__) - *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]); -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) - *low = isascii(*low) ? - static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low; -#else - *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low; -#endif - return low; -} - -char -ctype<char>::do_tolower(char_type c) const -{ -#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE - return isascii(c) ? - static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c; -#elif defined(__NetBSD__) - return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]); -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) - return isascii(c) ? - static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c; -#else - return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c; -#endif -} - -const char* -ctype<char>::do_tolower(char_type* low, const char_type* high) const -{ - for (; low != high; ++low) -#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE - *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low; -#elif defined(__NetBSD__) - *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]); -#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) - *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low; -#else - *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low; -#endif - return low; -} - -char -ctype<char>::do_widen(char c) const -{ - return c; -} - -const char* -ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const -{ - for (; low != high; ++low, ++dest) - *dest = *low; - return low; -} - -char -ctype<char>::do_narrow(char_type c, char dfault) const -{ - if (isascii(c)) - return static_cast<char>(c); - return dfault; -} - -const char* -ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const -{ - for (; low != high; ++low, ++dest) - if (isascii(*low)) - *dest = *low; - else - *dest = dfault; - return low; -} - -#if defined(__EMSCRIPTEN__) -extern "C" const unsigned short ** __ctype_b_loc(); -extern "C" const int ** __ctype_tolower_loc(); -extern "C" const int ** __ctype_toupper_loc(); -#endif - -#if defined(__ANDROID__) -// See src/support/android/android_locale.cpp -extern "C" const unsigned short* const _ctype_android; -#endif - -#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE -const ctype<char>::mask* -ctype<char>::classic_table() noexcept -{ - static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = { - cntrl, cntrl, - cntrl, cntrl, - cntrl, cntrl, - cntrl, cntrl, - cntrl, cntrl | space | blank, - cntrl | space, cntrl | space, - cntrl | space, cntrl | space, - cntrl, cntrl, - cntrl, cntrl, - cntrl, cntrl, - cntrl, cntrl, - cntrl, cntrl, - cntrl, cntrl, - cntrl, cntrl, - cntrl, cntrl, - cntrl, cntrl, - space | blank | print, punct | print, - punct | print, punct | print, - punct | print, punct | print, - punct | print, punct | print, - punct | print, punct | print, - punct | print, punct | print, - punct | print, punct | print, - punct | print, punct | print, - digit | print | xdigit, digit | print | xdigit, - digit | print | xdigit, digit | print | xdigit, - digit | print | xdigit, digit | print | xdigit, - digit | print | xdigit, digit | print | xdigit, - digit | print | xdigit, digit | print | xdigit, - punct | print, punct | print, - punct | print, punct | print, - punct | print, punct | print, - punct | print, upper | xdigit | print | alpha, - upper | xdigit | print | alpha, upper | xdigit | print | alpha, - upper | xdigit | print | alpha, upper | xdigit | print | alpha, - upper | xdigit | print | alpha, upper | print | alpha, - upper | print | alpha, upper | print | alpha, - upper | print | alpha, upper | print | alpha, - upper | print | alpha, upper | print | alpha, - upper | print | alpha, upper | print | alpha, - upper | print | alpha, upper | print | alpha, - upper | print | alpha, upper | print | alpha, - upper | print | alpha, upper | print | alpha, - upper | print | alpha, upper | print | alpha, - upper | print | alpha, upper | print | alpha, - upper | print | alpha, punct | print, - punct | print, punct | print, - punct | print, punct | print, - punct | print, lower | xdigit | print | alpha, - lower | xdigit | print | alpha, lower | xdigit | print | alpha, - lower | xdigit | print | alpha, lower | xdigit | print | alpha, - lower | xdigit | print | alpha, lower | print | alpha, - lower | print | alpha, lower | print | alpha, - lower | print | alpha, lower | print | alpha, - lower | print | alpha, lower | print | alpha, - lower | print | alpha, lower | print | alpha, - lower | print | alpha, lower | print | alpha, - lower | print | alpha, lower | print | alpha, - lower | print | alpha, lower | print | alpha, - lower | print | alpha, lower | print | alpha, - lower | print | alpha, lower | print | alpha, - lower | print | alpha, punct | print, - punct | print, punct | print, - punct | print, cntrl, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - return builtin_table; -} -#else -const ctype<char>::mask* -ctype<char>::classic_table() noexcept -{ -#if defined(__APPLE__) || defined(__FreeBSD__) - return _DefaultRuneLocale.__runetype; -#elif defined(__NetBSD__) - return _C_ctype_tab_ + 1; -#elif defined(__GLIBC__) - return _LIBCPP_GET_C_LOCALE->__ctype_b; -#elif defined(__sun__) - return __ctype_mask; -#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) - return __pctype_func(); -#elif defined(__EMSCRIPTEN__) - return *__ctype_b_loc(); -#elif defined(_NEWLIB_VERSION) - // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1]. - return _ctype_ + 1; -#elif defined(__ANDROID__) - return _ctype_android; -#elif defined(_AIX) - return (const unsigned int *)__lc_ctype_ptr->obj->mask; -#else - // Platform not supported: abort so the person doing the port knows what to - // fix -# warning ctype<char>::classic_table() is not implemented - printf("ctype<char>::classic_table() is not implemented\n"); - abort(); - return NULL; -#endif -} -#endif - -#if defined(__GLIBC__) -const int* -ctype<char>::__classic_lower_table() noexcept -{ - return _LIBCPP_GET_C_LOCALE->__ctype_tolower; -} - -const int* -ctype<char>::__classic_upper_table() noexcept -{ - return _LIBCPP_GET_C_LOCALE->__ctype_toupper; -} -#elif defined(__NetBSD__) -const short* -ctype<char>::__classic_lower_table() noexcept -{ - return _C_tolower_tab_ + 1; -} - -const short* -ctype<char>::__classic_upper_table() noexcept -{ - return _C_toupper_tab_ + 1; -} - -#elif defined(__EMSCRIPTEN__) -const int* -ctype<char>::__classic_lower_table() noexcept -{ - return *__ctype_tolower_loc(); -} - -const int* -ctype<char>::__classic_upper_table() noexcept -{ - return *__ctype_toupper_loc(); -} -#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ - -// template <> class ctype_byname<char> - -ctype_byname<char>::ctype_byname(const char* name, size_t refs) - : ctype<char>(0, false, refs), - __l(newlocale(LC_ALL_MASK, name, 0)) -{ - if (__l == 0) - __throw_runtime_error("ctype_byname<char>::ctype_byname" - " failed to construct for " + string(name)); -} - -ctype_byname<char>::ctype_byname(const string& name, size_t refs) - : ctype<char>(0, false, refs), - __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) -{ - if (__l == 0) - __throw_runtime_error("ctype_byname<char>::ctype_byname" - " failed to construct for " + name); -} - -ctype_byname<char>::~ctype_byname() -{ - freelocale(__l); -} - -char -ctype_byname<char>::do_toupper(char_type c) const -{ - return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l)); -} - -const char* -ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const -{ - for (; low != high; ++low) - *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l)); - return low; -} - -char -ctype_byname<char>::do_tolower(char_type c) const -{ - return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l)); -} - -const char* -ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const -{ - for (; low != high; ++low) - *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l)); - return low; -} - -// template <> class ctype_byname<wchar_t> - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs) - : ctype<wchar_t>(refs), - __l(newlocale(LC_ALL_MASK, name, 0)) -{ - if (__l == 0) - __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname" - " failed to construct for " + string(name)); -} - -ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs) - : ctype<wchar_t>(refs), - __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) -{ - if (__l == 0) - __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname" - " failed to construct for " + name); -} - -ctype_byname<wchar_t>::~ctype_byname() -{ - freelocale(__l); -} - -bool -ctype_byname<wchar_t>::do_is(mask m, char_type c) const -{ -#ifdef _LIBCPP_WCTYPE_IS_MASK - return static_cast<bool>(iswctype_l(c, m, __l)); -#else - bool result = false; - wint_t ch = static_cast<wint_t>(c); - if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0); - if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0); - if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0); - if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0); - if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0); - if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0); - if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0); - if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0); - if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0); - if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0); - return result; -#endif -} - -const wchar_t* -ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const -{ - for (; low != high; ++low, ++vec) - { - if (isascii(*low)) - *vec = static_cast<mask>(ctype<char>::classic_table()[*low]); - else - { - *vec = 0; - wint_t ch = static_cast<wint_t>(*low); - if (iswspace_l(ch, __l)) - *vec |= space; -#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT - if (iswprint_l(ch, __l)) - *vec |= print; -#endif - if (iswcntrl_l(ch, __l)) - *vec |= cntrl; - if (iswupper_l(ch, __l)) - *vec |= upper; - if (iswlower_l(ch, __l)) - *vec |= lower; -#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA - if (iswalpha_l(ch, __l)) - *vec |= alpha; -#endif - if (iswdigit_l(ch, __l)) - *vec |= digit; - if (iswpunct_l(ch, __l)) - *vec |= punct; -#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT - if (iswxdigit_l(ch, __l)) - *vec |= xdigit; -#endif -#if !defined(__sun__) - if (iswblank_l(ch, __l)) - *vec |= blank; -#endif - } - } - return low; -} - -const wchar_t* -ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const -{ - for (; low != high; ++low) - { -#ifdef _LIBCPP_WCTYPE_IS_MASK - if (iswctype_l(*low, m, __l)) - break; -#else - wint_t ch = static_cast<wint_t>(*low); - if ((m & space) == space && iswspace_l(ch, __l)) break; - if ((m & print) == print && iswprint_l(ch, __l)) break; - if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break; - if ((m & upper) == upper && iswupper_l(ch, __l)) break; - if ((m & lower) == lower && iswlower_l(ch, __l)) break; - if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break; - if ((m & digit) == digit && iswdigit_l(ch, __l)) break; - if ((m & punct) == punct && iswpunct_l(ch, __l)) break; - if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break; - if ((m & blank) == blank && iswblank_l(ch, __l)) break; -#endif - } - return low; -} - -const wchar_t* -ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const -{ - for (; low != high; ++low) - { -#ifdef _LIBCPP_WCTYPE_IS_MASK - if (!iswctype_l(*low, m, __l)) - break; -#else - wint_t ch = static_cast<wint_t>(*low); - if ((m & space) == space && iswspace_l(ch, __l)) continue; - if ((m & print) == print && iswprint_l(ch, __l)) continue; - if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue; - if ((m & upper) == upper && iswupper_l(ch, __l)) continue; - if ((m & lower) == lower && iswlower_l(ch, __l)) continue; - if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue; - if ((m & digit) == digit && iswdigit_l(ch, __l)) continue; - if ((m & punct) == punct && iswpunct_l(ch, __l)) continue; - if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue; - if ((m & blank) == blank && iswblank_l(ch, __l)) continue; - break; -#endif - } - return low; -} - -wchar_t -ctype_byname<wchar_t>::do_toupper(char_type c) const -{ - return towupper_l(c, __l); -} - -const wchar_t* -ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const -{ - for (; low != high; ++low) - *low = towupper_l(*low, __l); - return low; -} - -wchar_t -ctype_byname<wchar_t>::do_tolower(char_type c) const -{ - return towlower_l(c, __l); -} - -const wchar_t* -ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const -{ - for (; low != high; ++low) - *low = towlower_l(*low, __l); - return low; -} - -wchar_t -ctype_byname<wchar_t>::do_widen(char c) const -{ - return __libcpp_btowc_l(c, __l); -} - -const char* -ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const -{ - for (; low != high; ++low, ++dest) - *dest = __libcpp_btowc_l(*low, __l); - return low; -} - -char -ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const -{ - int r = __libcpp_wctob_l(c, __l); - return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault; -} - -const wchar_t* -ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const -{ - for (; low != high; ++low, ++dest) - { - int r = __libcpp_wctob_l(*low, __l); - *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault; - } - return low; -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -// template <> class codecvt<char, char, mbstate_t> - -locale::id codecvt<char, char, mbstate_t>::id; - -codecvt<char, char, mbstate_t>::~codecvt() -{ -} - -codecvt<char, char, mbstate_t>::result -codecvt<char, char, mbstate_t>::do_out(state_type&, - const intern_type* frm, const intern_type*, const intern_type*& frm_nxt, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - frm_nxt = frm; - to_nxt = to; - return noconv; -} - -codecvt<char, char, mbstate_t>::result -codecvt<char, char, mbstate_t>::do_in(state_type&, - const extern_type* frm, const extern_type*, const extern_type*& frm_nxt, - intern_type* to, intern_type*, intern_type*& to_nxt) const -{ - frm_nxt = frm; - to_nxt = to; - return noconv; -} - -codecvt<char, char, mbstate_t>::result -codecvt<char, char, mbstate_t>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -codecvt<char, char, mbstate_t>::do_encoding() const noexcept -{ - return 1; -} - -bool -codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept -{ - return true; -} - -int -codecvt<char, char, mbstate_t>::do_length(state_type&, - const extern_type* frm, const extern_type* end, size_t mx) const -{ - return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm))); -} - -int -codecvt<char, char, mbstate_t>::do_max_length() const noexcept -{ - return 1; -} - -// template <> class codecvt<wchar_t, char, mbstate_t> - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -locale::id codecvt<wchar_t, char, mbstate_t>::id; - -codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs) - : locale::facet(refs), - __l(_LIBCPP_GET_C_LOCALE) -{ -} - -codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs) - : locale::facet(refs), - __l(newlocale(LC_ALL_MASK, nm, 0)) -{ - if (__l == 0) - __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname" - " failed to construct for " + string(nm)); -} - -codecvt<wchar_t, char, mbstate_t>::~codecvt() -{ - if (__l != _LIBCPP_GET_C_LOCALE) - freelocale(__l); -} - -codecvt<wchar_t, char, mbstate_t>::result -codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - // look for first internal null in frm - const intern_type* fend = frm; - for (; fend != frm_end; ++fend) - if (*fend == 0) - break; - // loop over all null-terminated sequences in frm - to_nxt = to; - for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) - { - // save state in case it is needed to recover to_nxt on error - mbstate_t save_state = st; - size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), - static_cast<size_t>(to_end-to), &st, __l); - if (n == size_t(-1)) - { - // need to recover to_nxt - for (to_nxt = to; frm != frm_nxt; ++frm) - { - n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l); - if (n == size_t(-1)) - break; - to_nxt += n; - } - frm_nxt = frm; - return error; - } - if (n == 0) - return partial; - to_nxt += n; - if (to_nxt == to_end) - break; - if (fend != frm_end) // set up next null terminated sequence - { - // Try to write the terminating null - extern_type tmp[MB_LEN_MAX]; - n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l); - if (n == size_t(-1)) // on error - return error; - if (n > static_cast<size_t>(to_end-to_nxt)) // is there room? - return partial; - for (extern_type* p = tmp; n; --n) // write it - *to_nxt++ = *p++; - ++frm_nxt; - // look for next null in frm - for (fend = frm_nxt; fend != frm_end; ++fend) - if (*fend == 0) - break; - } - } - return frm_nxt == frm_end ? ok : partial; -} - -codecvt<wchar_t, char, mbstate_t>::result -codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - // look for first internal null in frm - const extern_type* fend = frm; - for (; fend != frm_end; ++fend) - if (*fend == 0) - break; - // loop over all null-terminated sequences in frm - to_nxt = to; - for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) - { - // save state in case it is needed to recover to_nxt on error - mbstate_t save_state = st; - size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), - static_cast<size_t>(to_end-to), &st, __l); - if (n == size_t(-1)) - { - // need to recover to_nxt - for (to_nxt = to; frm != frm_nxt; ++to_nxt) - { - n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm), - &save_state, __l); - switch (n) - { - case 0: - ++frm; - break; - case size_t(-1): - frm_nxt = frm; - return error; - case size_t(-2): - frm_nxt = frm; - return partial; - default: - frm += n; - break; - } - } - frm_nxt = frm; - return frm_nxt == frm_end ? ok : partial; - } - if (n == size_t(-1)) - return error; - to_nxt += n; - if (to_nxt == to_end) - break; - if (fend != frm_end) // set up next null terminated sequence - { - // Try to write the terminating null - n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l); - if (n != 0) // on error - return error; - ++to_nxt; - ++frm_nxt; - // look for next null in frm - for (fend = frm_nxt; fend != frm_end; ++fend) - if (*fend == 0) - break; - } - } - return frm_nxt == frm_end ? ok : partial; -} - -codecvt<wchar_t, char, mbstate_t>::result -codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - to_nxt = to; - extern_type tmp[MB_LEN_MAX]; - size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l); - if (n == size_t(-1) || n == 0) // on error - return error; - --n; - if (n > static_cast<size_t>(to_end-to_nxt)) // is there room? - return partial; - for (extern_type* p = tmp; n; --n) // write it - *to_nxt++ = *p++; - return ok; -} - -int -codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept -{ - if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0) - return -1; - - // stateless encoding - if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings - return 1; // which take more than 1 char to form a wchar_t - return 0; -} - -bool -codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept -{ - return false; -} - -int -codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - int nbytes = 0; - for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t) - { - size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l); - switch (n) - { - case 0: - ++nbytes; - ++frm; - break; - case size_t(-1): - case size_t(-2): - return nbytes; - default: - nbytes += n; - frm += n; - break; - } - } - return nbytes; -} - -int -codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept -{ - return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l)); -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -// Valid UTF ranges -// UTF-32 UTF-16 UTF-8 # of code points -// first second first second third fourth -// 000000 - 00007F 0000 - 007F 00 - 7F 127 -// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920 -// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048 -// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152 -// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048 -// 00D800 - 00DFFF invalid -// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192 -// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608 -// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432 -// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536 - -static -codecvt_base::result -utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, - uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & generate_header) - { - if (to_end-to_nxt < 3) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xEF); - *to_nxt++ = static_cast<uint8_t>(0xBB); - *to_nxt++ = static_cast<uint8_t>(0xBF); - } - for (; frm_nxt < frm_end; ++frm_nxt) - { - uint16_t wc1 = *frm_nxt; - if (wc1 > Maxcode) - return codecvt_base::error; - if (wc1 < 0x0080) - { - if (to_end-to_nxt < 1) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(wc1); - } - else if (wc1 < 0x0800) - { - if (to_end-to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); - } - else if (wc1 < 0xD800) - { - if (to_end-to_nxt < 3) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); - } - else if (wc1 < 0xDC00) - { - if (frm_end-frm_nxt < 2) - return codecvt_base::partial; - uint16_t wc2 = frm_nxt[1]; - if ((wc2 & 0xFC00) != 0xDC00) - return codecvt_base::error; - if (to_end-to_nxt < 4) - return codecvt_base::partial; - if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + - ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode) - return codecvt_base::error; - ++frm_nxt; - uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; - *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F)); - } - else if (wc1 < 0xE000) - { - return codecvt_base::error; - } - else - { - if (to_end-to_nxt < 3) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); - } - } - return codecvt_base::ok; -} - -static -codecvt_base::result -utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, - uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & generate_header) - { - if (to_end-to_nxt < 3) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xEF); - *to_nxt++ = static_cast<uint8_t>(0xBB); - *to_nxt++ = static_cast<uint8_t>(0xBF); - } - for (; frm_nxt < frm_end; ++frm_nxt) - { - uint16_t wc1 = static_cast<uint16_t>(*frm_nxt); - if (wc1 > Maxcode) - return codecvt_base::error; - if (wc1 < 0x0080) - { - if (to_end-to_nxt < 1) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(wc1); - } - else if (wc1 < 0x0800) - { - if (to_end-to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); - } - else if (wc1 < 0xD800) - { - if (to_end-to_nxt < 3) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); - } - else if (wc1 < 0xDC00) - { - if (frm_end-frm_nxt < 2) - return codecvt_base::partial; - uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]); - if ((wc2 & 0xFC00) != 0xDC00) - return codecvt_base::error; - if (to_end-to_nxt < 4) - return codecvt_base::partial; - if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + - ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode) - return codecvt_base::error; - ++frm_nxt; - uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; - *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F)); - } - else if (wc1 < 0xE000) - { - return codecvt_base::error; - } - else - { - if (to_end-to_nxt < 3) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); - } - } - return codecvt_base::ok; -} - -static -codecvt_base::result -utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, - uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && - frm_nxt[2] == 0xBF) - frm_nxt += 3; - } - for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) - { - uint8_t c1 = *frm_nxt; - if (c1 > Maxcode) - return codecvt_base::error; - if (c1 < 0x80) - { - *to_nxt = static_cast<uint16_t>(c1); - ++frm_nxt; - } - else if (c1 < 0xC2) - { - return codecvt_base::error; - } - else if (c1 < 0xE0) - { - if (frm_end-frm_nxt < 2) - return codecvt_base::partial; - uint8_t c2 = frm_nxt[1]; - if ((c2 & 0xC0) != 0x80) - return codecvt_base::error; - uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); - if (t > Maxcode) - return codecvt_base::error; - *to_nxt = t; - frm_nxt += 2; - } - else if (c1 < 0xF0) - { - if (frm_end-frm_nxt < 3) - return codecvt_base::partial; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - switch (c1) - { - case 0xE0: - if ((c2 & 0xE0) != 0xA0) - return codecvt_base::error; - break; - case 0xED: - if ((c2 & 0xE0) != 0x80) - return codecvt_base::error; - break; - default: - if ((c2 & 0xC0) != 0x80) - return codecvt_base::error; - break; - } - if ((c3 & 0xC0) != 0x80) - return codecvt_base::error; - uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) - | ((c2 & 0x3F) << 6) - | (c3 & 0x3F)); - if (t > Maxcode) - return codecvt_base::error; - *to_nxt = t; - frm_nxt += 3; - } - else if (c1 < 0xF5) - { - if (frm_end-frm_nxt < 4) - return codecvt_base::partial; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - uint8_t c4 = frm_nxt[3]; - switch (c1) - { - case 0xF0: - if (!(0x90 <= c2 && c2 <= 0xBF)) - return codecvt_base::error; - break; - case 0xF4: - if ((c2 & 0xF0) != 0x80) - return codecvt_base::error; - break; - default: - if ((c2 & 0xC0) != 0x80) - return codecvt_base::error; - break; - } - if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) - return codecvt_base::error; - if (to_end-to_nxt < 2) - return codecvt_base::partial; - if ((((c1 & 7UL) << 18) + - ((c2 & 0x3FUL) << 12) + - ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) - return codecvt_base::error; - *to_nxt = static_cast<uint16_t>( - 0xD800 - | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) - | ((c2 & 0x0F) << 2) - | ((c3 & 0x30) >> 4)); - *++to_nxt = static_cast<uint16_t>( - 0xDC00 - | ((c3 & 0x0F) << 6) - | (c4 & 0x3F)); - frm_nxt += 4; - } - else - { - return codecvt_base::error; - } - } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; -} - -static -codecvt_base::result -utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, - uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && - frm_nxt[2] == 0xBF) - frm_nxt += 3; - } - for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) - { - uint8_t c1 = *frm_nxt; - if (c1 > Maxcode) - return codecvt_base::error; - if (c1 < 0x80) - { - *to_nxt = static_cast<uint32_t>(c1); - ++frm_nxt; - } - else if (c1 < 0xC2) - { - return codecvt_base::error; - } - else if (c1 < 0xE0) - { - if (frm_end-frm_nxt < 2) - return codecvt_base::partial; - uint8_t c2 = frm_nxt[1]; - if ((c2 & 0xC0) != 0x80) - return codecvt_base::error; - uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); - if (t > Maxcode) - return codecvt_base::error; - *to_nxt = static_cast<uint32_t>(t); - frm_nxt += 2; - } - else if (c1 < 0xF0) - { - if (frm_end-frm_nxt < 3) - return codecvt_base::partial; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - switch (c1) - { - case 0xE0: - if ((c2 & 0xE0) != 0xA0) - return codecvt_base::error; - break; - case 0xED: - if ((c2 & 0xE0) != 0x80) - return codecvt_base::error; - break; - default: - if ((c2 & 0xC0) != 0x80) - return codecvt_base::error; - break; - } - if ((c3 & 0xC0) != 0x80) - return codecvt_base::error; - uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) - | ((c2 & 0x3F) << 6) - | (c3 & 0x3F)); - if (t > Maxcode) - return codecvt_base::error; - *to_nxt = static_cast<uint32_t>(t); - frm_nxt += 3; - } - else if (c1 < 0xF5) - { - if (frm_end-frm_nxt < 4) - return codecvt_base::partial; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - uint8_t c4 = frm_nxt[3]; - switch (c1) - { - case 0xF0: - if (!(0x90 <= c2 && c2 <= 0xBF)) - return codecvt_base::error; - break; - case 0xF4: - if ((c2 & 0xF0) != 0x80) - return codecvt_base::error; - break; - default: - if ((c2 & 0xC0) != 0x80) - return codecvt_base::error; - break; - } - if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) - return codecvt_base::error; - if (to_end-to_nxt < 2) - return codecvt_base::partial; - if ((((c1 & 7UL) << 18) + - ((c2 & 0x3FUL) << 12) + - ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) - return codecvt_base::error; - *to_nxt = static_cast<uint32_t>( - 0xD800 - | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) - | ((c2 & 0x0F) << 2) - | ((c3 & 0x30) >> 4)); - *++to_nxt = static_cast<uint32_t>( - 0xDC00 - | ((c3 & 0x0F) << 6) - | (c4 & 0x3F)); - frm_nxt += 4; - } - else - { - return codecvt_base::error; - } - } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; -} - -static -int -utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end, - size_t mx, unsigned long Maxcode = 0x10FFFF, - codecvt_mode mode = codecvt_mode(0)) -{ - const uint8_t* frm_nxt = frm; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && - frm_nxt[2] == 0xBF) - frm_nxt += 3; - } - for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t) - { - uint8_t c1 = *frm_nxt; - if (c1 > Maxcode) - break; - if (c1 < 0x80) - { - ++frm_nxt; - } - else if (c1 < 0xC2) - { - break; - } - else if (c1 < 0xE0) - { - if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80) - break; - uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)); - if (t > Maxcode) - break; - frm_nxt += 2; - } - else if (c1 < 0xF0) - { - if (frm_end-frm_nxt < 3) - break; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - switch (c1) - { - case 0xE0: - if ((c2 & 0xE0) != 0xA0) - return static_cast<int>(frm_nxt - frm); - break; - case 0xED: - if ((c2 & 0xE0) != 0x80) - return static_cast<int>(frm_nxt - frm); - break; - default: - if ((c2 & 0xC0) != 0x80) - return static_cast<int>(frm_nxt - frm); - break; - } - if ((c3 & 0xC0) != 0x80) - break; - if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) - break; - frm_nxt += 3; - } - else if (c1 < 0xF5) - { - if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2) - break; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - uint8_t c4 = frm_nxt[3]; - switch (c1) - { - case 0xF0: - if (!(0x90 <= c2 && c2 <= 0xBF)) - return static_cast<int>(frm_nxt - frm); - break; - case 0xF4: - if ((c2 & 0xF0) != 0x80) - return static_cast<int>(frm_nxt - frm); - break; - default: - if ((c2 & 0xC0) != 0x80) - return static_cast<int>(frm_nxt - frm); - break; - } - if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) - break; - if ((((c1 & 7UL) << 18) + - ((c2 & 0x3FUL) << 12) + - ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) - break; - ++nchar16_t; - frm_nxt += 4; - } - else - { - break; - } - } - return static_cast<int>(frm_nxt - frm); -} - -static -codecvt_base::result -ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, - uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & generate_header) - { - if (to_end-to_nxt < 3) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xEF); - *to_nxt++ = static_cast<uint8_t>(0xBB); - *to_nxt++ = static_cast<uint8_t>(0xBF); - } - for (; frm_nxt < frm_end; ++frm_nxt) - { - uint32_t wc = *frm_nxt; - if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) - return codecvt_base::error; - if (wc < 0x000080) - { - if (to_end-to_nxt < 1) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(wc); - } - else if (wc < 0x000800) - { - if (to_end-to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); - } - else if (wc < 0x010000) - { - if (to_end-to_nxt < 3) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F)); - } - else // if (wc < 0x110000) - { - if (to_end-to_nxt < 4) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F)); - } - } - return codecvt_base::ok; -} - -static -codecvt_base::result -utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, - uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && - frm_nxt[2] == 0xBF) - frm_nxt += 3; - } - for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) - { - uint8_t c1 = static_cast<uint8_t>(*frm_nxt); - if (c1 < 0x80) - { - if (c1 > Maxcode) - return codecvt_base::error; - *to_nxt = static_cast<uint32_t>(c1); - ++frm_nxt; - } - else if (c1 < 0xC2) - { - return codecvt_base::error; - } - else if (c1 < 0xE0) - { - if (frm_end-frm_nxt < 2) - return codecvt_base::partial; - uint8_t c2 = frm_nxt[1]; - if ((c2 & 0xC0) != 0x80) - return codecvt_base::error; - uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6) - | (c2 & 0x3F)); - if (t > Maxcode) - return codecvt_base::error; - *to_nxt = t; - frm_nxt += 2; - } - else if (c1 < 0xF0) - { - if (frm_end-frm_nxt < 3) - return codecvt_base::partial; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - switch (c1) - { - case 0xE0: - if ((c2 & 0xE0) != 0xA0) - return codecvt_base::error; - break; - case 0xED: - if ((c2 & 0xE0) != 0x80) - return codecvt_base::error; - break; - default: - if ((c2 & 0xC0) != 0x80) - return codecvt_base::error; - break; - } - if ((c3 & 0xC0) != 0x80) - return codecvt_base::error; - uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12) - | ((c2 & 0x3F) << 6) - | (c3 & 0x3F)); - if (t > Maxcode) - return codecvt_base::error; - *to_nxt = t; - frm_nxt += 3; - } - else if (c1 < 0xF5) - { - if (frm_end-frm_nxt < 4) - return codecvt_base::partial; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - uint8_t c4 = frm_nxt[3]; - switch (c1) - { - case 0xF0: - if (!(0x90 <= c2 && c2 <= 0xBF)) - return codecvt_base::error; - break; - case 0xF4: - if ((c2 & 0xF0) != 0x80) - return codecvt_base::error; - break; - default: - if ((c2 & 0xC0) != 0x80) - return codecvt_base::error; - break; - } - if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) - return codecvt_base::error; - uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18) - | ((c2 & 0x3F) << 12) - | ((c3 & 0x3F) << 6) - | (c4 & 0x3F)); - if (t > Maxcode) - return codecvt_base::error; - *to_nxt = t; - frm_nxt += 4; - } - else - { - return codecvt_base::error; - } - } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; -} - -static -int -utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, - size_t mx, unsigned long Maxcode = 0x10FFFF, - codecvt_mode mode = codecvt_mode(0)) -{ - const uint8_t* frm_nxt = frm; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && - frm_nxt[2] == 0xBF) - frm_nxt += 3; - } - for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) - { - uint8_t c1 = static_cast<uint8_t>(*frm_nxt); - if (c1 < 0x80) - { - if (c1 > Maxcode) - break; - ++frm_nxt; - } - else if (c1 < 0xC2) - { - break; - } - else if (c1 < 0xE0) - { - if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) - break; - if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) - break; - frm_nxt += 2; - } - else if (c1 < 0xF0) - { - if (frm_end-frm_nxt < 3) - break; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - switch (c1) - { - case 0xE0: - if ((c2 & 0xE0) != 0xA0) - return static_cast<int>(frm_nxt - frm); - break; - case 0xED: - if ((c2 & 0xE0) != 0x80) - return static_cast<int>(frm_nxt - frm); - break; - default: - if ((c2 & 0xC0) != 0x80) - return static_cast<int>(frm_nxt - frm); - break; - } - if ((c3 & 0xC0) != 0x80) - break; - if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) - break; - frm_nxt += 3; - } - else if (c1 < 0xF5) - { - if (frm_end-frm_nxt < 4) - break; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - uint8_t c4 = frm_nxt[3]; - switch (c1) - { - case 0xF0: - if (!(0x90 <= c2 && c2 <= 0xBF)) - return static_cast<int>(frm_nxt - frm); - break; - case 0xF4: - if ((c2 & 0xF0) != 0x80) - return static_cast<int>(frm_nxt - frm); - break; - default: - if ((c2 & 0xC0) != 0x80) - return static_cast<int>(frm_nxt - frm); - break; - } - if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) - break; - if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) | - ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode) - break; - frm_nxt += 4; - } - else - { - break; - } - } - return static_cast<int>(frm_nxt - frm); -} - -static -codecvt_base::result -ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, - uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & generate_header) - { - if (to_end-to_nxt < 3) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xEF); - *to_nxt++ = static_cast<uint8_t>(0xBB); - *to_nxt++ = static_cast<uint8_t>(0xBF); - } - for (; frm_nxt < frm_end; ++frm_nxt) - { - uint16_t wc = *frm_nxt; - if ((wc & 0xF800) == 0xD800 || wc > Maxcode) - return codecvt_base::error; - if (wc < 0x0080) - { - if (to_end-to_nxt < 1) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(wc); - } - else if (wc < 0x0800) - { - if (to_end-to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); - } - else // if (wc <= 0xFFFF) - { - if (to_end-to_nxt < 3) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12)); - *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); - *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F)); - } - } - return codecvt_base::ok; -} - -static -codecvt_base::result -utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, - uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && - frm_nxt[2] == 0xBF) - frm_nxt += 3; - } - for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) - { - uint8_t c1 = static_cast<uint8_t>(*frm_nxt); - if (c1 < 0x80) - { - if (c1 > Maxcode) - return codecvt_base::error; - *to_nxt = static_cast<uint16_t>(c1); - ++frm_nxt; - } - else if (c1 < 0xC2) - { - return codecvt_base::error; - } - else if (c1 < 0xE0) - { - if (frm_end-frm_nxt < 2) - return codecvt_base::partial; - uint8_t c2 = frm_nxt[1]; - if ((c2 & 0xC0) != 0x80) - return codecvt_base::error; - uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) - | (c2 & 0x3F)); - if (t > Maxcode) - return codecvt_base::error; - *to_nxt = t; - frm_nxt += 2; - } - else if (c1 < 0xF0) - { - if (frm_end-frm_nxt < 3) - return codecvt_base::partial; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - switch (c1) - { - case 0xE0: - if ((c2 & 0xE0) != 0xA0) - return codecvt_base::error; - break; - case 0xED: - if ((c2 & 0xE0) != 0x80) - return codecvt_base::error; - break; - default: - if ((c2 & 0xC0) != 0x80) - return codecvt_base::error; - break; - } - if ((c3 & 0xC0) != 0x80) - return codecvt_base::error; - uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) - | ((c2 & 0x3F) << 6) - | (c3 & 0x3F)); - if (t > Maxcode) - return codecvt_base::error; - *to_nxt = t; - frm_nxt += 3; - } - else - { - return codecvt_base::error; - } - } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; -} - -static -int -utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, - size_t mx, unsigned long Maxcode = 0x10FFFF, - codecvt_mode mode = codecvt_mode(0)) -{ - const uint8_t* frm_nxt = frm; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && - frm_nxt[2] == 0xBF) - frm_nxt += 3; - } - for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) - { - uint8_t c1 = static_cast<uint8_t>(*frm_nxt); - if (c1 < 0x80) - { - if (c1 > Maxcode) - break; - ++frm_nxt; - } - else if (c1 < 0xC2) - { - break; - } - else if (c1 < 0xE0) - { - if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) - break; - if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) - break; - frm_nxt += 2; - } - else if (c1 < 0xF0) - { - if (frm_end-frm_nxt < 3) - break; - uint8_t c2 = frm_nxt[1]; - uint8_t c3 = frm_nxt[2]; - switch (c1) - { - case 0xE0: - if ((c2 & 0xE0) != 0xA0) - return static_cast<int>(frm_nxt - frm); - break; - case 0xED: - if ((c2 & 0xE0) != 0x80) - return static_cast<int>(frm_nxt - frm); - break; - default: - if ((c2 & 0xC0) != 0x80) - return static_cast<int>(frm_nxt - frm); - break; - } - if ((c3 & 0xC0) != 0x80) - break; - if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) - break; - frm_nxt += 3; - } - else - { - break; - } - } - return static_cast<int>(frm_nxt - frm); -} - -static -codecvt_base::result -ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, - uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & generate_header) - { - if (to_end-to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xFE); - *to_nxt++ = static_cast<uint8_t>(0xFF); - } - for (; frm_nxt < frm_end; ++frm_nxt) - { - uint32_t wc = *frm_nxt; - if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) - return codecvt_base::error; - if (wc < 0x010000) - { - if (to_end-to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(wc >> 8); - *to_nxt++ = static_cast<uint8_t>(wc); - } - else - { - if (to_end-to_nxt < 4) - return codecvt_base::partial; - uint16_t t = static_cast<uint16_t>( - 0xD800 - | ((((wc & 0x1F0000) >> 16) - 1) << 6) - | ((wc & 0x00FC00) >> 10)); - *to_nxt++ = static_cast<uint8_t>(t >> 8); - *to_nxt++ = static_cast<uint8_t>(t); - t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); - *to_nxt++ = static_cast<uint8_t>(t >> 8); - *to_nxt++ = static_cast<uint8_t>(t); - } - } - return codecvt_base::ok; -} - -static -codecvt_base::result -utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, - uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) - frm_nxt += 2; - } - for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) - { - uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); - if ((c1 & 0xFC00) == 0xDC00) - return codecvt_base::error; - if ((c1 & 0xFC00) != 0xD800) - { - if (c1 > Maxcode) - return codecvt_base::error; - *to_nxt = static_cast<uint32_t>(c1); - frm_nxt += 2; - } - else - { - if (frm_end-frm_nxt < 4) - return codecvt_base::partial; - uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); - if ((c2 & 0xFC00) != 0xDC00) - return codecvt_base::error; - uint32_t t = static_cast<uint32_t>( - ((((c1 & 0x03C0) >> 6) + 1) << 16) - | ((c1 & 0x003F) << 10) - | (c2 & 0x03FF)); - if (t > Maxcode) - return codecvt_base::error; - *to_nxt = t; - frm_nxt += 4; - } - } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; -} - -static -int -utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, - size_t mx, unsigned long Maxcode = 0x10FFFF, - codecvt_mode mode = codecvt_mode(0)) -{ - const uint8_t* frm_nxt = frm; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) - frm_nxt += 2; - } - for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) - { - uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); - if ((c1 & 0xFC00) == 0xDC00) - break; - if ((c1 & 0xFC00) != 0xD800) - { - if (c1 > Maxcode) - break; - frm_nxt += 2; - } - else - { - if (frm_end-frm_nxt < 4) - break; - uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); - if ((c2 & 0xFC00) != 0xDC00) - break; - uint32_t t = static_cast<uint32_t>( - ((((c1 & 0x03C0) >> 6) + 1) << 16) - | ((c1 & 0x003F) << 10) - | (c2 & 0x03FF)); - if (t > Maxcode) - break; - frm_nxt += 4; - } - } - return static_cast<int>(frm_nxt - frm); -} - -static -codecvt_base::result -ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, - uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & generate_header) - { - if (to_end - to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xFF); - *to_nxt++ = static_cast<uint8_t>(0xFE); - } - for (; frm_nxt < frm_end; ++frm_nxt) - { - uint32_t wc = *frm_nxt; - if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) - return codecvt_base::error; - if (wc < 0x010000) - { - if (to_end-to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(wc); - *to_nxt++ = static_cast<uint8_t>(wc >> 8); - } - else - { - if (to_end-to_nxt < 4) - return codecvt_base::partial; - uint16_t t = static_cast<uint16_t>( - 0xD800 - | ((((wc & 0x1F0000) >> 16) - 1) << 6) - | ((wc & 0x00FC00) >> 10)); - *to_nxt++ = static_cast<uint8_t>(t); - *to_nxt++ = static_cast<uint8_t>(t >> 8); - t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); - *to_nxt++ = static_cast<uint8_t>(t); - *to_nxt++ = static_cast<uint8_t>(t >> 8); - } - } - return codecvt_base::ok; -} - -static -codecvt_base::result -utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, - uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) - frm_nxt += 2; - } - for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) - { - uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); - if ((c1 & 0xFC00) == 0xDC00) - return codecvt_base::error; - if ((c1 & 0xFC00) != 0xD800) - { - if (c1 > Maxcode) - return codecvt_base::error; - *to_nxt = static_cast<uint32_t>(c1); - frm_nxt += 2; - } - else - { - if (frm_end-frm_nxt < 4) - return codecvt_base::partial; - uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); - if ((c2 & 0xFC00) != 0xDC00) - return codecvt_base::error; - uint32_t t = static_cast<uint32_t>( - ((((c1 & 0x03C0) >> 6) + 1) << 16) - | ((c1 & 0x003F) << 10) - | (c2 & 0x03FF)); - if (t > Maxcode) - return codecvt_base::error; - *to_nxt = t; - frm_nxt += 4; - } - } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; -} - -static -int -utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, - size_t mx, unsigned long Maxcode = 0x10FFFF, - codecvt_mode mode = codecvt_mode(0)) -{ - const uint8_t* frm_nxt = frm; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) - frm_nxt += 2; - } - for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) - { - uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); - if ((c1 & 0xFC00) == 0xDC00) - break; - if ((c1 & 0xFC00) != 0xD800) - { - if (c1 > Maxcode) - break; - frm_nxt += 2; - } - else - { - if (frm_end-frm_nxt < 4) - break; - uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); - if ((c2 & 0xFC00) != 0xDC00) - break; - uint32_t t = static_cast<uint32_t>( - ((((c1 & 0x03C0) >> 6) + 1) << 16) - | ((c1 & 0x003F) << 10) - | (c2 & 0x03FF)); - if (t > Maxcode) - break; - frm_nxt += 4; - } - } - return static_cast<int>(frm_nxt - frm); -} - -static -codecvt_base::result -ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, - uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & generate_header) - { - if (to_end-to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xFE); - *to_nxt++ = static_cast<uint8_t>(0xFF); - } - for (; frm_nxt < frm_end; ++frm_nxt) - { - uint16_t wc = *frm_nxt; - if ((wc & 0xF800) == 0xD800 || wc > Maxcode) - return codecvt_base::error; - if (to_end-to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(wc >> 8); - *to_nxt++ = static_cast<uint8_t>(wc); - } - return codecvt_base::ok; -} - -static -codecvt_base::result -utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, - uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) - frm_nxt += 2; - } - for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) - { - uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); - if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) - return codecvt_base::error; - *to_nxt = c1; - frm_nxt += 2; - } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; -} - -static -int -utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, - size_t mx, unsigned long Maxcode = 0x10FFFF, - codecvt_mode mode = codecvt_mode(0)) -{ - const uint8_t* frm_nxt = frm; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) - frm_nxt += 2; - } - for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) - { - uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); - if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) - break; - frm_nxt += 2; - } - return static_cast<int>(frm_nxt - frm); -} - -static -codecvt_base::result -ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, - uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & generate_header) - { - if (to_end-to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xFF); - *to_nxt++ = static_cast<uint8_t>(0xFE); - } - for (; frm_nxt < frm_end; ++frm_nxt) - { - uint16_t wc = *frm_nxt; - if ((wc & 0xF800) == 0xD800 || wc > Maxcode) - return codecvt_base::error; - if (to_end-to_nxt < 2) - return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(wc); - *to_nxt++ = static_cast<uint8_t>(wc >> 8); - } - return codecvt_base::ok; -} - -static -codecvt_base::result -utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, - uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, - unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) -{ - frm_nxt = frm; - to_nxt = to; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) - frm_nxt += 2; - } - for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) - { - uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); - if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) - return codecvt_base::error; - *to_nxt = c1; - frm_nxt += 2; - } - return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; -} - -static -int -utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, - size_t mx, unsigned long Maxcode = 0x10FFFF, - codecvt_mode mode = codecvt_mode(0)) -{ - const uint8_t* frm_nxt = frm; - frm_nxt = frm; - if (mode & consume_header) - { - if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) - frm_nxt += 2; - } - for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) - { - uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); - if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) - break; - frm_nxt += 2; - } - return static_cast<int>(frm_nxt - frm); -} - -// template <> class codecvt<char16_t, char, mbstate_t> - -locale::id codecvt<char16_t, char, mbstate_t>::id; - -codecvt<char16_t, char, mbstate_t>::~codecvt() -{ -} - -codecvt<char16_t, char, mbstate_t>::result -codecvt<char16_t, char, mbstate_t>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); - const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); - const uint16_t* _frm_nxt = _frm; - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -codecvt<char16_t, char, mbstate_t>::result -codecvt<char16_t, char, mbstate_t>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; - uint16_t* _to = reinterpret_cast<uint16_t*>(to); - uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); - uint16_t* _to_nxt = _to; - result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -codecvt<char16_t, char, mbstate_t>::result -codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept -{ - return 0; -} - -bool -codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept -{ - return false; -} - -int -codecvt<char16_t, char, mbstate_t>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf8_to_utf16_length(_frm, _frm_end, mx); -} - -int -codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept -{ - return 4; -} - -#ifndef _LIBCPP_HAS_NO_CHAR8_T - -// template <> class codecvt<char16_t, char8_t, mbstate_t> - -locale::id codecvt<char16_t, char8_t, mbstate_t>::id; - -codecvt<char16_t, char8_t, mbstate_t>::~codecvt() -{ -} - -codecvt<char16_t, char8_t, mbstate_t>::result -codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); - const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); - const uint16_t* _frm_nxt = _frm; - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -codecvt<char16_t, char8_t, mbstate_t>::result -codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; - uint16_t* _to = reinterpret_cast<uint16_t*>(to); - uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); - uint16_t* _to_nxt = _to; - result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -codecvt<char16_t, char8_t, mbstate_t>::result -codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept -{ - return 0; -} - -bool -codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept -{ - return false; -} - -int -codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf8_to_utf16_length(_frm, _frm_end, mx); -} - -int -codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept -{ - return 4; -} - -#endif - -// template <> class codecvt<char32_t, char, mbstate_t> - -locale::id codecvt<char32_t, char, mbstate_t>::id; - -codecvt<char32_t, char, mbstate_t>::~codecvt() -{ -} - -codecvt<char32_t, char, mbstate_t>::result -codecvt<char32_t, char, mbstate_t>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); - const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); - const uint32_t* _frm_nxt = _frm; - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -codecvt<char32_t, char, mbstate_t>::result -codecvt<char32_t, char, mbstate_t>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; - uint32_t* _to = reinterpret_cast<uint32_t*>(to); - uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); - uint32_t* _to_nxt = _to; - result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -codecvt<char32_t, char, mbstate_t>::result -codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept -{ - return 0; -} - -bool -codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept -{ - return false; -} - -int -codecvt<char32_t, char, mbstate_t>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf8_to_ucs4_length(_frm, _frm_end, mx); -} - -int -codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept -{ - return 4; -} - -#ifndef _LIBCPP_HAS_NO_CHAR8_T - -// template <> class codecvt<char32_t, char8_t, mbstate_t> - -locale::id codecvt<char32_t, char8_t, mbstate_t>::id; - -codecvt<char32_t, char8_t, mbstate_t>::~codecvt() -{ -} - -codecvt<char32_t, char8_t, mbstate_t>::result -codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); - const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); - const uint32_t* _frm_nxt = _frm; - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -codecvt<char32_t, char8_t, mbstate_t>::result -codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; - uint32_t* _to = reinterpret_cast<uint32_t*>(to); - uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); - uint32_t* _to_nxt = _to; - result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -codecvt<char32_t, char8_t, mbstate_t>::result -codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept -{ - return 0; -} - -bool -codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept -{ - return false; -} - -int -codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf8_to_ucs4_length(_frm, _frm_end, mx); -} - -int -codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept -{ - return 4; -} - -#endif - -// __codecvt_utf8<wchar_t> - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -__codecvt_utf8<wchar_t>::result -__codecvt_utf8<wchar_t>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ -#if defined(_LIBCPP_SHORT_WCHAR) - const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); - const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); - const uint16_t* _frm_nxt = _frm; -#else - const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); - const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); - const uint32_t* _frm_nxt = _frm; -#endif - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; -#if defined(_LIBCPP_SHORT_WCHAR) - result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#else - result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#endif - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8<wchar_t>::result -__codecvt_utf8<wchar_t>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; -#if defined(_LIBCPP_SHORT_WCHAR) - uint16_t* _to = reinterpret_cast<uint16_t*>(to); - uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); - uint16_t* _to_nxt = _to; - result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#else - uint32_t* _to = reinterpret_cast<uint32_t*>(to); - uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); - uint32_t* _to_nxt = _to; - result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#endif - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8<wchar_t>::result -__codecvt_utf8<wchar_t>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf8<wchar_t>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf8<wchar_t>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); -#if defined(_LIBCPP_SHORT_WCHAR) - return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -#else - return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -#endif -} - -int -__codecvt_utf8<wchar_t>::do_max_length() const noexcept -{ -#if defined(_LIBCPP_SHORT_WCHAR) - if (_Mode_ & consume_header) - return 6; - return 3; -#else - if (_Mode_ & consume_header) - return 7; - return 4; -#endif -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -// __codecvt_utf8<char16_t> - -__codecvt_utf8<char16_t>::result -__codecvt_utf8<char16_t>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); - const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); - const uint16_t* _frm_nxt = _frm; - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8<char16_t>::result -__codecvt_utf8<char16_t>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; - uint16_t* _to = reinterpret_cast<uint16_t*>(to); - uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); - uint16_t* _to_nxt = _to; - result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8<char16_t>::result -__codecvt_utf8<char16_t>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf8<char16_t>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf8<char16_t>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf8<char16_t>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -} - -int -__codecvt_utf8<char16_t>::do_max_length() const noexcept -{ - if (_Mode_ & consume_header) - return 6; - return 3; -} - -// __codecvt_utf8<char32_t> - -__codecvt_utf8<char32_t>::result -__codecvt_utf8<char32_t>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); - const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); - const uint32_t* _frm_nxt = _frm; - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8<char32_t>::result -__codecvt_utf8<char32_t>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; - uint32_t* _to = reinterpret_cast<uint32_t*>(to); - uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); - uint32_t* _to_nxt = _to; - result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8<char32_t>::result -__codecvt_utf8<char32_t>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf8<char32_t>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf8<char32_t>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf8<char32_t>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -} - -int -__codecvt_utf8<char32_t>::do_max_length() const noexcept -{ - if (_Mode_ & consume_header) - return 7; - return 4; -} - -// __codecvt_utf16<wchar_t, false> - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -__codecvt_utf16<wchar_t, false>::result -__codecvt_utf16<wchar_t, false>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ -#if defined(_LIBCPP_SHORT_WCHAR) - const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); - const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); - const uint16_t* _frm_nxt = _frm; -#else - const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); - const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); - const uint32_t* _frm_nxt = _frm; -#endif - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; -#if defined(_LIBCPP_SHORT_WCHAR) - result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#else - result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#endif - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<wchar_t, false>::result -__codecvt_utf16<wchar_t, false>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; -#if defined(_LIBCPP_SHORT_WCHAR) - uint16_t* _to = reinterpret_cast<uint16_t*>(to); - uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); - uint16_t* _to_nxt = _to; - result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#else - uint32_t* _to = reinterpret_cast<uint32_t*>(to); - uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); - uint32_t* _to_nxt = _to; - result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#endif - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<wchar_t, false>::result -__codecvt_utf16<wchar_t, false>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf16<wchar_t, false>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); -#if defined(_LIBCPP_SHORT_WCHAR) - return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -#else - return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -#endif -} - -int -__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept -{ -#if defined(_LIBCPP_SHORT_WCHAR) - if (_Mode_ & consume_header) - return 4; - return 2; -#else - if (_Mode_ & consume_header) - return 6; - return 4; -#endif -} - -// __codecvt_utf16<wchar_t, true> - -__codecvt_utf16<wchar_t, true>::result -__codecvt_utf16<wchar_t, true>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ -#if defined(_LIBCPP_SHORT_WCHAR) - const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); - const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); - const uint16_t* _frm_nxt = _frm; -#else - const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); - const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); - const uint32_t* _frm_nxt = _frm; -#endif - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; -#if defined(_LIBCPP_SHORT_WCHAR) - result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#else - result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#endif - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<wchar_t, true>::result -__codecvt_utf16<wchar_t, true>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; -#if defined(_LIBCPP_SHORT_WCHAR) - uint16_t* _to = reinterpret_cast<uint16_t*>(to); - uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); - uint16_t* _to_nxt = _to; - result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#else - uint32_t* _to = reinterpret_cast<uint32_t*>(to); - uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); - uint32_t* _to_nxt = _to; - result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#endif - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<wchar_t, true>::result -__codecvt_utf16<wchar_t, true>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf16<wchar_t, true>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); -#if defined(_LIBCPP_SHORT_WCHAR) - return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -#else - return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -#endif -} - -int -__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept -{ -#if defined(_LIBCPP_SHORT_WCHAR) - if (_Mode_ & consume_header) - return 4; - return 2; -#else - if (_Mode_ & consume_header) - return 6; - return 4; -#endif -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -// __codecvt_utf16<char16_t, false> - -__codecvt_utf16<char16_t, false>::result -__codecvt_utf16<char16_t, false>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); - const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); - const uint16_t* _frm_nxt = _frm; - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<char16_t, false>::result -__codecvt_utf16<char16_t, false>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; - uint16_t* _to = reinterpret_cast<uint16_t*>(to); - uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); - uint16_t* _to_nxt = _to; - result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<char16_t, false>::result -__codecvt_utf16<char16_t, false>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf16<char16_t, false>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf16<char16_t, false>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -} - -int -__codecvt_utf16<char16_t, false>::do_max_length() const noexcept -{ - if (_Mode_ & consume_header) - return 4; - return 2; -} - -// __codecvt_utf16<char16_t, true> - -__codecvt_utf16<char16_t, true>::result -__codecvt_utf16<char16_t, true>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); - const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); - const uint16_t* _frm_nxt = _frm; - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<char16_t, true>::result -__codecvt_utf16<char16_t, true>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; - uint16_t* _to = reinterpret_cast<uint16_t*>(to); - uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); - uint16_t* _to_nxt = _to; - result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<char16_t, true>::result -__codecvt_utf16<char16_t, true>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf16<char16_t, true>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf16<char16_t, true>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -} - -int -__codecvt_utf16<char16_t, true>::do_max_length() const noexcept -{ - if (_Mode_ & consume_header) - return 4; - return 2; -} - -// __codecvt_utf16<char32_t, false> - -__codecvt_utf16<char32_t, false>::result -__codecvt_utf16<char32_t, false>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); - const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); - const uint32_t* _frm_nxt = _frm; - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<char32_t, false>::result -__codecvt_utf16<char32_t, false>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; - uint32_t* _to = reinterpret_cast<uint32_t*>(to); - uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); - uint32_t* _to_nxt = _to; - result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<char32_t, false>::result -__codecvt_utf16<char32_t, false>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf16<char32_t, false>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf16<char32_t, false>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -} - -int -__codecvt_utf16<char32_t, false>::do_max_length() const noexcept -{ - if (_Mode_ & consume_header) - return 6; - return 4; -} - -// __codecvt_utf16<char32_t, true> - -__codecvt_utf16<char32_t, true>::result -__codecvt_utf16<char32_t, true>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ -#if defined(_LIBCPP_SHORT_WCHAR) - const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); - const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); - const uint16_t* _frm_nxt = _frm; -#else - const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); - const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); - const uint32_t* _frm_nxt = _frm; -#endif - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; -#if defined(_LIBCPP_SHORT_WCHAR) - result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#else - result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); -#endif - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<char32_t, true>::result -__codecvt_utf16<char32_t, true>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; - uint32_t* _to = reinterpret_cast<uint32_t*>(to); - uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); - uint32_t* _to_nxt = _to; - result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf16<char32_t, true>::result -__codecvt_utf16<char32_t, true>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf16<char32_t, true>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf16<char32_t, true>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -} - -int -__codecvt_utf16<char32_t, true>::do_max_length() const noexcept -{ - if (_Mode_ & consume_header) - return 6; - return 4; -} - -// __codecvt_utf8_utf16<wchar_t> - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -__codecvt_utf8_utf16<wchar_t>::result -__codecvt_utf8_utf16<wchar_t>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ -#ifdef _WIN32 - const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); - const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); - const uint16_t* _frm_nxt = _frm; -#else - const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); - const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); - const uint32_t* _frm_nxt = _frm; -#endif - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8_utf16<wchar_t>::result -__codecvt_utf8_utf16<wchar_t>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; -#ifdef _WIN32 - uint16_t* _to = reinterpret_cast<uint16_t*>(to); - uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); - uint16_t* _to_nxt = _to; -#else - uint32_t* _to = reinterpret_cast<uint32_t*>(to); - uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); - uint32_t* _to_nxt = _to; -#endif - result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8_utf16<wchar_t>::result -__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf8_utf16<wchar_t>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -} - -int -__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept -{ - if (_Mode_ & consume_header) - return 7; - return 4; -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -// __codecvt_utf8_utf16<char16_t> - -__codecvt_utf8_utf16<char16_t>::result -__codecvt_utf8_utf16<char16_t>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); - const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); - const uint16_t* _frm_nxt = _frm; - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8_utf16<char16_t>::result -__codecvt_utf8_utf16<char16_t>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; - uint16_t* _to = reinterpret_cast<uint16_t*>(to); - uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); - uint16_t* _to_nxt = _to; - result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8_utf16<char16_t>::result -__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf8_utf16<char16_t>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -} - -int -__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept -{ - if (_Mode_ & consume_header) - return 7; - return 4; -} - -// __codecvt_utf8_utf16<char32_t> - -__codecvt_utf8_utf16<char32_t>::result -__codecvt_utf8_utf16<char32_t>::do_out(state_type&, - const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, - extern_type* to, extern_type* to_end, extern_type*& to_nxt) const -{ - const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); - const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); - const uint32_t* _frm_nxt = _frm; - uint8_t* _to = reinterpret_cast<uint8_t*>(to); - uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); - uint8_t* _to_nxt = _to; - result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8_utf16<char32_t>::result -__codecvt_utf8_utf16<char32_t>::do_in(state_type&, - const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, - intern_type* to, intern_type* to_end, intern_type*& to_nxt) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - const uint8_t* _frm_nxt = _frm; -#if defined(_LIBCPP_SHORT_WCHAR) - uint16_t* _to = reinterpret_cast<uint16_t*>(to); - uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); - uint16_t* _to_nxt = _to; -#else - uint32_t* _to = reinterpret_cast<uint32_t*>(to); - uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); - uint32_t* _to_nxt = _to; -#endif - result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, - _Maxcode_, _Mode_); - frm_nxt = frm + (_frm_nxt - _frm); - to_nxt = to + (_to_nxt - _to); - return r; -} - -__codecvt_utf8_utf16<char32_t>::result -__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&, - extern_type* to, extern_type*, extern_type*& to_nxt) const -{ - to_nxt = to; - return noconv; -} - -int -__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept -{ - return 0; -} - -bool -__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept -{ - return false; -} - -int -__codecvt_utf8_utf16<char32_t>::do_length(state_type&, - const extern_type* frm, const extern_type* frm_end, size_t mx) const -{ - const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); - const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); - return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); -} - -int -__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept -{ - if (_Mode_ & consume_header) - return 7; - return 4; -} - -// __narrow_to_utf8<16> - -__narrow_to_utf8<16>::~__narrow_to_utf8() -{ -} - -// __narrow_to_utf8<32> - -__narrow_to_utf8<32>::~__narrow_to_utf8() -{ -} - -// __widen_from_utf8<16> - -__widen_from_utf8<16>::~__widen_from_utf8() -{ -} - -// __widen_from_utf8<32> - -__widen_from_utf8<32>::~__widen_from_utf8() -{ -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -static bool checked_string_to_wchar_convert(wchar_t& dest, - const char* ptr, - locale_t loc) { - if (*ptr == '\0') - return false; - mbstate_t mb = {}; - wchar_t out; - size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc); - if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) { - return false; - } - dest = out; - return true; -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -static bool checked_string_to_char_convert(char& dest, - const char* ptr, - locale_t __loc) { - if (*ptr == '\0') - return false; - if (!ptr[1]) { - dest = *ptr; - return true; - } - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - // First convert the MBS into a wide char then attempt to narrow it using - // wctob_l. - wchar_t wout; - if (!checked_string_to_wchar_convert(wout, ptr, __loc)) - return false; - int res; - if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) { - dest = res; - return true; - } - // FIXME: Work around specific multibyte sequences that we can reasonably - // translate into a different single byte. - switch (wout) { - case L'\u202F': // narrow non-breaking space - case L'\u00A0': // non-breaking space - dest = ' '; - return true; - default: - return false; - } -#else // _LIBCPP_HAS_NO_WIDE_CHARACTERS - return false; -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - _LIBCPP_UNREACHABLE(); -} - - -// numpunct<char> && numpunct<wchar_t> - -locale::id numpunct< char >::id; -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -locale::id numpunct<wchar_t>::id; -#endif - -numpunct<char>::numpunct(size_t refs) - : locale::facet(refs), - __decimal_point_('.'), - __thousands_sep_(',') -{ -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -numpunct<wchar_t>::numpunct(size_t refs) - : locale::facet(refs), - __decimal_point_(L'.'), - __thousands_sep_(L',') -{ -} -#endif - -numpunct<char>::~numpunct() -{ -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -numpunct<wchar_t>::~numpunct() -{ -} -#endif - - char numpunct< char >::do_decimal_point() const {return __decimal_point_;} -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;} -#endif - - char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;} -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;} -#endif - -string numpunct< char >::do_grouping() const {return __grouping_;} -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -string numpunct<wchar_t>::do_grouping() const {return __grouping_;} -#endif - - string numpunct< char >::do_truename() const {return "true";} -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -wstring numpunct<wchar_t>::do_truename() const {return L"true";} -#endif - - string numpunct< char >::do_falsename() const {return "false";} -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -wstring numpunct<wchar_t>::do_falsename() const {return L"false";} -#endif - -// numpunct_byname<char> - -numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs) - : numpunct<char>(refs) -{ - __init(nm); -} - -numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs) - : numpunct<char>(refs) -{ - __init(nm.c_str()); -} - -numpunct_byname<char>::~numpunct_byname() -{ -} - -void -numpunct_byname<char>::__init(const char* nm) -{ - typedef numpunct<char> base; - if (strcmp(nm, "C") != 0) - { - __libcpp_unique_locale loc(nm); - if (!loc) - __throw_runtime_error("numpunct_byname<char>::numpunct_byname" - " failed to construct for " + string(nm)); - - lconv* lc = __libcpp_localeconv_l(loc.get()); - if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point, - loc.get())) - __decimal_point_ = base::do_decimal_point(); - if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep, - loc.get())) - __thousands_sep_ = base::do_thousands_sep(); - __grouping_ = lc->grouping; - // localization for truename and falsename is not available - } -} - -// numpunct_byname<wchar_t> - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs) - : numpunct<wchar_t>(refs) -{ - __init(nm); -} - -numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs) - : numpunct<wchar_t>(refs) -{ - __init(nm.c_str()); -} - -numpunct_byname<wchar_t>::~numpunct_byname() -{ -} - -void -numpunct_byname<wchar_t>::__init(const char* nm) -{ - if (strcmp(nm, "C") != 0) - { - __libcpp_unique_locale loc(nm); - if (!loc) - __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname" - " failed to construct for " + string(nm)); - - lconv* lc = __libcpp_localeconv_l(loc.get()); - checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point, - loc.get()); - checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep, - loc.get()); - __grouping_ = lc->grouping; - // localization for truename and falsename is not available - } -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -// num_get helpers - -int -__num_get_base::__get_base(ios_base& iob) -{ - ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield; - if (__basefield == ios_base::oct) - return 8; - else if (__basefield == ios_base::hex) - return 16; - else if (__basefield == 0) - return 0; - return 10; -} - -const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN"; - -void -__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, - ios_base::iostate& __err) -{ -// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing -// we always have at least a single entry in [__g, __g_end); the end of the input sequence +// +//===----------------------------------------------------------------------===// + +// On Solaris, we need to define something to make the C99 parts of localeconv +// visible. +#ifdef __sun__ +#define _LCONV_C99 +#endif + +#include "clocale" +#include "codecvt" +#include "cstdio" +#include "cstdlib" +#include "cstring" +#include "locale" +#include "string" +#include "type_traits" +#include "typeinfo" +#include "vector" + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# include "cwctype" +#endif + +#if defined(_AIX) +# include <sys/localedef.h> // for __lc_ctype_ptr +#endif + +#if defined(_LIBCPP_MSVCRT) +# define _CTYPE_DISABLE_MACROS +#endif +#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) +# include "__support/win32/locale_win32.h" +#elif !defined(__BIONIC__) && !defined(__NuttX__) +# include <langinfo.h> +#endif + +#include "atomic" +#include "include/sso_allocator.h" +#include "__undef_macros" + +// On Linux, wint_t and wchar_t have different signed-ness, and this causes +// lots of noise in the build log, but no bugs that I know of. +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wsign-conversion" +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +struct __libcpp_unique_locale { + __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {} + + ~__libcpp_unique_locale() { + if (__loc_) + freelocale(__loc_); + } + + explicit operator bool() const { return __loc_; } + + locale_t& get() { return __loc_; } + + locale_t __loc_; +private: + __libcpp_unique_locale(__libcpp_unique_locale const&); + __libcpp_unique_locale& operator=(__libcpp_unique_locale const&); +}; + +#ifdef __cloc_defined +locale_t __cloc() { + // In theory this could create a race condition. In practice + // the race condition is non-fatal since it will just create + // a little resource leak. Better approach would be appreciated. + static locale_t result = newlocale(LC_ALL_MASK, "C", 0); + return result; +} +#endif // __cloc_defined + +namespace { + +struct release +{ + void operator()(locale::facet* p) {p->__release_shared();} +}; + +template <class T, class ...Args> +T& make(Args ...args) +{ + static typename aligned_storage<sizeof(T)>::type buf; + auto *obj = ::new (&buf) T(args...); + return *obj; +} + +template <typename T, size_t N> +inline +_LIBCPP_CONSTEXPR +size_t +countof(const T (&)[N]) +{ + return N; +} + +template <typename T> +inline +_LIBCPP_CONSTEXPR +size_t +countof(const T * const begin, const T * const end) +{ + return static_cast<size_t>(end - begin); +} + +_LIBCPP_NORETURN static void __throw_runtime_error(const string &msg) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw runtime_error(msg); +#else + (void)msg; + _VSTD::abort(); +#endif +} + +} + +#if defined(_AIX) +// Set priority to INT_MIN + 256 + 150 +# pragma priority ( -2147483242 ) +#endif + +const locale::category locale::none; +const locale::category locale::collate; +const locale::category locale::ctype; +const locale::category locale::monetary; +const locale::category locale::numeric; +const locale::category locale::time; +const locale::category locale::messages; +const locale::category locale::all; + +class _LIBCPP_HIDDEN locale::__imp + : public facet +{ + enum {N = 30}; + vector<facet*, __sso_allocator<facet*, N> > facets_; + string name_; +public: + explicit __imp(size_t refs = 0); + explicit __imp(const string& name, size_t refs = 0); + __imp(const __imp&); + __imp(const __imp&, const string&, locale::category c); + __imp(const __imp& other, const __imp& one, locale::category c); + __imp(const __imp&, facet* f, long id); + ~__imp(); + + const string& name() const {return name_;} + bool has_facet(long id) const + {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];} + const locale::facet* use_facet(long id) const; + + static const locale& make_classic(); + static locale& make_global(); +private: + void install(facet* f, long id); + template <class F> void install(F* f) {install(f, f->id.__get());} + template <class F> void install_from(const __imp& other); +}; + +locale::__imp::__imp(size_t refs) + : facet(refs), + facets_(N), + name_("C") +{ + facets_.clear(); + install(&make<_VSTD::collate<char> >(1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<_VSTD::collate<wchar_t> >(1u)); +#endif + install(&make<_VSTD::ctype<char> >(nullptr, false, 1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<_VSTD::ctype<wchar_t> >(1u)); +#endif + install(&make<codecvt<char, char, mbstate_t> >(1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<codecvt<wchar_t, char, mbstate_t> >(1u)); +#endif +_LIBCPP_SUPPRESS_DEPRECATED_PUSH + install(&make<codecvt<char16_t, char, mbstate_t> >(1u)); + install(&make<codecvt<char32_t, char, mbstate_t> >(1u)); +_LIBCPP_SUPPRESS_DEPRECATED_POP +#ifndef _LIBCPP_HAS_NO_CHAR8_T + install(&make<codecvt<char16_t, char8_t, mbstate_t> >(1u)); + install(&make<codecvt<char32_t, char8_t, mbstate_t> >(1u)); +#endif + install(&make<numpunct<char> >(1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<numpunct<wchar_t> >(1u)); +#endif + install(&make<num_get<char> >(1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<num_get<wchar_t> >(1u)); +#endif + install(&make<num_put<char> >(1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<num_put<wchar_t> >(1u)); +#endif + install(&make<moneypunct<char, false> >(1u)); + install(&make<moneypunct<char, true> >(1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<moneypunct<wchar_t, false> >(1u)); + install(&make<moneypunct<wchar_t, true> >(1u)); +#endif + install(&make<money_get<char> >(1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<money_get<wchar_t> >(1u)); +#endif + install(&make<money_put<char> >(1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<money_put<wchar_t> >(1u)); +#endif + install(&make<time_get<char> >(1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<time_get<wchar_t> >(1u)); +#endif + install(&make<time_put<char> >(1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<time_put<wchar_t> >(1u)); +#endif + install(&make<_VSTD::messages<char> >(1u)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(&make<_VSTD::messages<wchar_t> >(1u)); +#endif +} + +locale::__imp::__imp(const string& name, size_t refs) + : facet(refs), + facets_(N), + name_(name) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + facets_ = locale::classic().__locale_->facets_; + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__add_shared(); + install(new collate_byname<char>(name_)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new collate_byname<wchar_t>(name_)); +#endif + install(new ctype_byname<char>(name_)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new ctype_byname<wchar_t>(name_)); +#endif + install(new codecvt_byname<char, char, mbstate_t>(name_)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new codecvt_byname<wchar_t, char, mbstate_t>(name_)); +#endif +_LIBCPP_SUPPRESS_DEPRECATED_PUSH + install(new codecvt_byname<char16_t, char, mbstate_t>(name_)); + install(new codecvt_byname<char32_t, char, mbstate_t>(name_)); +_LIBCPP_SUPPRESS_DEPRECATED_POP +#ifndef _LIBCPP_HAS_NO_CHAR8_T + install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name_)); + install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name_)); +#endif + install(new numpunct_byname<char>(name_)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new numpunct_byname<wchar_t>(name_)); +#endif + install(new moneypunct_byname<char, false>(name_)); + install(new moneypunct_byname<char, true>(name_)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new moneypunct_byname<wchar_t, false>(name_)); + install(new moneypunct_byname<wchar_t, true>(name_)); +#endif + install(new time_get_byname<char>(name_)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new time_get_byname<wchar_t>(name_)); +#endif + install(new time_put_byname<char>(name_)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new time_put_byname<wchar_t>(name_)); +#endif + install(new messages_byname<char>(name_)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new messages_byname<wchar_t>(name_)); +#endif +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__release_shared(); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +locale::__imp::__imp(const __imp& other) + : facets_(max<size_t>(N, other.facets_.size())), + name_(other.name_) +{ + facets_ = other.facets_; + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__add_shared(); +} + +locale::__imp::__imp(const __imp& other, const string& name, locale::category c) + : facets_(N), + name_("*") +{ + facets_ = other.facets_; + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__add_shared(); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + if (c & locale::collate) + { + install(new collate_byname<char>(name)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new collate_byname<wchar_t>(name)); +#endif + } + if (c & locale::ctype) + { + install(new ctype_byname<char>(name)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new ctype_byname<wchar_t>(name)); +#endif + install(new codecvt_byname<char, char, mbstate_t>(name)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new codecvt_byname<wchar_t, char, mbstate_t>(name)); +#endif +_LIBCPP_SUPPRESS_DEPRECATED_PUSH + install(new codecvt_byname<char16_t, char, mbstate_t>(name)); + install(new codecvt_byname<char32_t, char, mbstate_t>(name)); +_LIBCPP_SUPPRESS_DEPRECATED_POP +#ifndef _LIBCPP_HAS_NO_CHAR8_T + install(new codecvt_byname<char16_t, char8_t, mbstate_t>(name)); + install(new codecvt_byname<char32_t, char8_t, mbstate_t>(name)); +#endif + } + if (c & locale::monetary) + { + install(new moneypunct_byname<char, false>(name)); + install(new moneypunct_byname<char, true>(name)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new moneypunct_byname<wchar_t, false>(name)); + install(new moneypunct_byname<wchar_t, true>(name)); +#endif + } + if (c & locale::numeric) + { + install(new numpunct_byname<char>(name)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new numpunct_byname<wchar_t>(name)); +#endif + } + if (c & locale::time) + { + install(new time_get_byname<char>(name)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new time_get_byname<wchar_t>(name)); +#endif + install(new time_put_byname<char>(name)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new time_put_byname<wchar_t>(name)); +#endif + } + if (c & locale::messages) + { + install(new messages_byname<char>(name)); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install(new messages_byname<wchar_t>(name)); +#endif + } +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__release_shared(); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +template<class F> +inline +void +locale::__imp::install_from(const locale::__imp& one) +{ + long id = F::id.__get(); + install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id); +} + +locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c) + : facets_(N), + name_("*") +{ + facets_ = other.facets_; + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__add_shared(); +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + if (c & locale::collate) + { + install_from<_VSTD::collate<char> >(one); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<_VSTD::collate<wchar_t> >(one); +#endif + } + if (c & locale::ctype) + { + install_from<_VSTD::ctype<char> >(one); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<_VSTD::ctype<wchar_t> >(one); +#endif + install_from<_VSTD::codecvt<char, char, mbstate_t> >(one); +_LIBCPP_SUPPRESS_DEPRECATED_PUSH + install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one); + install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one); +_LIBCPP_SUPPRESS_DEPRECATED_POP +#ifndef _LIBCPP_HAS_NO_CHAR8_T + install_from<_VSTD::codecvt<char16_t, char8_t, mbstate_t> >(one); + install_from<_VSTD::codecvt<char32_t, char8_t, mbstate_t> >(one); +#endif +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<_VSTD::codecvt<wchar_t, char, mbstate_t> >(one); +#endif + } + if (c & locale::monetary) + { + install_from<moneypunct<char, false> >(one); + install_from<moneypunct<char, true> >(one); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<moneypunct<wchar_t, false> >(one); + install_from<moneypunct<wchar_t, true> >(one); +#endif + install_from<money_get<char> >(one); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<money_get<wchar_t> >(one); +#endif + install_from<money_put<char> >(one); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<money_put<wchar_t> >(one); +#endif + } + if (c & locale::numeric) + { + install_from<numpunct<char> >(one); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<numpunct<wchar_t> >(one); +#endif + install_from<num_get<char> >(one); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<num_get<wchar_t> >(one); +#endif + install_from<num_put<char> >(one); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<num_put<wchar_t> >(one); +#endif + } + if (c & locale::time) + { + install_from<time_get<char> >(one); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<time_get<wchar_t> >(one); +#endif + install_from<time_put<char> >(one); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<time_put<wchar_t> >(one); +#endif + } + if (c & locale::messages) + { + install_from<_VSTD::messages<char> >(one); +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + install_from<_VSTD::messages<wchar_t> >(one); +#endif + } +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__release_shared(); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +locale::__imp::__imp(const __imp& other, facet* f, long id) + : facets_(max<size_t>(N, other.facets_.size()+1)), + name_("*") +{ + f->__add_shared(); + unique_ptr<facet, release> hold(f); + facets_ = other.facets_; + for (unsigned i = 0; i < other.facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__add_shared(); + install(hold.get(), id); +} + +locale::__imp::~__imp() +{ + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__release_shared(); +} + +void +locale::__imp::install(facet* f, long id) +{ + f->__add_shared(); + unique_ptr<facet, release> hold(f); + if (static_cast<size_t>(id) >= facets_.size()) + facets_.resize(static_cast<size_t>(id+1)); + if (facets_[static_cast<size_t>(id)]) + facets_[static_cast<size_t>(id)]->__release_shared(); + facets_[static_cast<size_t>(id)] = hold.release(); +} + +const locale::facet* +locale::__imp::use_facet(long id) const +{ + if (!has_facet(id)) + __throw_bad_cast(); + return facets_[static_cast<size_t>(id)]; +} + +// locale + +const locale& +locale::__imp::make_classic() +{ + // only one thread can get in here and it only gets in once + static aligned_storage<sizeof(locale)>::type buf; + locale* c = reinterpret_cast<locale*>(&buf); + c->__locale_ = &make<__imp>(1u); + return *c; +} + +const locale& +locale::classic() +{ + static const locale& c = __imp::make_classic(); + return c; +} + +locale& +locale::__imp::make_global() +{ + // only one thread can get in here and it only gets in once + static aligned_storage<sizeof(locale)>::type buf; + auto *obj = ::new (&buf) locale(locale::classic()); + return *obj; +} + +locale& +locale::__global() +{ + static locale& g = __imp::make_global(); + return g; +} + +locale::locale() noexcept + : __locale_(__global().__locale_) +{ + __locale_->__add_shared(); +} + +locale::locale(const locale& l) noexcept + : __locale_(l.__locale_) +{ + __locale_->__add_shared(); +} + +locale::~locale() +{ + __locale_->__release_shared(); +} + +const locale& +locale::operator=(const locale& other) noexcept +{ + other.__locale_->__add_shared(); + __locale_->__release_shared(); + __locale_ = other.__locale_; + return *this; +} + +locale::locale(const char* name) + : __locale_(name ? new __imp(name) + : (__throw_runtime_error("locale constructed with null"), nullptr)) +{ + __locale_->__add_shared(); +} + +locale::locale(const string& name) + : __locale_(new __imp(name)) +{ + __locale_->__add_shared(); +} + +locale::locale(const locale& other, const char* name, category c) + : __locale_(name ? new __imp(*other.__locale_, name, c) + : (__throw_runtime_error("locale constructed with null"), nullptr)) +{ + __locale_->__add_shared(); +} + +locale::locale(const locale& other, const string& name, category c) + : __locale_(new __imp(*other.__locale_, name, c)) +{ + __locale_->__add_shared(); +} + +locale::locale(const locale& other, const locale& one, category c) + : __locale_(new __imp(*other.__locale_, *one.__locale_, c)) +{ + __locale_->__add_shared(); +} + +string +locale::name() const +{ + return __locale_->name(); +} + +void +locale::__install_ctor(const locale& other, facet* f, long id) +{ + if (f) + __locale_ = new __imp(*other.__locale_, f, id); + else + __locale_ = other.__locale_; + __locale_->__add_shared(); +} + +locale +locale::global(const locale& loc) +{ + locale& g = __global(); + locale r = g; + g = loc; + if (g.name() != "*") + setlocale(LC_ALL, g.name().c_str()); + return r; +} + +bool +locale::has_facet(id& x) const +{ + return __locale_->has_facet(x.__get()); +} + +const locale::facet* +locale::use_facet(id& x) const +{ + return __locale_->use_facet(x.__get()); +} + +bool +locale::operator==(const locale& y) const +{ + return (__locale_ == y.__locale_) + || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name()); +} + +// locale::facet + +locale::facet::~facet() +{ +} + +void +locale::facet::__on_zero_shared() noexcept +{ + delete this; +} + +// locale::id + +namespace +{ + +class __fake_bind +{ + locale::id* id_; + void (locale::id::* pmf_)(); +public: + __fake_bind(void (locale::id::* pmf)(), locale::id* id) + : id_(id), pmf_(pmf) {} + + void operator()() const + { + (id_->*pmf_)(); + } +}; + +} + +int32_t locale::id::__next_id; + +long +locale::id::__get() +{ + int32_t result = __id_.load(std::memory_order_acquire); + if (result == 0) { + static std::mutex m; + std::lock_guard<std::mutex> guard(m); + result = __id_.load(std::memory_order_acquire); + if (result == 0) { + result = ++__next_id; + __id_.store(result, std::memory_order_release); + } + } + return result - 1; +} + +// template <> class collate_byname<char> + +collate_byname<char>::collate_byname(const char* n, size_t refs) + : collate<char>(refs), + __l(newlocale(LC_ALL_MASK, n, 0)) +{ + if (__l == 0) + __throw_runtime_error("collate_byname<char>::collate_byname" + " failed to construct for " + string(n)); +} + +collate_byname<char>::collate_byname(const string& name, size_t refs) + : collate<char>(refs), + __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) +{ + if (__l == 0) + __throw_runtime_error("collate_byname<char>::collate_byname" + " failed to construct for " + name); +} + +collate_byname<char>::~collate_byname() +{ + freelocale(__l); +} + +int +collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1, + const char_type* __lo2, const char_type* __hi2) const +{ + string_type lhs(__lo1, __hi1); + string_type rhs(__lo2, __hi2); + int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l); + if (r < 0) + return -1; + if (r > 0) + return 1; + return r; +} + +collate_byname<char>::string_type +collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const +{ + const string_type in(lo, hi); + string_type out(strxfrm_l(0, in.c_str(), 0, __l), char()); + strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l); + return out; +} + +// template <> class collate_byname<wchar_t> + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +collate_byname<wchar_t>::collate_byname(const char* n, size_t refs) + : collate<wchar_t>(refs), + __l(newlocale(LC_ALL_MASK, n, 0)) +{ + if (__l == 0) + __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" + " failed to construct for " + string(n)); +} + +collate_byname<wchar_t>::collate_byname(const string& name, size_t refs) + : collate<wchar_t>(refs), + __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) +{ + if (__l == 0) + __throw_runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" + " failed to construct for " + name); +} + +collate_byname<wchar_t>::~collate_byname() +{ + freelocale(__l); +} + +int +collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1, + const char_type* __lo2, const char_type* __hi2) const +{ + string_type lhs(__lo1, __hi1); + string_type rhs(__lo2, __hi2); + int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l); + if (r < 0) + return -1; + if (r > 0) + return 1; + return r; +} + +collate_byname<wchar_t>::string_type +collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const +{ + const string_type in(lo, hi); + string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t()); + wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l); + return out; +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +const ctype_base::mask ctype_base::space; +const ctype_base::mask ctype_base::print; +const ctype_base::mask ctype_base::cntrl; +const ctype_base::mask ctype_base::upper; +const ctype_base::mask ctype_base::lower; +const ctype_base::mask ctype_base::alpha; +const ctype_base::mask ctype_base::digit; +const ctype_base::mask ctype_base::punct; +const ctype_base::mask ctype_base::xdigit; +const ctype_base::mask ctype_base::blank; +const ctype_base::mask ctype_base::alnum; +const ctype_base::mask ctype_base::graph; + +// template <> class ctype<wchar_t>; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +locale::id ctype<wchar_t>::id; + +ctype<wchar_t>::~ctype() +{ +} + +bool +ctype<wchar_t>::do_is(mask m, char_type c) const +{ + return isascii(c) ? (ctype<char>::classic_table()[c] & m) != 0 : false; +} + +const wchar_t* +ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const +{ + for (; low != high; ++low, ++vec) + *vec = static_cast<mask>(isascii(*low) ? + ctype<char>::classic_table()[*low] : 0); + return low; +} + +const wchar_t* +ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + if (isascii(*low) && (ctype<char>::classic_table()[*low] & m)) + break; + return low; +} + +const wchar_t* +ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m))) + break; + return low; +} + +wchar_t +ctype<wchar_t>::do_toupper(char_type c) const +{ +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE + return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c; +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ + defined(__NetBSD__) + return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c; +#else + return (isascii(c) && iswlower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'a'+L'A' : c; +#endif +} + +const wchar_t* +ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE + *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low; +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ + defined(__NetBSD__) + *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low] + : *low; +#else + *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? (*low-L'a'+L'A') : *low; +#endif + return low; +} + +wchar_t +ctype<wchar_t>::do_tolower(char_type c) const +{ +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE + return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c; +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ + defined(__NetBSD__) + return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c; +#else + return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-L'A'+'a' : c; +#endif +} + +const wchar_t* +ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE + *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low; +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) || \ + defined(__NetBSD__) + *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low] + : *low; +#else + *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-L'A'+L'a' : *low; +#endif + return low; +} + +wchar_t +ctype<wchar_t>::do_widen(char c) const +{ + return c; +} + +const char* +ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const +{ + for (; low != high; ++low, ++dest) + *dest = *low; + return low; +} + +char +ctype<wchar_t>::do_narrow(char_type c, char dfault) const +{ + if (isascii(c)) + return static_cast<char>(c); + return dfault; +} + +const wchar_t* +ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const +{ + for (; low != high; ++low, ++dest) + if (isascii(*low)) + *dest = static_cast<char>(*low); + else + *dest = dfault; + return low; +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// template <> class ctype<char>; + +locale::id ctype<char>::id; + +ctype<char>::ctype(const mask* tab, bool del, size_t refs) + : locale::facet(refs), + __tab_(tab), + __del_(del) +{ + if (__tab_ == 0) + __tab_ = classic_table(); +} + +ctype<char>::~ctype() +{ + if (__tab_ && __del_) + delete [] __tab_; +} + +char +ctype<char>::do_toupper(char_type c) const +{ +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE + return isascii(c) ? + static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c; +#elif defined(__NetBSD__) + return static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]); +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) + return isascii(c) ? + static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(c)]) : c; +#else + return (isascii(c) && islower_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'a'+'A' : c; +#endif +} + +const char* +ctype<char>::do_toupper(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE + *low = isascii(*low) ? + static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low; +#elif defined(__NetBSD__) + *low = static_cast<char>(__classic_upper_table()[static_cast<unsigned char>(*low)]); +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) + *low = isascii(*low) ? + static_cast<char>(__classic_upper_table()[static_cast<size_t>(*low)]) : *low; +#else + *low = (isascii(*low) && islower_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'a'+'A' : *low; +#endif + return low; +} + +char +ctype<char>::do_tolower(char_type c) const +{ +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE + return isascii(c) ? + static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c; +#elif defined(__NetBSD__) + return static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(c)]); +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) + return isascii(c) ? + static_cast<char>(__classic_lower_table()[static_cast<size_t>(c)]) : c; +#else + return (isascii(c) && isupper_l(c, _LIBCPP_GET_C_LOCALE)) ? c-'A'+'a' : c; +#endif +} + +const char* +ctype<char>::do_tolower(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE + *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low; +#elif defined(__NetBSD__) + *low = static_cast<char>(__classic_lower_table()[static_cast<unsigned char>(*low)]); +#elif defined(__GLIBC__) || defined(__EMSCRIPTEN__) + *low = isascii(*low) ? static_cast<char>(__classic_lower_table()[static_cast<size_t>(*low)]) : *low; +#else + *low = (isascii(*low) && isupper_l(*low, _LIBCPP_GET_C_LOCALE)) ? *low-'A'+'a' : *low; +#endif + return low; +} + +char +ctype<char>::do_widen(char c) const +{ + return c; +} + +const char* +ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const +{ + for (; low != high; ++low, ++dest) + *dest = *low; + return low; +} + +char +ctype<char>::do_narrow(char_type c, char dfault) const +{ + if (isascii(c)) + return static_cast<char>(c); + return dfault; +} + +const char* +ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const +{ + for (; low != high; ++low, ++dest) + if (isascii(*low)) + *dest = *low; + else + *dest = dfault; + return low; +} + +#if defined(__EMSCRIPTEN__) +extern "C" const unsigned short ** __ctype_b_loc(); +extern "C" const int ** __ctype_tolower_loc(); +extern "C" const int ** __ctype_toupper_loc(); +#endif + +#if defined(__ANDROID__) +// See src/support/android/android_locale.cpp +extern "C" const unsigned short* const _ctype_android; +#endif + +#ifdef _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE +const ctype<char>::mask* +ctype<char>::classic_table() noexcept +{ + static _LIBCPP_CONSTEXPR const ctype<char>::mask builtin_table[table_size] = { + cntrl, cntrl, + cntrl, cntrl, + cntrl, cntrl, + cntrl, cntrl, + cntrl, cntrl | space | blank, + cntrl | space, cntrl | space, + cntrl | space, cntrl | space, + cntrl, cntrl, + cntrl, cntrl, + cntrl, cntrl, + cntrl, cntrl, + cntrl, cntrl, + cntrl, cntrl, + cntrl, cntrl, + cntrl, cntrl, + cntrl, cntrl, + space | blank | print, punct | print, + punct | print, punct | print, + punct | print, punct | print, + punct | print, punct | print, + punct | print, punct | print, + punct | print, punct | print, + punct | print, punct | print, + punct | print, punct | print, + digit | print | xdigit, digit | print | xdigit, + digit | print | xdigit, digit | print | xdigit, + digit | print | xdigit, digit | print | xdigit, + digit | print | xdigit, digit | print | xdigit, + digit | print | xdigit, digit | print | xdigit, + punct | print, punct | print, + punct | print, punct | print, + punct | print, punct | print, + punct | print, upper | xdigit | print | alpha, + upper | xdigit | print | alpha, upper | xdigit | print | alpha, + upper | xdigit | print | alpha, upper | xdigit | print | alpha, + upper | xdigit | print | alpha, upper | print | alpha, + upper | print | alpha, upper | print | alpha, + upper | print | alpha, upper | print | alpha, + upper | print | alpha, upper | print | alpha, + upper | print | alpha, upper | print | alpha, + upper | print | alpha, upper | print | alpha, + upper | print | alpha, upper | print | alpha, + upper | print | alpha, upper | print | alpha, + upper | print | alpha, upper | print | alpha, + upper | print | alpha, upper | print | alpha, + upper | print | alpha, punct | print, + punct | print, punct | print, + punct | print, punct | print, + punct | print, lower | xdigit | print | alpha, + lower | xdigit | print | alpha, lower | xdigit | print | alpha, + lower | xdigit | print | alpha, lower | xdigit | print | alpha, + lower | xdigit | print | alpha, lower | print | alpha, + lower | print | alpha, lower | print | alpha, + lower | print | alpha, lower | print | alpha, + lower | print | alpha, lower | print | alpha, + lower | print | alpha, lower | print | alpha, + lower | print | alpha, lower | print | alpha, + lower | print | alpha, lower | print | alpha, + lower | print | alpha, lower | print | alpha, + lower | print | alpha, lower | print | alpha, + lower | print | alpha, lower | print | alpha, + lower | print | alpha, punct | print, + punct | print, punct | print, + punct | print, cntrl, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + return builtin_table; +} +#else +const ctype<char>::mask* +ctype<char>::classic_table() noexcept +{ +#if defined(__APPLE__) || defined(__FreeBSD__) + return _DefaultRuneLocale.__runetype; +#elif defined(__NetBSD__) + return _C_ctype_tab_ + 1; +#elif defined(__GLIBC__) + return _LIBCPP_GET_C_LOCALE->__ctype_b; +#elif defined(__sun__) + return __ctype_mask; +#elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) + return __pctype_func(); +#elif defined(__EMSCRIPTEN__) + return *__ctype_b_loc(); +#elif defined(_NEWLIB_VERSION) + // Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1]. + return _ctype_ + 1; +#elif defined(__ANDROID__) + return _ctype_android; +#elif defined(_AIX) + return (const unsigned int *)__lc_ctype_ptr->obj->mask; +#else + // Platform not supported: abort so the person doing the port knows what to + // fix +# warning ctype<char>::classic_table() is not implemented + printf("ctype<char>::classic_table() is not implemented\n"); + abort(); + return NULL; +#endif +} +#endif + +#if defined(__GLIBC__) +const int* +ctype<char>::__classic_lower_table() noexcept +{ + return _LIBCPP_GET_C_LOCALE->__ctype_tolower; +} + +const int* +ctype<char>::__classic_upper_table() noexcept +{ + return _LIBCPP_GET_C_LOCALE->__ctype_toupper; +} +#elif defined(__NetBSD__) +const short* +ctype<char>::__classic_lower_table() noexcept +{ + return _C_tolower_tab_ + 1; +} + +const short* +ctype<char>::__classic_upper_table() noexcept +{ + return _C_toupper_tab_ + 1; +} + +#elif defined(__EMSCRIPTEN__) +const int* +ctype<char>::__classic_lower_table() noexcept +{ + return *__ctype_tolower_loc(); +} + +const int* +ctype<char>::__classic_upper_table() noexcept +{ + return *__ctype_toupper_loc(); +} +#endif // __GLIBC__ || __NETBSD__ || __EMSCRIPTEN__ + +// template <> class ctype_byname<char> + +ctype_byname<char>::ctype_byname(const char* name, size_t refs) + : ctype<char>(0, false, refs), + __l(newlocale(LC_ALL_MASK, name, 0)) +{ + if (__l == 0) + __throw_runtime_error("ctype_byname<char>::ctype_byname" + " failed to construct for " + string(name)); +} + +ctype_byname<char>::ctype_byname(const string& name, size_t refs) + : ctype<char>(0, false, refs), + __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) +{ + if (__l == 0) + __throw_runtime_error("ctype_byname<char>::ctype_byname" + " failed to construct for " + name); +} + +ctype_byname<char>::~ctype_byname() +{ + freelocale(__l); +} + +char +ctype_byname<char>::do_toupper(char_type c) const +{ + return static_cast<char>(toupper_l(static_cast<unsigned char>(c), __l)); +} + +const char* +ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = static_cast<char>(toupper_l(static_cast<unsigned char>(*low), __l)); + return low; +} + +char +ctype_byname<char>::do_tolower(char_type c) const +{ + return static_cast<char>(tolower_l(static_cast<unsigned char>(c), __l)); +} + +const char* +ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = static_cast<char>(tolower_l(static_cast<unsigned char>(*low), __l)); + return low; +} + +// template <> class ctype_byname<wchar_t> + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs) + : ctype<wchar_t>(refs), + __l(newlocale(LC_ALL_MASK, name, 0)) +{ + if (__l == 0) + __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname" + " failed to construct for " + string(name)); +} + +ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs) + : ctype<wchar_t>(refs), + __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) +{ + if (__l == 0) + __throw_runtime_error("ctype_byname<wchar_t>::ctype_byname" + " failed to construct for " + name); +} + +ctype_byname<wchar_t>::~ctype_byname() +{ + freelocale(__l); +} + +bool +ctype_byname<wchar_t>::do_is(mask m, char_type c) const +{ +#ifdef _LIBCPP_WCTYPE_IS_MASK + return static_cast<bool>(iswctype_l(c, m, __l)); +#else + bool result = false; + wint_t ch = static_cast<wint_t>(c); + if ((m & space) == space) result |= (iswspace_l(ch, __l) != 0); + if ((m & print) == print) result |= (iswprint_l(ch, __l) != 0); + if ((m & cntrl) == cntrl) result |= (iswcntrl_l(ch, __l) != 0); + if ((m & upper) == upper) result |= (iswupper_l(ch, __l) != 0); + if ((m & lower) == lower) result |= (iswlower_l(ch, __l) != 0); + if ((m & alpha) == alpha) result |= (iswalpha_l(ch, __l) != 0); + if ((m & digit) == digit) result |= (iswdigit_l(ch, __l) != 0); + if ((m & punct) == punct) result |= (iswpunct_l(ch, __l) != 0); + if ((m & xdigit) == xdigit) result |= (iswxdigit_l(ch, __l) != 0); + if ((m & blank) == blank) result |= (iswblank_l(ch, __l) != 0); + return result; +#endif +} + +const wchar_t* +ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const +{ + for (; low != high; ++low, ++vec) + { + if (isascii(*low)) + *vec = static_cast<mask>(ctype<char>::classic_table()[*low]); + else + { + *vec = 0; + wint_t ch = static_cast<wint_t>(*low); + if (iswspace_l(ch, __l)) + *vec |= space; +#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT + if (iswprint_l(ch, __l)) + *vec |= print; +#endif + if (iswcntrl_l(ch, __l)) + *vec |= cntrl; + if (iswupper_l(ch, __l)) + *vec |= upper; + if (iswlower_l(ch, __l)) + *vec |= lower; +#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA + if (iswalpha_l(ch, __l)) + *vec |= alpha; +#endif + if (iswdigit_l(ch, __l)) + *vec |= digit; + if (iswpunct_l(ch, __l)) + *vec |= punct; +#ifndef _LIBCPP_CTYPE_MASK_IS_COMPOSITE_XDIGIT + if (iswxdigit_l(ch, __l)) + *vec |= xdigit; +#endif +#if !defined(__sun__) + if (iswblank_l(ch, __l)) + *vec |= blank; +#endif + } + } + return low; +} + +const wchar_t* +ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + { +#ifdef _LIBCPP_WCTYPE_IS_MASK + if (iswctype_l(*low, m, __l)) + break; +#else + wint_t ch = static_cast<wint_t>(*low); + if ((m & space) == space && iswspace_l(ch, __l)) break; + if ((m & print) == print && iswprint_l(ch, __l)) break; + if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) break; + if ((m & upper) == upper && iswupper_l(ch, __l)) break; + if ((m & lower) == lower && iswlower_l(ch, __l)) break; + if ((m & alpha) == alpha && iswalpha_l(ch, __l)) break; + if ((m & digit) == digit && iswdigit_l(ch, __l)) break; + if ((m & punct) == punct && iswpunct_l(ch, __l)) break; + if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) break; + if ((m & blank) == blank && iswblank_l(ch, __l)) break; +#endif + } + return low; +} + +const wchar_t* +ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + { +#ifdef _LIBCPP_WCTYPE_IS_MASK + if (!iswctype_l(*low, m, __l)) + break; +#else + wint_t ch = static_cast<wint_t>(*low); + if ((m & space) == space && iswspace_l(ch, __l)) continue; + if ((m & print) == print && iswprint_l(ch, __l)) continue; + if ((m & cntrl) == cntrl && iswcntrl_l(ch, __l)) continue; + if ((m & upper) == upper && iswupper_l(ch, __l)) continue; + if ((m & lower) == lower && iswlower_l(ch, __l)) continue; + if ((m & alpha) == alpha && iswalpha_l(ch, __l)) continue; + if ((m & digit) == digit && iswdigit_l(ch, __l)) continue; + if ((m & punct) == punct && iswpunct_l(ch, __l)) continue; + if ((m & xdigit) == xdigit && iswxdigit_l(ch, __l)) continue; + if ((m & blank) == blank && iswblank_l(ch, __l)) continue; + break; +#endif + } + return low; +} + +wchar_t +ctype_byname<wchar_t>::do_toupper(char_type c) const +{ + return towupper_l(c, __l); +} + +const wchar_t* +ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = towupper_l(*low, __l); + return low; +} + +wchar_t +ctype_byname<wchar_t>::do_tolower(char_type c) const +{ + return towlower_l(c, __l); +} + +const wchar_t* +ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = towlower_l(*low, __l); + return low; +} + +wchar_t +ctype_byname<wchar_t>::do_widen(char c) const +{ + return __libcpp_btowc_l(c, __l); +} + +const char* +ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const +{ + for (; low != high; ++low, ++dest) + *dest = __libcpp_btowc_l(*low, __l); + return low; +} + +char +ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const +{ + int r = __libcpp_wctob_l(c, __l); + return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault; +} + +const wchar_t* +ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const +{ + for (; low != high; ++low, ++dest) + { + int r = __libcpp_wctob_l(*low, __l); + *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault; + } + return low; +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// template <> class codecvt<char, char, mbstate_t> + +locale::id codecvt<char, char, mbstate_t>::id; + +codecvt<char, char, mbstate_t>::~codecvt() +{ +} + +codecvt<char, char, mbstate_t>::result +codecvt<char, char, mbstate_t>::do_out(state_type&, + const intern_type* frm, const intern_type*, const intern_type*& frm_nxt, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + frm_nxt = frm; + to_nxt = to; + return noconv; +} + +codecvt<char, char, mbstate_t>::result +codecvt<char, char, mbstate_t>::do_in(state_type&, + const extern_type* frm, const extern_type*, const extern_type*& frm_nxt, + intern_type* to, intern_type*, intern_type*& to_nxt) const +{ + frm_nxt = frm; + to_nxt = to; + return noconv; +} + +codecvt<char, char, mbstate_t>::result +codecvt<char, char, mbstate_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +codecvt<char, char, mbstate_t>::do_encoding() const noexcept +{ + return 1; +} + +bool +codecvt<char, char, mbstate_t>::do_always_noconv() const noexcept +{ + return true; +} + +int +codecvt<char, char, mbstate_t>::do_length(state_type&, + const extern_type* frm, const extern_type* end, size_t mx) const +{ + return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm))); +} + +int +codecvt<char, char, mbstate_t>::do_max_length() const noexcept +{ + return 1; +} + +// template <> class codecvt<wchar_t, char, mbstate_t> + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +locale::id codecvt<wchar_t, char, mbstate_t>::id; + +codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs) + : locale::facet(refs), + __l(_LIBCPP_GET_C_LOCALE) +{ +} + +codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs) + : locale::facet(refs), + __l(newlocale(LC_ALL_MASK, nm, 0)) +{ + if (__l == 0) + __throw_runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname" + " failed to construct for " + string(nm)); +} + +codecvt<wchar_t, char, mbstate_t>::~codecvt() +{ + if (__l != _LIBCPP_GET_C_LOCALE) + freelocale(__l); +} + +codecvt<wchar_t, char, mbstate_t>::result +codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + // look for first internal null in frm + const intern_type* fend = frm; + for (; fend != frm_end; ++fend) + if (*fend == 0) + break; + // loop over all null-terminated sequences in frm + to_nxt = to; + for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) + { + // save state in case it is needed to recover to_nxt on error + mbstate_t save_state = st; + size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), + static_cast<size_t>(to_end-to), &st, __l); + if (n == size_t(-1)) + { + // need to recover to_nxt + for (to_nxt = to; frm != frm_nxt; ++frm) + { + n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l); + if (n == size_t(-1)) + break; + to_nxt += n; + } + frm_nxt = frm; + return error; + } + if (n == 0) + return partial; + to_nxt += n; + if (to_nxt == to_end) + break; + if (fend != frm_end) // set up next null terminated sequence + { + // Try to write the terminating null + extern_type tmp[MB_LEN_MAX]; + n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l); + if (n == size_t(-1)) // on error + return error; + if (n > static_cast<size_t>(to_end-to_nxt)) // is there room? + return partial; + for (extern_type* p = tmp; n; --n) // write it + *to_nxt++ = *p++; + ++frm_nxt; + // look for next null in frm + for (fend = frm_nxt; fend != frm_end; ++fend) + if (*fend == 0) + break; + } + } + return frm_nxt == frm_end ? ok : partial; +} + +codecvt<wchar_t, char, mbstate_t>::result +codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + // look for first internal null in frm + const extern_type* fend = frm; + for (; fend != frm_end; ++fend) + if (*fend == 0) + break; + // loop over all null-terminated sequences in frm + to_nxt = to; + for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) + { + // save state in case it is needed to recover to_nxt on error + mbstate_t save_state = st; + size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), + static_cast<size_t>(to_end-to), &st, __l); + if (n == size_t(-1)) + { + // need to recover to_nxt + for (to_nxt = to; frm != frm_nxt; ++to_nxt) + { + n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm), + &save_state, __l); + switch (n) + { + case 0: + ++frm; + break; + case size_t(-1): + frm_nxt = frm; + return error; + case size_t(-2): + frm_nxt = frm; + return partial; + default: + frm += n; + break; + } + } + frm_nxt = frm; + return frm_nxt == frm_end ? ok : partial; + } + if (n == size_t(-1)) + return error; + to_nxt += n; + if (to_nxt == to_end) + break; + if (fend != frm_end) // set up next null terminated sequence + { + // Try to write the terminating null + n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l); + if (n != 0) // on error + return error; + ++to_nxt; + ++frm_nxt; + // look for next null in frm + for (fend = frm_nxt; fend != frm_end; ++fend) + if (*fend == 0) + break; + } + } + return frm_nxt == frm_end ? ok : partial; +} + +codecvt<wchar_t, char, mbstate_t>::result +codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + to_nxt = to; + extern_type tmp[MB_LEN_MAX]; + size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l); + if (n == size_t(-1) || n == 0) // on error + return error; + --n; + if (n > static_cast<size_t>(to_end-to_nxt)) // is there room? + return partial; + for (extern_type* p = tmp; n; --n) // write it + *to_nxt++ = *p++; + return ok; +} + +int +codecvt<wchar_t, char, mbstate_t>::do_encoding() const noexcept +{ + if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0) + return -1; + + // stateless encoding + if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings + return 1; // which take more than 1 char to form a wchar_t + return 0; +} + +bool +codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const noexcept +{ + return false; +} + +int +codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + int nbytes = 0; + for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t) + { + size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l); + switch (n) + { + case 0: + ++nbytes; + ++frm; + break; + case size_t(-1): + case size_t(-2): + return nbytes; + default: + nbytes += n; + frm += n; + break; + } + } + return nbytes; +} + +int +codecvt<wchar_t, char, mbstate_t>::do_max_length() const noexcept +{ + return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l)); +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// Valid UTF ranges +// UTF-32 UTF-16 UTF-8 # of code points +// first second first second third fourth +// 000000 - 00007F 0000 - 007F 00 - 7F 127 +// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920 +// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048 +// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152 +// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048 +// 00D800 - 00DFFF invalid +// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192 +// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608 +// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432 +// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536 + +static +codecvt_base::result +utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, + uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & generate_header) + { + if (to_end-to_nxt < 3) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xEF); + *to_nxt++ = static_cast<uint8_t>(0xBB); + *to_nxt++ = static_cast<uint8_t>(0xBF); + } + for (; frm_nxt < frm_end; ++frm_nxt) + { + uint16_t wc1 = *frm_nxt; + if (wc1 > Maxcode) + return codecvt_base::error; + if (wc1 < 0x0080) + { + if (to_end-to_nxt < 1) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(wc1); + } + else if (wc1 < 0x0800) + { + if (to_end-to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); + } + else if (wc1 < 0xD800) + { + if (to_end-to_nxt < 3) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); + } + else if (wc1 < 0xDC00) + { + if (frm_end-frm_nxt < 2) + return codecvt_base::partial; + uint16_t wc2 = frm_nxt[1]; + if ((wc2 & 0xFC00) != 0xDC00) + return codecvt_base::error; + if (to_end-to_nxt < 4) + return codecvt_base::partial; + if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + + ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode) + return codecvt_base::error; + ++frm_nxt; + uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; + *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F)); + } + else if (wc1 < 0xE000) + { + return codecvt_base::error; + } + else + { + if (to_end-to_nxt < 3) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); + } + } + return codecvt_base::ok; +} + +static +codecvt_base::result +utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, + uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & generate_header) + { + if (to_end-to_nxt < 3) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xEF); + *to_nxt++ = static_cast<uint8_t>(0xBB); + *to_nxt++ = static_cast<uint8_t>(0xBF); + } + for (; frm_nxt < frm_end; ++frm_nxt) + { + uint16_t wc1 = static_cast<uint16_t>(*frm_nxt); + if (wc1 > Maxcode) + return codecvt_base::error; + if (wc1 < 0x0080) + { + if (to_end-to_nxt < 1) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(wc1); + } + else if (wc1 < 0x0800) + { + if (to_end-to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); + } + else if (wc1 < 0xD800) + { + if (to_end-to_nxt < 3) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); + } + else if (wc1 < 0xDC00) + { + if (frm_end-frm_nxt < 2) + return codecvt_base::partial; + uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]); + if ((wc2 & 0xFC00) != 0xDC00) + return codecvt_base::error; + if (to_end-to_nxt < 4) + return codecvt_base::partial; + if (((((wc1 & 0x03C0UL) >> 6) + 1) << 16) + + ((wc1 & 0x003FUL) << 10) + (wc2 & 0x03FF) > Maxcode) + return codecvt_base::error; + ++frm_nxt; + uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; + *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc2 & 0x003F)); + } + else if (wc1 < 0xE000) + { + return codecvt_base::error; + } + else + { + if (to_end-to_nxt < 3) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc1 >> 12)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x003F)); + } + } + return codecvt_base::ok; +} + +static +codecvt_base::result +utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, + uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && + frm_nxt[2] == 0xBF) + frm_nxt += 3; + } + for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) + { + uint8_t c1 = *frm_nxt; + if (c1 > Maxcode) + return codecvt_base::error; + if (c1 < 0x80) + { + *to_nxt = static_cast<uint16_t>(c1); + ++frm_nxt; + } + else if (c1 < 0xC2) + { + return codecvt_base::error; + } + else if (c1 < 0xE0) + { + if (frm_end-frm_nxt < 2) + return codecvt_base::partial; + uint8_t c2 = frm_nxt[1]; + if ((c2 & 0xC0) != 0x80) + return codecvt_base::error; + uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); + if (t > Maxcode) + return codecvt_base::error; + *to_nxt = t; + frm_nxt += 2; + } + else if (c1 < 0xF0) + { + if (frm_end-frm_nxt < 3) + return codecvt_base::partial; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + switch (c1) + { + case 0xE0: + if ((c2 & 0xE0) != 0xA0) + return codecvt_base::error; + break; + case 0xED: + if ((c2 & 0xE0) != 0x80) + return codecvt_base::error; + break; + default: + if ((c2 & 0xC0) != 0x80) + return codecvt_base::error; + break; + } + if ((c3 & 0xC0) != 0x80) + return codecvt_base::error; + uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) + | ((c2 & 0x3F) << 6) + | (c3 & 0x3F)); + if (t > Maxcode) + return codecvt_base::error; + *to_nxt = t; + frm_nxt += 3; + } + else if (c1 < 0xF5) + { + if (frm_end-frm_nxt < 4) + return codecvt_base::partial; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + uint8_t c4 = frm_nxt[3]; + switch (c1) + { + case 0xF0: + if (!(0x90 <= c2 && c2 <= 0xBF)) + return codecvt_base::error; + break; + case 0xF4: + if ((c2 & 0xF0) != 0x80) + return codecvt_base::error; + break; + default: + if ((c2 & 0xC0) != 0x80) + return codecvt_base::error; + break; + } + if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) + return codecvt_base::error; + if (to_end-to_nxt < 2) + return codecvt_base::partial; + if ((((c1 & 7UL) << 18) + + ((c2 & 0x3FUL) << 12) + + ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) + return codecvt_base::error; + *to_nxt = static_cast<uint16_t>( + 0xD800 + | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) + | ((c2 & 0x0F) << 2) + | ((c3 & 0x30) >> 4)); + *++to_nxt = static_cast<uint16_t>( + 0xDC00 + | ((c3 & 0x0F) << 6) + | (c4 & 0x3F)); + frm_nxt += 4; + } + else + { + return codecvt_base::error; + } + } + return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +codecvt_base::result +utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, + uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && + frm_nxt[2] == 0xBF) + frm_nxt += 3; + } + for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) + { + uint8_t c1 = *frm_nxt; + if (c1 > Maxcode) + return codecvt_base::error; + if (c1 < 0x80) + { + *to_nxt = static_cast<uint32_t>(c1); + ++frm_nxt; + } + else if (c1 < 0xC2) + { + return codecvt_base::error; + } + else if (c1 < 0xE0) + { + if (frm_end-frm_nxt < 2) + return codecvt_base::partial; + uint8_t c2 = frm_nxt[1]; + if ((c2 & 0xC0) != 0x80) + return codecvt_base::error; + uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); + if (t > Maxcode) + return codecvt_base::error; + *to_nxt = static_cast<uint32_t>(t); + frm_nxt += 2; + } + else if (c1 < 0xF0) + { + if (frm_end-frm_nxt < 3) + return codecvt_base::partial; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + switch (c1) + { + case 0xE0: + if ((c2 & 0xE0) != 0xA0) + return codecvt_base::error; + break; + case 0xED: + if ((c2 & 0xE0) != 0x80) + return codecvt_base::error; + break; + default: + if ((c2 & 0xC0) != 0x80) + return codecvt_base::error; + break; + } + if ((c3 & 0xC0) != 0x80) + return codecvt_base::error; + uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) + | ((c2 & 0x3F) << 6) + | (c3 & 0x3F)); + if (t > Maxcode) + return codecvt_base::error; + *to_nxt = static_cast<uint32_t>(t); + frm_nxt += 3; + } + else if (c1 < 0xF5) + { + if (frm_end-frm_nxt < 4) + return codecvt_base::partial; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + uint8_t c4 = frm_nxt[3]; + switch (c1) + { + case 0xF0: + if (!(0x90 <= c2 && c2 <= 0xBF)) + return codecvt_base::error; + break; + case 0xF4: + if ((c2 & 0xF0) != 0x80) + return codecvt_base::error; + break; + default: + if ((c2 & 0xC0) != 0x80) + return codecvt_base::error; + break; + } + if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) + return codecvt_base::error; + if (to_end-to_nxt < 2) + return codecvt_base::partial; + if ((((c1 & 7UL) << 18) + + ((c2 & 0x3FUL) << 12) + + ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) + return codecvt_base::error; + *to_nxt = static_cast<uint32_t>( + 0xD800 + | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) + | ((c2 & 0x0F) << 2) + | ((c3 & 0x30) >> 4)); + *++to_nxt = static_cast<uint32_t>( + 0xDC00 + | ((c3 & 0x0F) << 6) + | (c4 & 0x3F)); + frm_nxt += 4; + } + else + { + return codecvt_base::error; + } + } + return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end, + size_t mx, unsigned long Maxcode = 0x10FFFF, + codecvt_mode mode = codecvt_mode(0)) +{ + const uint8_t* frm_nxt = frm; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && + frm_nxt[2] == 0xBF) + frm_nxt += 3; + } + for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t) + { + uint8_t c1 = *frm_nxt; + if (c1 > Maxcode) + break; + if (c1 < 0x80) + { + ++frm_nxt; + } + else if (c1 < 0xC2) + { + break; + } + else if (c1 < 0xE0) + { + if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80) + break; + uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)); + if (t > Maxcode) + break; + frm_nxt += 2; + } + else if (c1 < 0xF0) + { + if (frm_end-frm_nxt < 3) + break; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + switch (c1) + { + case 0xE0: + if ((c2 & 0xE0) != 0xA0) + return static_cast<int>(frm_nxt - frm); + break; + case 0xED: + if ((c2 & 0xE0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + default: + if ((c2 & 0xC0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + } + if ((c3 & 0xC0) != 0x80) + break; + if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) + break; + frm_nxt += 3; + } + else if (c1 < 0xF5) + { + if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2) + break; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + uint8_t c4 = frm_nxt[3]; + switch (c1) + { + case 0xF0: + if (!(0x90 <= c2 && c2 <= 0xBF)) + return static_cast<int>(frm_nxt - frm); + break; + case 0xF4: + if ((c2 & 0xF0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + default: + if ((c2 & 0xC0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + } + if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) + break; + if ((((c1 & 7UL) << 18) + + ((c2 & 0x3FUL) << 12) + + ((c3 & 0x3FUL) << 6) + (c4 & 0x3F)) > Maxcode) + break; + ++nchar16_t; + frm_nxt += 4; + } + else + { + break; + } + } + return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, + uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & generate_header) + { + if (to_end-to_nxt < 3) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xEF); + *to_nxt++ = static_cast<uint8_t>(0xBB); + *to_nxt++ = static_cast<uint8_t>(0xBF); + } + for (; frm_nxt < frm_end; ++frm_nxt) + { + uint32_t wc = *frm_nxt; + if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) + return codecvt_base::error; + if (wc < 0x000080) + { + if (to_end-to_nxt < 1) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(wc); + } + else if (wc < 0x000800) + { + if (to_end-to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); + } + else if (wc < 0x010000) + { + if (to_end-to_nxt < 3) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F)); + } + else // if (wc < 0x110000) + { + if (to_end-to_nxt < 4) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xF0 | (wc >> 18)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x00003F)); + } + } + return codecvt_base::ok; +} + +static +codecvt_base::result +utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, + uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && + frm_nxt[2] == 0xBF) + frm_nxt += 3; + } + for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) + { + uint8_t c1 = static_cast<uint8_t>(*frm_nxt); + if (c1 < 0x80) + { + if (c1 > Maxcode) + return codecvt_base::error; + *to_nxt = static_cast<uint32_t>(c1); + ++frm_nxt; + } + else if (c1 < 0xC2) + { + return codecvt_base::error; + } + else if (c1 < 0xE0) + { + if (frm_end-frm_nxt < 2) + return codecvt_base::partial; + uint8_t c2 = frm_nxt[1]; + if ((c2 & 0xC0) != 0x80) + return codecvt_base::error; + uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6) + | (c2 & 0x3F)); + if (t > Maxcode) + return codecvt_base::error; + *to_nxt = t; + frm_nxt += 2; + } + else if (c1 < 0xF0) + { + if (frm_end-frm_nxt < 3) + return codecvt_base::partial; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + switch (c1) + { + case 0xE0: + if ((c2 & 0xE0) != 0xA0) + return codecvt_base::error; + break; + case 0xED: + if ((c2 & 0xE0) != 0x80) + return codecvt_base::error; + break; + default: + if ((c2 & 0xC0) != 0x80) + return codecvt_base::error; + break; + } + if ((c3 & 0xC0) != 0x80) + return codecvt_base::error; + uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12) + | ((c2 & 0x3F) << 6) + | (c3 & 0x3F)); + if (t > Maxcode) + return codecvt_base::error; + *to_nxt = t; + frm_nxt += 3; + } + else if (c1 < 0xF5) + { + if (frm_end-frm_nxt < 4) + return codecvt_base::partial; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + uint8_t c4 = frm_nxt[3]; + switch (c1) + { + case 0xF0: + if (!(0x90 <= c2 && c2 <= 0xBF)) + return codecvt_base::error; + break; + case 0xF4: + if ((c2 & 0xF0) != 0x80) + return codecvt_base::error; + break; + default: + if ((c2 & 0xC0) != 0x80) + return codecvt_base::error; + break; + } + if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) + return codecvt_base::error; + uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18) + | ((c2 & 0x3F) << 12) + | ((c3 & 0x3F) << 6) + | (c4 & 0x3F)); + if (t > Maxcode) + return codecvt_base::error; + *to_nxt = t; + frm_nxt += 4; + } + else + { + return codecvt_base::error; + } + } + return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, + size_t mx, unsigned long Maxcode = 0x10FFFF, + codecvt_mode mode = codecvt_mode(0)) +{ + const uint8_t* frm_nxt = frm; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && + frm_nxt[2] == 0xBF) + frm_nxt += 3; + } + for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) + { + uint8_t c1 = static_cast<uint8_t>(*frm_nxt); + if (c1 < 0x80) + { + if (c1 > Maxcode) + break; + ++frm_nxt; + } + else if (c1 < 0xC2) + { + break; + } + else if (c1 < 0xE0) + { + if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) + break; + if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) + break; + frm_nxt += 2; + } + else if (c1 < 0xF0) + { + if (frm_end-frm_nxt < 3) + break; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + switch (c1) + { + case 0xE0: + if ((c2 & 0xE0) != 0xA0) + return static_cast<int>(frm_nxt - frm); + break; + case 0xED: + if ((c2 & 0xE0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + default: + if ((c2 & 0xC0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + } + if ((c3 & 0xC0) != 0x80) + break; + if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) + break; + frm_nxt += 3; + } + else if (c1 < 0xF5) + { + if (frm_end-frm_nxt < 4) + break; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + uint8_t c4 = frm_nxt[3]; + switch (c1) + { + case 0xF0: + if (!(0x90 <= c2 && c2 <= 0xBF)) + return static_cast<int>(frm_nxt - frm); + break; + case 0xF4: + if ((c2 & 0xF0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + default: + if ((c2 & 0xC0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + } + if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) + break; + if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) | + ((c3 & 0x3Fu) << 6) | (c4 & 0x3Fu)) > Maxcode) + break; + frm_nxt += 4; + } + else + { + break; + } + } + return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, + uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & generate_header) + { + if (to_end-to_nxt < 3) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xEF); + *to_nxt++ = static_cast<uint8_t>(0xBB); + *to_nxt++ = static_cast<uint8_t>(0xBF); + } + for (; frm_nxt < frm_end; ++frm_nxt) + { + uint16_t wc = *frm_nxt; + if ((wc & 0xF800) == 0xD800 || wc > Maxcode) + return codecvt_base::error; + if (wc < 0x0080) + { + if (to_end-to_nxt < 1) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(wc); + } + else if (wc < 0x0800) + { + if (to_end-to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); + } + else // if (wc <= 0xFFFF) + { + if (to_end-to_nxt < 3) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xE0 | (wc >> 12)); + *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); + *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x003F)); + } + } + return codecvt_base::ok; +} + +static +codecvt_base::result +utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, + uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && + frm_nxt[2] == 0xBF) + frm_nxt += 3; + } + for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) + { + uint8_t c1 = static_cast<uint8_t>(*frm_nxt); + if (c1 < 0x80) + { + if (c1 > Maxcode) + return codecvt_base::error; + *to_nxt = static_cast<uint16_t>(c1); + ++frm_nxt; + } + else if (c1 < 0xC2) + { + return codecvt_base::error; + } + else if (c1 < 0xE0) + { + if (frm_end-frm_nxt < 2) + return codecvt_base::partial; + uint8_t c2 = frm_nxt[1]; + if ((c2 & 0xC0) != 0x80) + return codecvt_base::error; + uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) + | (c2 & 0x3F)); + if (t > Maxcode) + return codecvt_base::error; + *to_nxt = t; + frm_nxt += 2; + } + else if (c1 < 0xF0) + { + if (frm_end-frm_nxt < 3) + return codecvt_base::partial; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + switch (c1) + { + case 0xE0: + if ((c2 & 0xE0) != 0xA0) + return codecvt_base::error; + break; + case 0xED: + if ((c2 & 0xE0) != 0x80) + return codecvt_base::error; + break; + default: + if ((c2 & 0xC0) != 0x80) + return codecvt_base::error; + break; + } + if ((c3 & 0xC0) != 0x80) + return codecvt_base::error; + uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) + | ((c2 & 0x3F) << 6) + | (c3 & 0x3F)); + if (t > Maxcode) + return codecvt_base::error; + *to_nxt = t; + frm_nxt += 3; + } + else + { + return codecvt_base::error; + } + } + return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, + size_t mx, unsigned long Maxcode = 0x10FFFF, + codecvt_mode mode = codecvt_mode(0)) +{ + const uint8_t* frm_nxt = frm; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && + frm_nxt[2] == 0xBF) + frm_nxt += 3; + } + for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) + { + uint8_t c1 = static_cast<uint8_t>(*frm_nxt); + if (c1 < 0x80) + { + if (c1 > Maxcode) + break; + ++frm_nxt; + } + else if (c1 < 0xC2) + { + break; + } + else if (c1 < 0xE0) + { + if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) + break; + if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) + break; + frm_nxt += 2; + } + else if (c1 < 0xF0) + { + if (frm_end-frm_nxt < 3) + break; + uint8_t c2 = frm_nxt[1]; + uint8_t c3 = frm_nxt[2]; + switch (c1) + { + case 0xE0: + if ((c2 & 0xE0) != 0xA0) + return static_cast<int>(frm_nxt - frm); + break; + case 0xED: + if ((c2 & 0xE0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + default: + if ((c2 & 0xC0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + } + if ((c3 & 0xC0) != 0x80) + break; + if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) + break; + frm_nxt += 3; + } + else + { + break; + } + } + return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, + uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & generate_header) + { + if (to_end-to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xFE); + *to_nxt++ = static_cast<uint8_t>(0xFF); + } + for (; frm_nxt < frm_end; ++frm_nxt) + { + uint32_t wc = *frm_nxt; + if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) + return codecvt_base::error; + if (wc < 0x010000) + { + if (to_end-to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(wc >> 8); + *to_nxt++ = static_cast<uint8_t>(wc); + } + else + { + if (to_end-to_nxt < 4) + return codecvt_base::partial; + uint16_t t = static_cast<uint16_t>( + 0xD800 + | ((((wc & 0x1F0000) >> 16) - 1) << 6) + | ((wc & 0x00FC00) >> 10)); + *to_nxt++ = static_cast<uint8_t>(t >> 8); + *to_nxt++ = static_cast<uint8_t>(t); + t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); + *to_nxt++ = static_cast<uint8_t>(t >> 8); + *to_nxt++ = static_cast<uint8_t>(t); + } + } + return codecvt_base::ok; +} + +static +codecvt_base::result +utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, + uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) + frm_nxt += 2; + } + for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) + { + uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); + if ((c1 & 0xFC00) == 0xDC00) + return codecvt_base::error; + if ((c1 & 0xFC00) != 0xD800) + { + if (c1 > Maxcode) + return codecvt_base::error; + *to_nxt = static_cast<uint32_t>(c1); + frm_nxt += 2; + } + else + { + if (frm_end-frm_nxt < 4) + return codecvt_base::partial; + uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); + if ((c2 & 0xFC00) != 0xDC00) + return codecvt_base::error; + uint32_t t = static_cast<uint32_t>( + ((((c1 & 0x03C0) >> 6) + 1) << 16) + | ((c1 & 0x003F) << 10) + | (c2 & 0x03FF)); + if (t > Maxcode) + return codecvt_base::error; + *to_nxt = t; + frm_nxt += 4; + } + } + return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, + size_t mx, unsigned long Maxcode = 0x10FFFF, + codecvt_mode mode = codecvt_mode(0)) +{ + const uint8_t* frm_nxt = frm; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) + frm_nxt += 2; + } + for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) + { + uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); + if ((c1 & 0xFC00) == 0xDC00) + break; + if ((c1 & 0xFC00) != 0xD800) + { + if (c1 > Maxcode) + break; + frm_nxt += 2; + } + else + { + if (frm_end-frm_nxt < 4) + break; + uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); + if ((c2 & 0xFC00) != 0xDC00) + break; + uint32_t t = static_cast<uint32_t>( + ((((c1 & 0x03C0) >> 6) + 1) << 16) + | ((c1 & 0x003F) << 10) + | (c2 & 0x03FF)); + if (t > Maxcode) + break; + frm_nxt += 4; + } + } + return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, + uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & generate_header) + { + if (to_end - to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xFF); + *to_nxt++ = static_cast<uint8_t>(0xFE); + } + for (; frm_nxt < frm_end; ++frm_nxt) + { + uint32_t wc = *frm_nxt; + if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) + return codecvt_base::error; + if (wc < 0x010000) + { + if (to_end-to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(wc); + *to_nxt++ = static_cast<uint8_t>(wc >> 8); + } + else + { + if (to_end-to_nxt < 4) + return codecvt_base::partial; + uint16_t t = static_cast<uint16_t>( + 0xD800 + | ((((wc & 0x1F0000) >> 16) - 1) << 6) + | ((wc & 0x00FC00) >> 10)); + *to_nxt++ = static_cast<uint8_t>(t); + *to_nxt++ = static_cast<uint8_t>(t >> 8); + t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); + *to_nxt++ = static_cast<uint8_t>(t); + *to_nxt++ = static_cast<uint8_t>(t >> 8); + } + } + return codecvt_base::ok; +} + +static +codecvt_base::result +utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, + uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) + frm_nxt += 2; + } + for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) + { + uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); + if ((c1 & 0xFC00) == 0xDC00) + return codecvt_base::error; + if ((c1 & 0xFC00) != 0xD800) + { + if (c1 > Maxcode) + return codecvt_base::error; + *to_nxt = static_cast<uint32_t>(c1); + frm_nxt += 2; + } + else + { + if (frm_end-frm_nxt < 4) + return codecvt_base::partial; + uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); + if ((c2 & 0xFC00) != 0xDC00) + return codecvt_base::error; + uint32_t t = static_cast<uint32_t>( + ((((c1 & 0x03C0) >> 6) + 1) << 16) + | ((c1 & 0x003F) << 10) + | (c2 & 0x03FF)); + if (t > Maxcode) + return codecvt_base::error; + *to_nxt = t; + frm_nxt += 4; + } + } + return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, + size_t mx, unsigned long Maxcode = 0x10FFFF, + codecvt_mode mode = codecvt_mode(0)) +{ + const uint8_t* frm_nxt = frm; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) + frm_nxt += 2; + } + for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) + { + uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); + if ((c1 & 0xFC00) == 0xDC00) + break; + if ((c1 & 0xFC00) != 0xD800) + { + if (c1 > Maxcode) + break; + frm_nxt += 2; + } + else + { + if (frm_end-frm_nxt < 4) + break; + uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); + if ((c2 & 0xFC00) != 0xDC00) + break; + uint32_t t = static_cast<uint32_t>( + ((((c1 & 0x03C0) >> 6) + 1) << 16) + | ((c1 & 0x003F) << 10) + | (c2 & 0x03FF)); + if (t > Maxcode) + break; + frm_nxt += 4; + } + } + return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, + uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & generate_header) + { + if (to_end-to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xFE); + *to_nxt++ = static_cast<uint8_t>(0xFF); + } + for (; frm_nxt < frm_end; ++frm_nxt) + { + uint16_t wc = *frm_nxt; + if ((wc & 0xF800) == 0xD800 || wc > Maxcode) + return codecvt_base::error; + if (to_end-to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(wc >> 8); + *to_nxt++ = static_cast<uint8_t>(wc); + } + return codecvt_base::ok; +} + +static +codecvt_base::result +utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, + uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) + frm_nxt += 2; + } + for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) + { + uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); + if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) + return codecvt_base::error; + *to_nxt = c1; + frm_nxt += 2; + } + return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, + size_t mx, unsigned long Maxcode = 0x10FFFF, + codecvt_mode mode = codecvt_mode(0)) +{ + const uint8_t* frm_nxt = frm; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) + frm_nxt += 2; + } + for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) + { + uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); + if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) + break; + frm_nxt += 2; + } + return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, + uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & generate_header) + { + if (to_end-to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(0xFF); + *to_nxt++ = static_cast<uint8_t>(0xFE); + } + for (; frm_nxt < frm_end; ++frm_nxt) + { + uint16_t wc = *frm_nxt; + if ((wc & 0xF800) == 0xD800 || wc > Maxcode) + return codecvt_base::error; + if (to_end-to_nxt < 2) + return codecvt_base::partial; + *to_nxt++ = static_cast<uint8_t>(wc); + *to_nxt++ = static_cast<uint8_t>(wc >> 8); + } + return codecvt_base::ok; +} + +static +codecvt_base::result +utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, + uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, + unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ + frm_nxt = frm; + to_nxt = to; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) + frm_nxt += 2; + } + for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) + { + uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); + if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) + return codecvt_base::error; + *to_nxt = c1; + frm_nxt += 2; + } + return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, + size_t mx, unsigned long Maxcode = 0x10FFFF, + codecvt_mode mode = codecvt_mode(0)) +{ + const uint8_t* frm_nxt = frm; + frm_nxt = frm; + if (mode & consume_header) + { + if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) + frm_nxt += 2; + } + for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) + { + uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); + if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) + break; + frm_nxt += 2; + } + return static_cast<int>(frm_nxt - frm); +} + +// template <> class codecvt<char16_t, char, mbstate_t> + +locale::id codecvt<char16_t, char, mbstate_t>::id; + +codecvt<char16_t, char, mbstate_t>::~codecvt() +{ +} + +codecvt<char16_t, char, mbstate_t>::result +codecvt<char16_t, char, mbstate_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); + const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); + const uint16_t* _frm_nxt = _frm; + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +codecvt<char16_t, char, mbstate_t>::result +codecvt<char16_t, char, mbstate_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; + uint16_t* _to = reinterpret_cast<uint16_t*>(to); + uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); + uint16_t* _to_nxt = _to; + result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +codecvt<char16_t, char, mbstate_t>::result +codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +codecvt<char16_t, char, mbstate_t>::do_encoding() const noexcept +{ + return 0; +} + +bool +codecvt<char16_t, char, mbstate_t>::do_always_noconv() const noexcept +{ + return false; +} + +int +codecvt<char16_t, char, mbstate_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf8_to_utf16_length(_frm, _frm_end, mx); +} + +int +codecvt<char16_t, char, mbstate_t>::do_max_length() const noexcept +{ + return 4; +} + +#ifndef _LIBCPP_HAS_NO_CHAR8_T + +// template <> class codecvt<char16_t, char8_t, mbstate_t> + +locale::id codecvt<char16_t, char8_t, mbstate_t>::id; + +codecvt<char16_t, char8_t, mbstate_t>::~codecvt() +{ +} + +codecvt<char16_t, char8_t, mbstate_t>::result +codecvt<char16_t, char8_t, mbstate_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); + const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); + const uint16_t* _frm_nxt = _frm; + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +codecvt<char16_t, char8_t, mbstate_t>::result +codecvt<char16_t, char8_t, mbstate_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; + uint16_t* _to = reinterpret_cast<uint16_t*>(to); + uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); + uint16_t* _to_nxt = _to; + result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +codecvt<char16_t, char8_t, mbstate_t>::result +codecvt<char16_t, char8_t, mbstate_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +codecvt<char16_t, char8_t, mbstate_t>::do_encoding() const noexcept +{ + return 0; +} + +bool +codecvt<char16_t, char8_t, mbstate_t>::do_always_noconv() const noexcept +{ + return false; +} + +int +codecvt<char16_t, char8_t, mbstate_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf8_to_utf16_length(_frm, _frm_end, mx); +} + +int +codecvt<char16_t, char8_t, mbstate_t>::do_max_length() const noexcept +{ + return 4; +} + +#endif + +// template <> class codecvt<char32_t, char, mbstate_t> + +locale::id codecvt<char32_t, char, mbstate_t>::id; + +codecvt<char32_t, char, mbstate_t>::~codecvt() +{ +} + +codecvt<char32_t, char, mbstate_t>::result +codecvt<char32_t, char, mbstate_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); + const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); + const uint32_t* _frm_nxt = _frm; + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +codecvt<char32_t, char, mbstate_t>::result +codecvt<char32_t, char, mbstate_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; + uint32_t* _to = reinterpret_cast<uint32_t*>(to); + uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); + uint32_t* _to_nxt = _to; + result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +codecvt<char32_t, char, mbstate_t>::result +codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +codecvt<char32_t, char, mbstate_t>::do_encoding() const noexcept +{ + return 0; +} + +bool +codecvt<char32_t, char, mbstate_t>::do_always_noconv() const noexcept +{ + return false; +} + +int +codecvt<char32_t, char, mbstate_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf8_to_ucs4_length(_frm, _frm_end, mx); +} + +int +codecvt<char32_t, char, mbstate_t>::do_max_length() const noexcept +{ + return 4; +} + +#ifndef _LIBCPP_HAS_NO_CHAR8_T + +// template <> class codecvt<char32_t, char8_t, mbstate_t> + +locale::id codecvt<char32_t, char8_t, mbstate_t>::id; + +codecvt<char32_t, char8_t, mbstate_t>::~codecvt() +{ +} + +codecvt<char32_t, char8_t, mbstate_t>::result +codecvt<char32_t, char8_t, mbstate_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); + const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); + const uint32_t* _frm_nxt = _frm; + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +codecvt<char32_t, char8_t, mbstate_t>::result +codecvt<char32_t, char8_t, mbstate_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; + uint32_t* _to = reinterpret_cast<uint32_t*>(to); + uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); + uint32_t* _to_nxt = _to; + result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +codecvt<char32_t, char8_t, mbstate_t>::result +codecvt<char32_t, char8_t, mbstate_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +codecvt<char32_t, char8_t, mbstate_t>::do_encoding() const noexcept +{ + return 0; +} + +bool +codecvt<char32_t, char8_t, mbstate_t>::do_always_noconv() const noexcept +{ + return false; +} + +int +codecvt<char32_t, char8_t, mbstate_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf8_to_ucs4_length(_frm, _frm_end, mx); +} + +int +codecvt<char32_t, char8_t, mbstate_t>::do_max_length() const noexcept +{ + return 4; +} + +#endif + +// __codecvt_utf8<wchar_t> + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +__codecvt_utf8<wchar_t>::result +__codecvt_utf8<wchar_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +#if defined(_LIBCPP_SHORT_WCHAR) + const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); + const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); + const uint16_t* _frm_nxt = _frm; +#else + const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); + const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); + const uint32_t* _frm_nxt = _frm; +#endif + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; +#if defined(_LIBCPP_SHORT_WCHAR) + result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#else + result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#endif + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8<wchar_t>::result +__codecvt_utf8<wchar_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; +#if defined(_LIBCPP_SHORT_WCHAR) + uint16_t* _to = reinterpret_cast<uint16_t*>(to); + uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); + uint16_t* _to_nxt = _to; + result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#else + uint32_t* _to = reinterpret_cast<uint32_t*>(to); + uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); + uint32_t* _to_nxt = _to; + result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#endif + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8<wchar_t>::result +__codecvt_utf8<wchar_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf8<wchar_t>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf8<wchar_t>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf8<wchar_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +#if defined(_LIBCPP_SHORT_WCHAR) + return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +#else + return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +#endif +} + +int +__codecvt_utf8<wchar_t>::do_max_length() const noexcept +{ +#if defined(_LIBCPP_SHORT_WCHAR) + if (_Mode_ & consume_header) + return 6; + return 3; +#else + if (_Mode_ & consume_header) + return 7; + return 4; +#endif +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// __codecvt_utf8<char16_t> + +__codecvt_utf8<char16_t>::result +__codecvt_utf8<char16_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); + const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); + const uint16_t* _frm_nxt = _frm; + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8<char16_t>::result +__codecvt_utf8<char16_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; + uint16_t* _to = reinterpret_cast<uint16_t*>(to); + uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); + uint16_t* _to_nxt = _to; + result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8<char16_t>::result +__codecvt_utf8<char16_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf8<char16_t>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf8<char16_t>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf8<char16_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf8<char16_t>::do_max_length() const noexcept +{ + if (_Mode_ & consume_header) + return 6; + return 3; +} + +// __codecvt_utf8<char32_t> + +__codecvt_utf8<char32_t>::result +__codecvt_utf8<char32_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); + const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); + const uint32_t* _frm_nxt = _frm; + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8<char32_t>::result +__codecvt_utf8<char32_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; + uint32_t* _to = reinterpret_cast<uint32_t*>(to); + uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); + uint32_t* _to_nxt = _to; + result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8<char32_t>::result +__codecvt_utf8<char32_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf8<char32_t>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf8<char32_t>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf8<char32_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf8<char32_t>::do_max_length() const noexcept +{ + if (_Mode_ & consume_header) + return 7; + return 4; +} + +// __codecvt_utf16<wchar_t, false> + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +__codecvt_utf16<wchar_t, false>::result +__codecvt_utf16<wchar_t, false>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +#if defined(_LIBCPP_SHORT_WCHAR) + const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); + const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); + const uint16_t* _frm_nxt = _frm; +#else + const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); + const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); + const uint32_t* _frm_nxt = _frm; +#endif + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; +#if defined(_LIBCPP_SHORT_WCHAR) + result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#else + result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#endif + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<wchar_t, false>::result +__codecvt_utf16<wchar_t, false>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; +#if defined(_LIBCPP_SHORT_WCHAR) + uint16_t* _to = reinterpret_cast<uint16_t*>(to); + uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); + uint16_t* _to_nxt = _to; + result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#else + uint32_t* _to = reinterpret_cast<uint32_t*>(to); + uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); + uint32_t* _to_nxt = _to; + result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#endif + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<wchar_t, false>::result +__codecvt_utf16<wchar_t, false>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf16<wchar_t, false>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf16<wchar_t, false>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf16<wchar_t, false>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +#if defined(_LIBCPP_SHORT_WCHAR) + return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +#else + return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +#endif +} + +int +__codecvt_utf16<wchar_t, false>::do_max_length() const noexcept +{ +#if defined(_LIBCPP_SHORT_WCHAR) + if (_Mode_ & consume_header) + return 4; + return 2; +#else + if (_Mode_ & consume_header) + return 6; + return 4; +#endif +} + +// __codecvt_utf16<wchar_t, true> + +__codecvt_utf16<wchar_t, true>::result +__codecvt_utf16<wchar_t, true>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +#if defined(_LIBCPP_SHORT_WCHAR) + const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); + const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); + const uint16_t* _frm_nxt = _frm; +#else + const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); + const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); + const uint32_t* _frm_nxt = _frm; +#endif + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; +#if defined(_LIBCPP_SHORT_WCHAR) + result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#else + result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#endif + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<wchar_t, true>::result +__codecvt_utf16<wchar_t, true>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; +#if defined(_LIBCPP_SHORT_WCHAR) + uint16_t* _to = reinterpret_cast<uint16_t*>(to); + uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); + uint16_t* _to_nxt = _to; + result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#else + uint32_t* _to = reinterpret_cast<uint32_t*>(to); + uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); + uint32_t* _to_nxt = _to; + result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#endif + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<wchar_t, true>::result +__codecvt_utf16<wchar_t, true>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf16<wchar_t, true>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf16<wchar_t, true>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf16<wchar_t, true>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +#if defined(_LIBCPP_SHORT_WCHAR) + return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +#else + return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +#endif +} + +int +__codecvt_utf16<wchar_t, true>::do_max_length() const noexcept +{ +#if defined(_LIBCPP_SHORT_WCHAR) + if (_Mode_ & consume_header) + return 4; + return 2; +#else + if (_Mode_ & consume_header) + return 6; + return 4; +#endif +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// __codecvt_utf16<char16_t, false> + +__codecvt_utf16<char16_t, false>::result +__codecvt_utf16<char16_t, false>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); + const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); + const uint16_t* _frm_nxt = _frm; + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<char16_t, false>::result +__codecvt_utf16<char16_t, false>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; + uint16_t* _to = reinterpret_cast<uint16_t*>(to); + uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); + uint16_t* _to_nxt = _to; + result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<char16_t, false>::result +__codecvt_utf16<char16_t, false>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf16<char16_t, false>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf16<char16_t, false>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf16<char16_t, false>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf16<char16_t, false>::do_max_length() const noexcept +{ + if (_Mode_ & consume_header) + return 4; + return 2; +} + +// __codecvt_utf16<char16_t, true> + +__codecvt_utf16<char16_t, true>::result +__codecvt_utf16<char16_t, true>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); + const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); + const uint16_t* _frm_nxt = _frm; + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<char16_t, true>::result +__codecvt_utf16<char16_t, true>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; + uint16_t* _to = reinterpret_cast<uint16_t*>(to); + uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); + uint16_t* _to_nxt = _to; + result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<char16_t, true>::result +__codecvt_utf16<char16_t, true>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf16<char16_t, true>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf16<char16_t, true>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf16<char16_t, true>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf16<char16_t, true>::do_max_length() const noexcept +{ + if (_Mode_ & consume_header) + return 4; + return 2; +} + +// __codecvt_utf16<char32_t, false> + +__codecvt_utf16<char32_t, false>::result +__codecvt_utf16<char32_t, false>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); + const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); + const uint32_t* _frm_nxt = _frm; + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<char32_t, false>::result +__codecvt_utf16<char32_t, false>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; + uint32_t* _to = reinterpret_cast<uint32_t*>(to); + uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); + uint32_t* _to_nxt = _to; + result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<char32_t, false>::result +__codecvt_utf16<char32_t, false>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf16<char32_t, false>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf16<char32_t, false>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf16<char32_t, false>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf16<char32_t, false>::do_max_length() const noexcept +{ + if (_Mode_ & consume_header) + return 6; + return 4; +} + +// __codecvt_utf16<char32_t, true> + +__codecvt_utf16<char32_t, true>::result +__codecvt_utf16<char32_t, true>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +#if defined(_LIBCPP_SHORT_WCHAR) + const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); + const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); + const uint16_t* _frm_nxt = _frm; +#else + const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); + const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); + const uint32_t* _frm_nxt = _frm; +#endif + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; +#if defined(_LIBCPP_SHORT_WCHAR) + result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#else + result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); +#endif + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<char32_t, true>::result +__codecvt_utf16<char32_t, true>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; + uint32_t* _to = reinterpret_cast<uint32_t*>(to); + uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); + uint32_t* _to_nxt = _to; + result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf16<char32_t, true>::result +__codecvt_utf16<char32_t, true>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf16<char32_t, true>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf16<char32_t, true>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf16<char32_t, true>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf16<char32_t, true>::do_max_length() const noexcept +{ + if (_Mode_ & consume_header) + return 6; + return 4; +} + +// __codecvt_utf8_utf16<wchar_t> + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +__codecvt_utf8_utf16<wchar_t>::result +__codecvt_utf8_utf16<wchar_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +#ifdef _WIN32 + const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); + const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); + const uint16_t* _frm_nxt = _frm; +#else + const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); + const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); + const uint32_t* _frm_nxt = _frm; +#endif + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8_utf16<wchar_t>::result +__codecvt_utf8_utf16<wchar_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; +#ifdef _WIN32 + uint16_t* _to = reinterpret_cast<uint16_t*>(to); + uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); + uint16_t* _to_nxt = _to; +#else + uint32_t* _to = reinterpret_cast<uint32_t*>(to); + uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); + uint32_t* _to_nxt = _to; +#endif + result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8_utf16<wchar_t>::result +__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf8_utf16<wchar_t>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf8_utf16<wchar_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf8_utf16<wchar_t>::do_max_length() const noexcept +{ + if (_Mode_ & consume_header) + return 7; + return 4; +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// __codecvt_utf8_utf16<char16_t> + +__codecvt_utf8_utf16<char16_t>::result +__codecvt_utf8_utf16<char16_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); + const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); + const uint16_t* _frm_nxt = _frm; + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8_utf16<char16_t>::result +__codecvt_utf8_utf16<char16_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; + uint16_t* _to = reinterpret_cast<uint16_t*>(to); + uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); + uint16_t* _to_nxt = _to; + result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8_utf16<char16_t>::result +__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf8_utf16<char16_t>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf8_utf16<char16_t>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf8_utf16<char16_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf8_utf16<char16_t>::do_max_length() const noexcept +{ + if (_Mode_ & consume_header) + return 7; + return 4; +} + +// __codecvt_utf8_utf16<char32_t> + +__codecvt_utf8_utf16<char32_t>::result +__codecvt_utf8_utf16<char32_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); + const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); + const uint32_t* _frm_nxt = _frm; + uint8_t* _to = reinterpret_cast<uint8_t*>(to); + uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); + uint8_t* _to_nxt = _to; + result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8_utf16<char32_t>::result +__codecvt_utf8_utf16<char32_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + const uint8_t* _frm_nxt = _frm; +#if defined(_LIBCPP_SHORT_WCHAR) + uint16_t* _to = reinterpret_cast<uint16_t*>(to); + uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); + uint16_t* _to_nxt = _to; +#else + uint32_t* _to = reinterpret_cast<uint32_t*>(to); + uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); + uint32_t* _to_nxt = _to; +#endif + result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, + _Maxcode_, _Mode_); + frm_nxt = frm + (_frm_nxt - _frm); + to_nxt = to + (_to_nxt - _to); + return r; +} + +__codecvt_utf8_utf16<char32_t>::result +__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +__codecvt_utf8_utf16<char32_t>::do_encoding() const noexcept +{ + return 0; +} + +bool +__codecvt_utf8_utf16<char32_t>::do_always_noconv() const noexcept +{ + return false; +} + +int +__codecvt_utf8_utf16<char32_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); + const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); + return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf8_utf16<char32_t>::do_max_length() const noexcept +{ + if (_Mode_ & consume_header) + return 7; + return 4; +} + +// __narrow_to_utf8<16> + +__narrow_to_utf8<16>::~__narrow_to_utf8() +{ +} + +// __narrow_to_utf8<32> + +__narrow_to_utf8<32>::~__narrow_to_utf8() +{ +} + +// __widen_from_utf8<16> + +__widen_from_utf8<16>::~__widen_from_utf8() +{ +} + +// __widen_from_utf8<32> + +__widen_from_utf8<32>::~__widen_from_utf8() +{ +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +static bool checked_string_to_wchar_convert(wchar_t& dest, + const char* ptr, + locale_t loc) { + if (*ptr == '\0') + return false; + mbstate_t mb = {}; + wchar_t out; + size_t ret = __libcpp_mbrtowc_l(&out, ptr, strlen(ptr), &mb, loc); + if (ret == static_cast<size_t>(-1) || ret == static_cast<size_t>(-2)) { + return false; + } + dest = out; + return true; +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +static bool checked_string_to_char_convert(char& dest, + const char* ptr, + locale_t __loc) { + if (*ptr == '\0') + return false; + if (!ptr[1]) { + dest = *ptr; + return true; + } + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + // First convert the MBS into a wide char then attempt to narrow it using + // wctob_l. + wchar_t wout; + if (!checked_string_to_wchar_convert(wout, ptr, __loc)) + return false; + int res; + if ((res = __libcpp_wctob_l(wout, __loc)) != char_traits<char>::eof()) { + dest = res; + return true; + } + // FIXME: Work around specific multibyte sequences that we can reasonably + // translate into a different single byte. + switch (wout) { + case L'\u202F': // narrow non-breaking space + case L'\u00A0': // non-breaking space + dest = ' '; + return true; + default: + return false; + } +#else // _LIBCPP_HAS_NO_WIDE_CHARACTERS + return false; +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + _LIBCPP_UNREACHABLE(); +} + + +// numpunct<char> && numpunct<wchar_t> + +locale::id numpunct< char >::id; +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +locale::id numpunct<wchar_t>::id; +#endif + +numpunct<char>::numpunct(size_t refs) + : locale::facet(refs), + __decimal_point_('.'), + __thousands_sep_(',') +{ +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +numpunct<wchar_t>::numpunct(size_t refs) + : locale::facet(refs), + __decimal_point_(L'.'), + __thousands_sep_(L',') +{ +} +#endif + +numpunct<char>::~numpunct() +{ +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +numpunct<wchar_t>::~numpunct() +{ +} +#endif + + char numpunct< char >::do_decimal_point() const {return __decimal_point_;} +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;} +#endif + + char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;} +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;} +#endif + +string numpunct< char >::do_grouping() const {return __grouping_;} +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +string numpunct<wchar_t>::do_grouping() const {return __grouping_;} +#endif + + string numpunct< char >::do_truename() const {return "true";} +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +wstring numpunct<wchar_t>::do_truename() const {return L"true";} +#endif + + string numpunct< char >::do_falsename() const {return "false";} +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +wstring numpunct<wchar_t>::do_falsename() const {return L"false";} +#endif + +// numpunct_byname<char> + +numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs) + : numpunct<char>(refs) +{ + __init(nm); +} + +numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs) + : numpunct<char>(refs) +{ + __init(nm.c_str()); +} + +numpunct_byname<char>::~numpunct_byname() +{ +} + +void +numpunct_byname<char>::__init(const char* nm) +{ + typedef numpunct<char> base; + if (strcmp(nm, "C") != 0) + { + __libcpp_unique_locale loc(nm); + if (!loc) + __throw_runtime_error("numpunct_byname<char>::numpunct_byname" + " failed to construct for " + string(nm)); + + lconv* lc = __libcpp_localeconv_l(loc.get()); + if (!checked_string_to_char_convert(__decimal_point_, lc->decimal_point, + loc.get())) + __decimal_point_ = base::do_decimal_point(); + if (!checked_string_to_char_convert(__thousands_sep_, lc->thousands_sep, + loc.get())) + __thousands_sep_ = base::do_thousands_sep(); + __grouping_ = lc->grouping; + // localization for truename and falsename is not available + } +} + +// numpunct_byname<wchar_t> + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs) + : numpunct<wchar_t>(refs) +{ + __init(nm); +} + +numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs) + : numpunct<wchar_t>(refs) +{ + __init(nm.c_str()); +} + +numpunct_byname<wchar_t>::~numpunct_byname() +{ +} + +void +numpunct_byname<wchar_t>::__init(const char* nm) +{ + if (strcmp(nm, "C") != 0) + { + __libcpp_unique_locale loc(nm); + if (!loc) + __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname" + " failed to construct for " + string(nm)); + + lconv* lc = __libcpp_localeconv_l(loc.get()); + checked_string_to_wchar_convert(__decimal_point_, lc->decimal_point, + loc.get()); + checked_string_to_wchar_convert(__thousands_sep_, lc->thousands_sep, + loc.get()); + __grouping_ = lc->grouping; + // localization for truename and falsename is not available + } +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// num_get helpers + +int +__num_get_base::__get_base(ios_base& iob) +{ + ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield; + if (__basefield == ios_base::oct) + return 8; + else if (__basefield == ios_base::hex) + return 16; + else if (__basefield == 0) + return 0; + return 10; +} + +const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN"; + +void +__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, + ios_base::iostate& __err) +{ +// if the grouping pattern is empty _or_ there are no grouping bits, then do nothing +// we always have at least a single entry in [__g, __g_end); the end of the input sequence if (__grouping.size() != 0 && __g_end - __g > 1) - { - reverse(__g, __g_end); - const char* __ig = __grouping.data(); - const char* __eg = __ig + __grouping.size(); - for (unsigned* __r = __g; __r < __g_end-1; ++__r) - { - if (0 < *__ig && *__ig < numeric_limits<char>::max()) - { - if (static_cast<unsigned>(*__ig) != *__r) - { - __err = ios_base::failbit; - return; - } - } - if (__eg - __ig > 1) - ++__ig; - } - if (0 < *__ig && *__ig < numeric_limits<char>::max()) - { - if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0) - __err = ios_base::failbit; - } - } -} - -void -__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd, - ios_base::fmtflags __flags) -{ - if ((__flags & ios_base::showpos) && - (__flags & ios_base::basefield) != ios_base::oct && - (__flags & ios_base::basefield) != ios_base::hex && - __signd) - *__fmtp++ = '+'; - if (__flags & ios_base::showbase) - *__fmtp++ = '#'; - while(*__len) - *__fmtp++ = *__len++; - if ((__flags & ios_base::basefield) == ios_base::oct) - *__fmtp = 'o'; - else if ((__flags & ios_base::basefield) == ios_base::hex) - { - if (__flags & ios_base::uppercase) - *__fmtp = 'X'; - else - *__fmtp = 'x'; - } - else if (__signd) - *__fmtp = 'd'; - else - *__fmtp = 'u'; -} - -bool -__num_put_base::__format_float(char* __fmtp, const char* __len, - ios_base::fmtflags __flags) -{ - bool specify_precision = true; - if (__flags & ios_base::showpos) - *__fmtp++ = '+'; - if (__flags & ios_base::showpoint) - *__fmtp++ = '#'; - ios_base::fmtflags floatfield = __flags & ios_base::floatfield; - bool uppercase = (__flags & ios_base::uppercase) != 0; - if (floatfield == (ios_base::fixed | ios_base::scientific)) - specify_precision = false; - else - { - *__fmtp++ = '.'; - *__fmtp++ = '*'; - } - while(*__len) - *__fmtp++ = *__len++; - if (floatfield == ios_base::fixed) - { - if (uppercase) - *__fmtp = 'F'; - else - *__fmtp = 'f'; - } - else if (floatfield == ios_base::scientific) - { - if (uppercase) - *__fmtp = 'E'; - else - *__fmtp = 'e'; - } - else if (floatfield == (ios_base::fixed | ios_base::scientific)) - { - if (uppercase) - *__fmtp = 'A'; - else - *__fmtp = 'a'; - } - else - { - if (uppercase) - *__fmtp = 'G'; - else - *__fmtp = 'g'; - } - return specify_precision; -} - -char* -__num_put_base::__identify_padding(char* __nb, char* __ne, - const ios_base& __iob) -{ - switch (__iob.flags() & ios_base::adjustfield) - { - case ios_base::internal: - if (__nb[0] == '-' || __nb[0] == '+') - return __nb+1; - if (__ne - __nb >= 2 && __nb[0] == '0' - && (__nb[1] == 'x' || __nb[1] == 'X')) - return __nb+2; - break; - case ios_base::left: - return __ne; - case ios_base::right: - default: - break; - } - return __nb; -} - -// time_get - -static -string* -init_weeks() -{ - static string weeks[14]; - weeks[0] = "Sunday"; - weeks[1] = "Monday"; - weeks[2] = "Tuesday"; - weeks[3] = "Wednesday"; - weeks[4] = "Thursday"; - weeks[5] = "Friday"; - weeks[6] = "Saturday"; - weeks[7] = "Sun"; - weeks[8] = "Mon"; - weeks[9] = "Tue"; - weeks[10] = "Wed"; - weeks[11] = "Thu"; - weeks[12] = "Fri"; - weeks[13] = "Sat"; - return weeks; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -static -wstring* -init_wweeks() -{ - static wstring weeks[14]; - weeks[0] = L"Sunday"; - weeks[1] = L"Monday"; - weeks[2] = L"Tuesday"; - weeks[3] = L"Wednesday"; - weeks[4] = L"Thursday"; - weeks[5] = L"Friday"; - weeks[6] = L"Saturday"; - weeks[7] = L"Sun"; - weeks[8] = L"Mon"; - weeks[9] = L"Tue"; - weeks[10] = L"Wed"; - weeks[11] = L"Thu"; - weeks[12] = L"Fri"; - weeks[13] = L"Sat"; - return weeks; -} -#endif - -template <> -const string* -__time_get_c_storage<char>::__weeks() const -{ - static const string* weeks = init_weeks(); - return weeks; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -const wstring* -__time_get_c_storage<wchar_t>::__weeks() const -{ - static const wstring* weeks = init_wweeks(); - return weeks; -} -#endif - -static -string* -init_months() -{ - static string months[24]; - months[0] = "January"; - months[1] = "February"; - months[2] = "March"; - months[3] = "April"; - months[4] = "May"; - months[5] = "June"; - months[6] = "July"; - months[7] = "August"; - months[8] = "September"; - months[9] = "October"; - months[10] = "November"; - months[11] = "December"; - months[12] = "Jan"; - months[13] = "Feb"; - months[14] = "Mar"; - months[15] = "Apr"; - months[16] = "May"; - months[17] = "Jun"; - months[18] = "Jul"; - months[19] = "Aug"; - months[20] = "Sep"; - months[21] = "Oct"; - months[22] = "Nov"; - months[23] = "Dec"; - return months; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -static -wstring* -init_wmonths() -{ - static wstring months[24]; - months[0] = L"January"; - months[1] = L"February"; - months[2] = L"March"; - months[3] = L"April"; - months[4] = L"May"; - months[5] = L"June"; - months[6] = L"July"; - months[7] = L"August"; - months[8] = L"September"; - months[9] = L"October"; - months[10] = L"November"; - months[11] = L"December"; - months[12] = L"Jan"; - months[13] = L"Feb"; - months[14] = L"Mar"; - months[15] = L"Apr"; - months[16] = L"May"; - months[17] = L"Jun"; - months[18] = L"Jul"; - months[19] = L"Aug"; - months[20] = L"Sep"; - months[21] = L"Oct"; - months[22] = L"Nov"; - months[23] = L"Dec"; - return months; -} -#endif - -template <> -const string* -__time_get_c_storage<char>::__months() const -{ - static const string* months = init_months(); - return months; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -const wstring* -__time_get_c_storage<wchar_t>::__months() const -{ - static const wstring* months = init_wmonths(); - return months; -} -#endif - -static -string* -init_am_pm() -{ - static string am_pm[2]; - am_pm[0] = "AM"; - am_pm[1] = "PM"; - return am_pm; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -static -wstring* -init_wam_pm() -{ - static wstring am_pm[2]; - am_pm[0] = L"AM"; - am_pm[1] = L"PM"; - return am_pm; -} -#endif - -template <> -const string* -__time_get_c_storage<char>::__am_pm() const -{ - static const string* am_pm = init_am_pm(); - return am_pm; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -const wstring* -__time_get_c_storage<wchar_t>::__am_pm() const -{ - static const wstring* am_pm = init_wam_pm(); - return am_pm; -} -#endif - -template <> -const string& -__time_get_c_storage<char>::__x() const -{ - static string s("%m/%d/%y"); - return s; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -const wstring& -__time_get_c_storage<wchar_t>::__x() const -{ - static wstring s(L"%m/%d/%y"); - return s; -} -#endif - -template <> -const string& -__time_get_c_storage<char>::__X() const -{ - static string s("%H:%M:%S"); - return s; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -const wstring& -__time_get_c_storage<wchar_t>::__X() const -{ - static wstring s(L"%H:%M:%S"); - return s; -} -#endif - -template <> -const string& -__time_get_c_storage<char>::__c() const -{ - static string s("%a %b %d %H:%M:%S %Y"); - return s; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -const wstring& -__time_get_c_storage<wchar_t>::__c() const -{ - static wstring s(L"%a %b %d %H:%M:%S %Y"); - return s; -} -#endif - -template <> -const string& -__time_get_c_storage<char>::__r() const -{ - static string s("%I:%M:%S %p"); - return s; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -const wstring& -__time_get_c_storage<wchar_t>::__r() const -{ - static wstring s(L"%I:%M:%S %p"); - return s; -} -#endif - -// time_get_byname - -__time_get::__time_get(const char* nm) - : __loc_(newlocale(LC_ALL_MASK, nm, 0)) -{ - if (__loc_ == 0) - __throw_runtime_error("time_get_byname" - " failed to construct for " + string(nm)); -} - -__time_get::__time_get(const string& nm) - : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) -{ - if (__loc_ == 0) - __throw_runtime_error("time_get_byname" - " failed to construct for " + nm); -} - -__time_get::~__time_get() -{ - freelocale(__loc_); -} -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wmissing-field-initializers" -#endif -#if defined(__GNUG__) -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif - -template <> -string -__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct) -{ - tm t = {0}; - t.tm_sec = 59; - t.tm_min = 55; - t.tm_hour = 23; - t.tm_mday = 31; - t.tm_mon = 11; - t.tm_year = 161; - t.tm_wday = 6; - t.tm_yday = 364; - t.tm_isdst = -1; - char buf[100]; - char f[3] = {0}; - f[0] = '%'; - f[1] = fmt; - size_t n = strftime_l(buf, countof(buf), f, &t, __loc_); - char* bb = buf; - char* be = buf + n; - string result; - while (bb != be) - { - if (ct.is(ctype_base::space, *bb)) - { - result.push_back(' '); - for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb) - ; - continue; - } - char* w = bb; - ios_base::iostate err = ios_base::goodbit; - ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14, - ct, err, false) - - this->__weeks_; - if (i < 14) - { - result.push_back('%'); - if (i < 7) - result.push_back('A'); - else - result.push_back('a'); - bb = w; - continue; - } - w = bb; - i = __scan_keyword(w, be, this->__months_, this->__months_+24, - ct, err, false) - - this->__months_; - if (i < 24) - { - result.push_back('%'); - if (i < 12) - result.push_back('B'); - else - result.push_back('b'); - if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) - result.back() = 'm'; - bb = w; - continue; - } - if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) - { - w = bb; - i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2, - ct, err, false) - this->__am_pm_; - if (i < 2) - { - result.push_back('%'); - result.push_back('p'); - bb = w; - continue; - } - } - w = bb; - if (ct.is(ctype_base::digit, *bb)) - { - switch(__get_up_to_n_digits(bb, be, err, ct, 4)) - { - case 6: - result.push_back('%'); - result.push_back('w'); - break; - case 7: - result.push_back('%'); - result.push_back('u'); - break; - case 11: - result.push_back('%'); - result.push_back('I'); - break; - case 12: - result.push_back('%'); - result.push_back('m'); - break; - case 23: - result.push_back('%'); - result.push_back('H'); - break; - case 31: - result.push_back('%'); - result.push_back('d'); - break; - case 55: - result.push_back('%'); - result.push_back('M'); - break; - case 59: - result.push_back('%'); - result.push_back('S'); - break; - case 61: - result.push_back('%'); - result.push_back('y'); - break; - case 364: - result.push_back('%'); - result.push_back('j'); - break; - case 2061: - result.push_back('%'); - result.push_back('Y'); - break; - default: - for (; w != bb; ++w) - result.push_back(*w); - break; - } - continue; - } - if (*bb == '%') - { - result.push_back('%'); - result.push_back('%'); - ++bb; - continue; - } - result.push_back(*bb); - ++bb; - } - return result; -} - -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wmissing-braces" -#endif - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -wstring -__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct) -{ - tm t = {0}; - t.tm_sec = 59; - t.tm_min = 55; - t.tm_hour = 23; - t.tm_mday = 31; - t.tm_mon = 11; - t.tm_year = 161; - t.tm_wday = 6; - t.tm_yday = 364; - t.tm_isdst = -1; - char buf[100]; - char f[3] = {0}; - f[0] = '%'; - f[1] = fmt; - strftime_l(buf, countof(buf), f, &t, __loc_); - wchar_t wbuf[100]; - wchar_t* wbb = wbuf; - mbstate_t mb = {0}; - const char* bb = buf; - size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_); - if (j == size_t(-1)) - __throw_runtime_error("locale not supported"); - wchar_t* wbe = wbb + j; - wstring result; - while (wbb != wbe) - { - if (ct.is(ctype_base::space, *wbb)) - { - result.push_back(L' '); - for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb) - ; - continue; - } - wchar_t* w = wbb; - ios_base::iostate err = ios_base::goodbit; - ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14, - ct, err, false) - - this->__weeks_; - if (i < 14) - { - result.push_back(L'%'); - if (i < 7) - result.push_back(L'A'); - else - result.push_back(L'a'); - wbb = w; - continue; - } - w = wbb; - i = __scan_keyword(w, wbe, this->__months_, this->__months_+24, - ct, err, false) - - this->__months_; - if (i < 24) - { - result.push_back(L'%'); - if (i < 12) - result.push_back(L'B'); - else - result.push_back(L'b'); - if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) - result.back() = L'm'; - wbb = w; - continue; - } - if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) - { - w = wbb; - i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2, - ct, err, false) - this->__am_pm_; - if (i < 2) - { - result.push_back(L'%'); - result.push_back(L'p'); - wbb = w; - continue; - } - } - w = wbb; - if (ct.is(ctype_base::digit, *wbb)) - { - switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4)) - { - case 6: - result.push_back(L'%'); - result.push_back(L'w'); - break; - case 7: - result.push_back(L'%'); - result.push_back(L'u'); - break; - case 11: - result.push_back(L'%'); - result.push_back(L'I'); - break; - case 12: - result.push_back(L'%'); - result.push_back(L'm'); - break; - case 23: - result.push_back(L'%'); - result.push_back(L'H'); - break; - case 31: - result.push_back(L'%'); - result.push_back(L'd'); - break; - case 55: - result.push_back(L'%'); - result.push_back(L'M'); - break; - case 59: - result.push_back(L'%'); - result.push_back(L'S'); - break; - case 61: - result.push_back(L'%'); - result.push_back(L'y'); - break; - case 364: - result.push_back(L'%'); - result.push_back(L'j'); - break; - case 2061: - result.push_back(L'%'); - result.push_back(L'Y'); - break; - default: - for (; w != wbb; ++w) - result.push_back(*w); - break; - } - continue; - } - if (ct.narrow(*wbb, 0) == '%') - { - result.push_back(L'%'); - result.push_back(L'%'); - ++wbb; - continue; - } - result.push_back(*wbb); - ++wbb; - } - return result; -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -template <> -void -__time_get_storage<char>::init(const ctype<char>& ct) -{ - tm t = {0}; - char buf[100]; - // __weeks_ - for (int i = 0; i < 7; ++i) - { - t.tm_wday = i; - strftime_l(buf, countof(buf), "%A", &t, __loc_); - __weeks_[i] = buf; - strftime_l(buf, countof(buf), "%a", &t, __loc_); - __weeks_[i+7] = buf; - } - // __months_ - for (int i = 0; i < 12; ++i) - { - t.tm_mon = i; - strftime_l(buf, countof(buf), "%B", &t, __loc_); - __months_[i] = buf; - strftime_l(buf, countof(buf), "%b", &t, __loc_); - __months_[i+12] = buf; - } - // __am_pm_ - t.tm_hour = 1; - strftime_l(buf, countof(buf), "%p", &t, __loc_); - __am_pm_[0] = buf; - t.tm_hour = 13; - strftime_l(buf, countof(buf), "%p", &t, __loc_); - __am_pm_[1] = buf; - __c_ = __analyze('c', ct); - __r_ = __analyze('r', ct); - __x_ = __analyze('x', ct); - __X_ = __analyze('X', ct); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -void -__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) -{ - tm t = {0}; - char buf[100]; - wchar_t wbuf[100]; - wchar_t* wbe; - mbstate_t mb = {0}; - // __weeks_ - for (int i = 0; i < 7; ++i) - { - t.tm_wday = i; - strftime_l(buf, countof(buf), "%A", &t, __loc_); - mb = mbstate_t(); - const char* bb = buf; - size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); - if (j == size_t(-1) || j == 0) - __throw_runtime_error("locale not supported"); - wbe = wbuf + j; - __weeks_[i].assign(wbuf, wbe); - strftime_l(buf, countof(buf), "%a", &t, __loc_); - mb = mbstate_t(); - bb = buf; - j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); - if (j == size_t(-1) || j == 0) - __throw_runtime_error("locale not supported"); - wbe = wbuf + j; - __weeks_[i+7].assign(wbuf, wbe); - } - // __months_ - for (int i = 0; i < 12; ++i) - { - t.tm_mon = i; - strftime_l(buf, countof(buf), "%B", &t, __loc_); - mb = mbstate_t(); - const char* bb = buf; - size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); - if (j == size_t(-1) || j == 0) - __throw_runtime_error("locale not supported"); - wbe = wbuf + j; - __months_[i].assign(wbuf, wbe); - strftime_l(buf, countof(buf), "%b", &t, __loc_); - mb = mbstate_t(); - bb = buf; - j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); - if (j == size_t(-1) || j == 0) - __throw_runtime_error("locale not supported"); - wbe = wbuf + j; - __months_[i+12].assign(wbuf, wbe); - } - // __am_pm_ - t.tm_hour = 1; - strftime_l(buf, countof(buf), "%p", &t, __loc_); - mb = mbstate_t(); - const char* bb = buf; - size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); - if (j == size_t(-1)) - __throw_runtime_error("locale not supported"); - wbe = wbuf + j; - __am_pm_[0].assign(wbuf, wbe); - t.tm_hour = 13; - strftime_l(buf, countof(buf), "%p", &t, __loc_); - mb = mbstate_t(); - bb = buf; - j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); - if (j == size_t(-1)) - __throw_runtime_error("locale not supported"); - wbe = wbuf + j; - __am_pm_[1].assign(wbuf, wbe); - __c_ = __analyze('c', ct); - __r_ = __analyze('r', ct); - __x_ = __analyze('x', ct); - __X_ = __analyze('X', ct); -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -template <class CharT> -struct _LIBCPP_HIDDEN __time_get_temp - : public ctype_byname<CharT> -{ - explicit __time_get_temp(const char* nm) - : ctype_byname<CharT>(nm, 1) {} - explicit __time_get_temp(const string& nm) - : ctype_byname<CharT>(nm, 1) {} -}; - -template <> -__time_get_storage<char>::__time_get_storage(const char* __nm) - : __time_get(__nm) -{ - const __time_get_temp<char> ct(__nm); - init(ct); -} - -template <> -__time_get_storage<char>::__time_get_storage(const string& __nm) - : __time_get(__nm) -{ - const __time_get_temp<char> ct(__nm); - init(ct); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -__time_get_storage<wchar_t>::__time_get_storage(const char* __nm) - : __time_get(__nm) -{ - const __time_get_temp<wchar_t> ct(__nm); - init(ct); -} - -template <> -__time_get_storage<wchar_t>::__time_get_storage(const string& __nm) - : __time_get(__nm) -{ - const __time_get_temp<wchar_t> ct(__nm); - init(ct); -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -template <> -time_base::dateorder -__time_get_storage<char>::__do_date_order() const -{ - unsigned i; - for (i = 0; i < __x_.size(); ++i) - if (__x_[i] == '%') - break; - ++i; - switch (__x_[i]) - { - case 'y': - case 'Y': - for (++i; i < __x_.size(); ++i) - if (__x_[i] == '%') - break; - if (i == __x_.size()) - break; - ++i; - switch (__x_[i]) - { - case 'm': - for (++i; i < __x_.size(); ++i) - if (__x_[i] == '%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == 'd') - return time_base::ymd; - break; - case 'd': - for (++i; i < __x_.size(); ++i) - if (__x_[i] == '%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == 'm') - return time_base::ydm; - break; - } - break; - case 'm': - for (++i; i < __x_.size(); ++i) - if (__x_[i] == '%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == 'd') - { - for (++i; i < __x_.size(); ++i) - if (__x_[i] == '%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == 'y' || __x_[i] == 'Y') - return time_base::mdy; - break; - } - break; - case 'd': - for (++i; i < __x_.size(); ++i) - if (__x_[i] == '%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == 'm') - { - for (++i; i < __x_.size(); ++i) - if (__x_[i] == '%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == 'y' || __x_[i] == 'Y') - return time_base::dmy; - break; - } - break; - } - return time_base::no_order; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -time_base::dateorder -__time_get_storage<wchar_t>::__do_date_order() const -{ - unsigned i; - for (i = 0; i < __x_.size(); ++i) - if (__x_[i] == L'%') - break; - ++i; - switch (__x_[i]) - { - case L'y': - case L'Y': - for (++i; i < __x_.size(); ++i) - if (__x_[i] == L'%') - break; - if (i == __x_.size()) - break; - ++i; - switch (__x_[i]) - { - case L'm': - for (++i; i < __x_.size(); ++i) - if (__x_[i] == L'%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == L'd') - return time_base::ymd; - break; - case L'd': - for (++i; i < __x_.size(); ++i) - if (__x_[i] == L'%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == L'm') - return time_base::ydm; - break; - } - break; - case L'm': - for (++i; i < __x_.size(); ++i) - if (__x_[i] == L'%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == L'd') - { - for (++i; i < __x_.size(); ++i) - if (__x_[i] == L'%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == L'y' || __x_[i] == L'Y') - return time_base::mdy; - break; - } - break; - case L'd': - for (++i; i < __x_.size(); ++i) - if (__x_[i] == L'%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == L'm') - { - for (++i; i < __x_.size(); ++i) - if (__x_[i] == L'%') - break; - if (i == __x_.size()) - break; - ++i; - if (__x_[i] == L'y' || __x_[i] == L'Y') - return time_base::dmy; - break; - } - break; - } - return time_base::no_order; -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -// time_put - -__time_put::__time_put(const char* nm) - : __loc_(newlocale(LC_ALL_MASK, nm, 0)) -{ - if (__loc_ == 0) - __throw_runtime_error("time_put_byname" - " failed to construct for " + string(nm)); -} - -__time_put::__time_put(const string& nm) - : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) -{ - if (__loc_ == 0) - __throw_runtime_error("time_put_byname" - " failed to construct for " + nm); -} - -__time_put::~__time_put() -{ - if (__loc_ != _LIBCPP_GET_C_LOCALE) - freelocale(__loc_); -} - -void -__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm, - char __fmt, char __mod) const -{ - char fmt[] = {'%', __fmt, __mod, 0}; - if (__mod != 0) - swap(fmt[1], fmt[2]); - size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_); - __ne = __nb + n; -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -void -__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, - char __fmt, char __mod) const -{ - char __nar[100]; - char* __ne = __nar + 100; - __do_put(__nar, __ne, __tm, __fmt, __mod); - mbstate_t mb = {0}; - const char* __nb = __nar; - size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_); - if (j == size_t(-1)) - __throw_runtime_error("locale not supported"); - __we = __wb + j; -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -// moneypunct_byname - -template <class charT> -static -void -__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_, - bool intl, char cs_precedes, char sep_by_space, char sign_posn, - charT space_char) -{ - const char sign = static_cast<char>(money_base::sign); - const char space = static_cast<char>(money_base::space); - const char none = static_cast<char>(money_base::none); - const char symbol = static_cast<char>(money_base::symbol); - const char value = static_cast<char>(money_base::value); - const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4; - - // Comments on case branches reflect 'C11 7.11.2.1 The localeconv - // function'. "Space between sign and symbol or value" means that - // if the sign is adjacent to the symbol, there's a space between - // them, and otherwise there's a space between the sign and value. - // - // C11's localeconv specifies that the fourth character of an - // international curr_symbol is used to separate the sign and - // value when sep_by_space says to do so. C++ can't represent - // that, so we just use a space. When sep_by_space says to - // separate the symbol and value-or-sign with a space, we rearrange the - // curr_symbol to put its spacing character on the correct side of - // the symbol. - // - // We also need to avoid adding an extra space between the sign - // and value when the currency symbol is suppressed (by not - // setting showbase). We match glibc's strfmon by interpreting - // sep_by_space==1 as "omit the space when the currency symbol is - // absent". - // - // Users who want to get this right should use ICU instead. - - switch (cs_precedes) - { - case 0: // value before curr_symbol - if (symbol_contains_sep) { - // Move the separator to before the symbol, to place it - // between the value and symbol. - rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3, - __curr_symbol_.end()); - } - switch (sign_posn) - { - case 0: // Parentheses surround the quantity and currency symbol. - pat.field[0] = sign; - pat.field[1] = value; - pat.field[2] = none; // Any space appears in the symbol. - pat.field[3] = symbol; - switch (sep_by_space) - { - case 0: // No space separates the currency symbol and value. - // This case may have changed between C99 and C11; - // assume the currency symbol matches the intention. - case 2: // Space between sign and currency or value. - // The "sign" is two parentheses, so no space here either. - return; - case 1: // Space between currency-and-sign or currency and value. - if (!symbol_contains_sep) { - // We insert the space into the symbol instead of - // setting pat.field[2]=space so that when - // showbase is not set, the space goes away too. - __curr_symbol_.insert((size_t)0, 1, space_char); - } - return; - default: - break; - } - break; - case 1: // The sign string precedes the quantity and currency symbol. - pat.field[0] = sign; - pat.field[3] = symbol; - switch (sep_by_space) - { - case 0: // No space separates the currency symbol and value. - pat.field[1] = value; - pat.field[2] = none; - return; - case 1: // Space between currency-and-sign or currency and value. - pat.field[1] = value; - pat.field[2] = none; - if (!symbol_contains_sep) { - // We insert the space into the symbol instead of - // setting pat.field[2]=space so that when - // showbase is not set, the space goes away too. - __curr_symbol_.insert((size_t)0, 1, space_char); - } - return; - case 2: // Space between sign and currency or value. - pat.field[1] = space; - pat.field[2] = value; - if (symbol_contains_sep) { - // Remove the separator from the symbol, since it - // has already appeared after the sign. - __curr_symbol_.erase(__curr_symbol_.begin()); - } - return; - default: - break; - } - break; - case 2: // The sign string succeeds the quantity and currency symbol. - pat.field[0] = value; - pat.field[3] = sign; - switch (sep_by_space) - { - case 0: // No space separates the currency symbol and value. - pat.field[1] = none; - pat.field[2] = symbol; - return; - case 1: // Space between currency-and-sign or currency and value. - if (!symbol_contains_sep) { - // We insert the space into the symbol instead of - // setting pat.field[1]=space so that when - // showbase is not set, the space goes away too. - __curr_symbol_.insert((size_t)0, 1, space_char); - } - pat.field[1] = none; - pat.field[2] = symbol; - return; - case 2: // Space between sign and currency or value. - pat.field[1] = symbol; - pat.field[2] = space; - if (symbol_contains_sep) { - // Remove the separator from the symbol, since it - // should not be removed if showbase is absent. - __curr_symbol_.erase(__curr_symbol_.begin()); - } - return; - default: - break; - } - break; - case 3: // The sign string immediately precedes the currency symbol. - pat.field[0] = value; - pat.field[3] = symbol; - switch (sep_by_space) - { - case 0: // No space separates the currency symbol and value. - pat.field[1] = none; - pat.field[2] = sign; - return; - case 1: // Space between currency-and-sign or currency and value. - pat.field[1] = space; - pat.field[2] = sign; - if (symbol_contains_sep) { - // Remove the separator from the symbol, since it - // has already appeared before the sign. - __curr_symbol_.erase(__curr_symbol_.begin()); - } - return; - case 2: // Space between sign and currency or value. - pat.field[1] = sign; - pat.field[2] = none; - if (!symbol_contains_sep) { - // We insert the space into the symbol instead of - // setting pat.field[2]=space so that when - // showbase is not set, the space goes away too. - __curr_symbol_.insert((size_t)0, 1, space_char); - } - return; - default: - break; - } - break; - case 4: // The sign string immediately succeeds the currency symbol. - pat.field[0] = value; - pat.field[3] = sign; - switch (sep_by_space) - { - case 0: // No space separates the currency symbol and value. - pat.field[1] = none; - pat.field[2] = symbol; - return; - case 1: // Space between currency-and-sign or currency and value. - pat.field[1] = none; - pat.field[2] = symbol; - if (!symbol_contains_sep) { - // We insert the space into the symbol instead of - // setting pat.field[1]=space so that when - // showbase is not set, the space goes away too. - __curr_symbol_.insert((size_t)0, 1, space_char); - } - return; - case 2: // Space between sign and currency or value. - pat.field[1] = symbol; - pat.field[2] = space; - if (symbol_contains_sep) { - // Remove the separator from the symbol, since it - // should not disappear when showbase is absent. - __curr_symbol_.erase(__curr_symbol_.begin()); - } - return; - default: - break; - } - break; - default: - break; - } - break; - case 1: // curr_symbol before value - switch (sign_posn) - { - case 0: // Parentheses surround the quantity and currency symbol. - pat.field[0] = sign; - pat.field[1] = symbol; - pat.field[2] = none; // Any space appears in the symbol. - pat.field[3] = value; - switch (sep_by_space) - { - case 0: // No space separates the currency symbol and value. - // This case may have changed between C99 and C11; - // assume the currency symbol matches the intention. - case 2: // Space between sign and currency or value. - // The "sign" is two parentheses, so no space here either. - return; - case 1: // Space between currency-and-sign or currency and value. - if (!symbol_contains_sep) { - // We insert the space into the symbol instead of - // setting pat.field[2]=space so that when - // showbase is not set, the space goes away too. - __curr_symbol_.insert((size_t)0, 1, space_char); - } - return; - default: - break; - } - break; - case 1: // The sign string precedes the quantity and currency symbol. - pat.field[0] = sign; - pat.field[3] = value; - switch (sep_by_space) - { - case 0: // No space separates the currency symbol and value. - pat.field[1] = symbol; - pat.field[2] = none; - return; - case 1: // Space between currency-and-sign or currency and value. - pat.field[1] = symbol; - pat.field[2] = none; - if (!symbol_contains_sep) { - // We insert the space into the symbol instead of - // setting pat.field[2]=space so that when - // showbase is not set, the space goes away too. - __curr_symbol_.push_back(space_char); - } - return; - case 2: // Space between sign and currency or value. - pat.field[1] = space; - pat.field[2] = symbol; - if (symbol_contains_sep) { - // Remove the separator from the symbol, since it - // has already appeared after the sign. - __curr_symbol_.pop_back(); - } - return; - default: - break; - } - break; - case 2: // The sign string succeeds the quantity and currency symbol. - pat.field[0] = symbol; - pat.field[3] = sign; - switch (sep_by_space) - { - case 0: // No space separates the currency symbol and value. - pat.field[1] = none; - pat.field[2] = value; - return; - case 1: // Space between currency-and-sign or currency and value. - pat.field[1] = none; - pat.field[2] = value; - if (!symbol_contains_sep) { - // We insert the space into the symbol instead of - // setting pat.field[1]=space so that when - // showbase is not set, the space goes away too. - __curr_symbol_.push_back(space_char); - } - return; - case 2: // Space between sign and currency or value. - pat.field[1] = value; - pat.field[2] = space; - if (symbol_contains_sep) { - // Remove the separator from the symbol, since it - // will appear before the sign. - __curr_symbol_.pop_back(); - } - return; - default: - break; - } - break; - case 3: // The sign string immediately precedes the currency symbol. - pat.field[0] = sign; - pat.field[3] = value; - switch (sep_by_space) - { - case 0: // No space separates the currency symbol and value. - pat.field[1] = symbol; - pat.field[2] = none; - return; - case 1: // Space between currency-and-sign or currency and value. - pat.field[1] = symbol; - pat.field[2] = none; - if (!symbol_contains_sep) { - // We insert the space into the symbol instead of - // setting pat.field[2]=space so that when - // showbase is not set, the space goes away too. - __curr_symbol_.push_back(space_char); - } - return; - case 2: // Space between sign and currency or value. - pat.field[1] = space; - pat.field[2] = symbol; - if (symbol_contains_sep) { - // Remove the separator from the symbol, since it - // has already appeared after the sign. - __curr_symbol_.pop_back(); - } - return; - default: - break; - } - break; - case 4: // The sign string immediately succeeds the currency symbol. - pat.field[0] = symbol; - pat.field[3] = value; - switch (sep_by_space) - { - case 0: // No space separates the currency symbol and value. - pat.field[1] = sign; - pat.field[2] = none; - return; - case 1: // Space between currency-and-sign or currency and value. - pat.field[1] = sign; - pat.field[2] = space; - if (symbol_contains_sep) { - // Remove the separator from the symbol, since it - // should not disappear when showbase is absent. - __curr_symbol_.pop_back(); - } - return; - case 2: // Space between sign and currency or value. - pat.field[1] = none; - pat.field[2] = sign; - if (!symbol_contains_sep) { - // We insert the space into the symbol instead of - // setting pat.field[1]=space so that when - // showbase is not set, the space goes away too. - __curr_symbol_.push_back(space_char); - } - return; - default: - break; - } - break; - default: - break; - } - break; - default: - break; - } - pat.field[0] = symbol; - pat.field[1] = sign; - pat.field[2] = none; - pat.field[3] = value; -} - -template<> -void -moneypunct_byname<char, false>::init(const char* nm) -{ - typedef moneypunct<char, false> base; - __libcpp_unique_locale loc(nm); - if (!loc) - __throw_runtime_error("moneypunct_byname" - " failed to construct for " + string(nm)); - - lconv* lc = __libcpp_localeconv_l(loc.get()); - if (!checked_string_to_char_convert(__decimal_point_, - lc->mon_decimal_point, - loc.get())) - __decimal_point_ = base::do_decimal_point(); - if (!checked_string_to_char_convert(__thousands_sep_, - lc->mon_thousands_sep, - loc.get())) - __thousands_sep_ = base::do_thousands_sep(); - - __grouping_ = lc->mon_grouping; - __curr_symbol_ = lc->currency_symbol; - if (lc->frac_digits != CHAR_MAX) - __frac_digits_ = lc->frac_digits; - else - __frac_digits_ = base::do_frac_digits(); - if (lc->p_sign_posn == 0) - __positive_sign_ = "()"; - else - __positive_sign_ = lc->positive_sign; - if (lc->n_sign_posn == 0) - __negative_sign_ = "()"; - else - __negative_sign_ = lc->negative_sign; - // Assume the positive and negative formats will want spaces in - // the same places in curr_symbol since there's no way to - // represent anything else. - string_type __dummy_curr_symbol = __curr_symbol_; - __init_pat(__pos_format_, __dummy_curr_symbol, false, - lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); - __init_pat(__neg_format_, __curr_symbol_, false, - lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); -} - -template<> -void -moneypunct_byname<char, true>::init(const char* nm) -{ - typedef moneypunct<char, true> base; - __libcpp_unique_locale loc(nm); - if (!loc) - __throw_runtime_error("moneypunct_byname" - " failed to construct for " + string(nm)); - - lconv* lc = __libcpp_localeconv_l(loc.get()); - if (!checked_string_to_char_convert(__decimal_point_, - lc->mon_decimal_point, - loc.get())) - __decimal_point_ = base::do_decimal_point(); - if (!checked_string_to_char_convert(__thousands_sep_, - lc->mon_thousands_sep, - loc.get())) - __thousands_sep_ = base::do_thousands_sep(); - __grouping_ = lc->mon_grouping; - __curr_symbol_ = lc->int_curr_symbol; - if (lc->int_frac_digits != CHAR_MAX) - __frac_digits_ = lc->int_frac_digits; - else - __frac_digits_ = base::do_frac_digits(); -#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) - if (lc->p_sign_posn == 0) -#else // _LIBCPP_MSVCRT - if (lc->int_p_sign_posn == 0) -#endif // !_LIBCPP_MSVCRT - __positive_sign_ = "()"; - else - __positive_sign_ = lc->positive_sign; -#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) - if(lc->n_sign_posn == 0) -#else // _LIBCPP_MSVCRT - if (lc->int_n_sign_posn == 0) -#endif // !_LIBCPP_MSVCRT - __negative_sign_ = "()"; - else - __negative_sign_ = lc->negative_sign; - // Assume the positive and negative formats will want spaces in - // the same places in curr_symbol since there's no way to - // represent anything else. - string_type __dummy_curr_symbol = __curr_symbol_; -#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) - __init_pat(__pos_format_, __dummy_curr_symbol, true, - lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); - __init_pat(__neg_format_, __curr_symbol_, true, - lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); -#else // _LIBCPP_MSVCRT - __init_pat(__pos_format_, __dummy_curr_symbol, true, - lc->int_p_cs_precedes, lc->int_p_sep_by_space, - lc->int_p_sign_posn, ' '); - __init_pat(__neg_format_, __curr_symbol_, true, - lc->int_n_cs_precedes, lc->int_n_sep_by_space, - lc->int_n_sign_posn, ' '); -#endif // !_LIBCPP_MSVCRT -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template<> -void -moneypunct_byname<wchar_t, false>::init(const char* nm) -{ - typedef moneypunct<wchar_t, false> base; - __libcpp_unique_locale loc(nm); - if (!loc) - __throw_runtime_error("moneypunct_byname" - " failed to construct for " + string(nm)); - lconv* lc = __libcpp_localeconv_l(loc.get()); - if (!checked_string_to_wchar_convert(__decimal_point_, - lc->mon_decimal_point, - loc.get())) - __decimal_point_ = base::do_decimal_point(); - if (!checked_string_to_wchar_convert(__thousands_sep_, - lc->mon_thousands_sep, - loc.get())) - __thousands_sep_ = base::do_thousands_sep(); - __grouping_ = lc->mon_grouping; - wchar_t wbuf[100]; - mbstate_t mb = {0}; - const char* bb = lc->currency_symbol; - size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); - if (j == size_t(-1)) - __throw_runtime_error("locale not supported"); - wchar_t* wbe = wbuf + j; - __curr_symbol_.assign(wbuf, wbe); - if (lc->frac_digits != CHAR_MAX) - __frac_digits_ = lc->frac_digits; - else - __frac_digits_ = base::do_frac_digits(); - if (lc->p_sign_posn == 0) - __positive_sign_ = L"()"; - else - { - mb = mbstate_t(); - bb = lc->positive_sign; - j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); - if (j == size_t(-1)) - __throw_runtime_error("locale not supported"); - wbe = wbuf + j; - __positive_sign_.assign(wbuf, wbe); - } - if (lc->n_sign_posn == 0) - __negative_sign_ = L"()"; - else - { - mb = mbstate_t(); - bb = lc->negative_sign; - j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); - if (j == size_t(-1)) - __throw_runtime_error("locale not supported"); - wbe = wbuf + j; - __negative_sign_.assign(wbuf, wbe); - } - // Assume the positive and negative formats will want spaces in - // the same places in curr_symbol since there's no way to - // represent anything else. - string_type __dummy_curr_symbol = __curr_symbol_; - __init_pat(__pos_format_, __dummy_curr_symbol, false, - lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); - __init_pat(__neg_format_, __curr_symbol_, false, - lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); -} - -template<> -void -moneypunct_byname<wchar_t, true>::init(const char* nm) -{ - typedef moneypunct<wchar_t, true> base; - __libcpp_unique_locale loc(nm); - if (!loc) - __throw_runtime_error("moneypunct_byname" - " failed to construct for " + string(nm)); - - lconv* lc = __libcpp_localeconv_l(loc.get()); - if (!checked_string_to_wchar_convert(__decimal_point_, - lc->mon_decimal_point, - loc.get())) - __decimal_point_ = base::do_decimal_point(); - if (!checked_string_to_wchar_convert(__thousands_sep_, - lc->mon_thousands_sep, - loc.get())) - __thousands_sep_ = base::do_thousands_sep(); - __grouping_ = lc->mon_grouping; - wchar_t wbuf[100]; - mbstate_t mb = {0}; - const char* bb = lc->int_curr_symbol; - size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); - if (j == size_t(-1)) - __throw_runtime_error("locale not supported"); - wchar_t* wbe = wbuf + j; - __curr_symbol_.assign(wbuf, wbe); - if (lc->int_frac_digits != CHAR_MAX) - __frac_digits_ = lc->int_frac_digits; - else - __frac_digits_ = base::do_frac_digits(); -#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) - if (lc->p_sign_posn == 0) -#else // _LIBCPP_MSVCRT - if (lc->int_p_sign_posn == 0) -#endif // !_LIBCPP_MSVCRT - __positive_sign_ = L"()"; - else - { - mb = mbstate_t(); - bb = lc->positive_sign; - j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); - if (j == size_t(-1)) - __throw_runtime_error("locale not supported"); - wbe = wbuf + j; - __positive_sign_.assign(wbuf, wbe); - } -#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) - if (lc->n_sign_posn == 0) -#else // _LIBCPP_MSVCRT - if (lc->int_n_sign_posn == 0) -#endif // !_LIBCPP_MSVCRT - __negative_sign_ = L"()"; - else - { - mb = mbstate_t(); - bb = lc->negative_sign; - j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); - if (j == size_t(-1)) - __throw_runtime_error("locale not supported"); - wbe = wbuf + j; - __negative_sign_.assign(wbuf, wbe); - } - // Assume the positive and negative formats will want spaces in - // the same places in curr_symbol since there's no way to - // represent anything else. - string_type __dummy_curr_symbol = __curr_symbol_; -#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) - __init_pat(__pos_format_, __dummy_curr_symbol, true, - lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); - __init_pat(__neg_format_, __curr_symbol_, true, - lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); -#else // _LIBCPP_MSVCRT - __init_pat(__pos_format_, __dummy_curr_symbol, true, - lc->int_p_cs_precedes, lc->int_p_sep_by_space, - lc->int_p_sign_posn, L' '); - __init_pat(__neg_format_, __curr_symbol_, true, - lc->int_n_cs_precedes, lc->int_n_sep_by_space, - lc->int_n_sign_posn, L' '); -#endif // !_LIBCPP_MSVCRT -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -void __do_nothing(void*) {} - -void __throw_runtime_error(const char* msg) -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - throw runtime_error(msg); -#else - (void)msg; - _VSTD::abort(); -#endif -} - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;) - - template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;) - - template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>; - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;) -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>; - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;) -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;) - - template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>; -_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;) -template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>; -template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>; -#ifndef _LIBCPP_HAS_NO_CHAR8_T -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>; -template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>; -#endif - -_LIBCPP_END_NAMESPACE_STD + { + reverse(__g, __g_end); + const char* __ig = __grouping.data(); + const char* __eg = __ig + __grouping.size(); + for (unsigned* __r = __g; __r < __g_end-1; ++__r) + { + if (0 < *__ig && *__ig < numeric_limits<char>::max()) + { + if (static_cast<unsigned>(*__ig) != *__r) + { + __err = ios_base::failbit; + return; + } + } + if (__eg - __ig > 1) + ++__ig; + } + if (0 < *__ig && *__ig < numeric_limits<char>::max()) + { + if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0) + __err = ios_base::failbit; + } + } +} + +void +__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd, + ios_base::fmtflags __flags) +{ + if ((__flags & ios_base::showpos) && + (__flags & ios_base::basefield) != ios_base::oct && + (__flags & ios_base::basefield) != ios_base::hex && + __signd) + *__fmtp++ = '+'; + if (__flags & ios_base::showbase) + *__fmtp++ = '#'; + while(*__len) + *__fmtp++ = *__len++; + if ((__flags & ios_base::basefield) == ios_base::oct) + *__fmtp = 'o'; + else if ((__flags & ios_base::basefield) == ios_base::hex) + { + if (__flags & ios_base::uppercase) + *__fmtp = 'X'; + else + *__fmtp = 'x'; + } + else if (__signd) + *__fmtp = 'd'; + else + *__fmtp = 'u'; +} + +bool +__num_put_base::__format_float(char* __fmtp, const char* __len, + ios_base::fmtflags __flags) +{ + bool specify_precision = true; + if (__flags & ios_base::showpos) + *__fmtp++ = '+'; + if (__flags & ios_base::showpoint) + *__fmtp++ = '#'; + ios_base::fmtflags floatfield = __flags & ios_base::floatfield; + bool uppercase = (__flags & ios_base::uppercase) != 0; + if (floatfield == (ios_base::fixed | ios_base::scientific)) + specify_precision = false; + else + { + *__fmtp++ = '.'; + *__fmtp++ = '*'; + } + while(*__len) + *__fmtp++ = *__len++; + if (floatfield == ios_base::fixed) + { + if (uppercase) + *__fmtp = 'F'; + else + *__fmtp = 'f'; + } + else if (floatfield == ios_base::scientific) + { + if (uppercase) + *__fmtp = 'E'; + else + *__fmtp = 'e'; + } + else if (floatfield == (ios_base::fixed | ios_base::scientific)) + { + if (uppercase) + *__fmtp = 'A'; + else + *__fmtp = 'a'; + } + else + { + if (uppercase) + *__fmtp = 'G'; + else + *__fmtp = 'g'; + } + return specify_precision; +} + +char* +__num_put_base::__identify_padding(char* __nb, char* __ne, + const ios_base& __iob) +{ + switch (__iob.flags() & ios_base::adjustfield) + { + case ios_base::internal: + if (__nb[0] == '-' || __nb[0] == '+') + return __nb+1; + if (__ne - __nb >= 2 && __nb[0] == '0' + && (__nb[1] == 'x' || __nb[1] == 'X')) + return __nb+2; + break; + case ios_base::left: + return __ne; + case ios_base::right: + default: + break; + } + return __nb; +} + +// time_get + +static +string* +init_weeks() +{ + static string weeks[14]; + weeks[0] = "Sunday"; + weeks[1] = "Monday"; + weeks[2] = "Tuesday"; + weeks[3] = "Wednesday"; + weeks[4] = "Thursday"; + weeks[5] = "Friday"; + weeks[6] = "Saturday"; + weeks[7] = "Sun"; + weeks[8] = "Mon"; + weeks[9] = "Tue"; + weeks[10] = "Wed"; + weeks[11] = "Thu"; + weeks[12] = "Fri"; + weeks[13] = "Sat"; + return weeks; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +static +wstring* +init_wweeks() +{ + static wstring weeks[14]; + weeks[0] = L"Sunday"; + weeks[1] = L"Monday"; + weeks[2] = L"Tuesday"; + weeks[3] = L"Wednesday"; + weeks[4] = L"Thursday"; + weeks[5] = L"Friday"; + weeks[6] = L"Saturday"; + weeks[7] = L"Sun"; + weeks[8] = L"Mon"; + weeks[9] = L"Tue"; + weeks[10] = L"Wed"; + weeks[11] = L"Thu"; + weeks[12] = L"Fri"; + weeks[13] = L"Sat"; + return weeks; +} +#endif + +template <> +const string* +__time_get_c_storage<char>::__weeks() const +{ + static const string* weeks = init_weeks(); + return weeks; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +const wstring* +__time_get_c_storage<wchar_t>::__weeks() const +{ + static const wstring* weeks = init_wweeks(); + return weeks; +} +#endif + +static +string* +init_months() +{ + static string months[24]; + months[0] = "January"; + months[1] = "February"; + months[2] = "March"; + months[3] = "April"; + months[4] = "May"; + months[5] = "June"; + months[6] = "July"; + months[7] = "August"; + months[8] = "September"; + months[9] = "October"; + months[10] = "November"; + months[11] = "December"; + months[12] = "Jan"; + months[13] = "Feb"; + months[14] = "Mar"; + months[15] = "Apr"; + months[16] = "May"; + months[17] = "Jun"; + months[18] = "Jul"; + months[19] = "Aug"; + months[20] = "Sep"; + months[21] = "Oct"; + months[22] = "Nov"; + months[23] = "Dec"; + return months; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +static +wstring* +init_wmonths() +{ + static wstring months[24]; + months[0] = L"January"; + months[1] = L"February"; + months[2] = L"March"; + months[3] = L"April"; + months[4] = L"May"; + months[5] = L"June"; + months[6] = L"July"; + months[7] = L"August"; + months[8] = L"September"; + months[9] = L"October"; + months[10] = L"November"; + months[11] = L"December"; + months[12] = L"Jan"; + months[13] = L"Feb"; + months[14] = L"Mar"; + months[15] = L"Apr"; + months[16] = L"May"; + months[17] = L"Jun"; + months[18] = L"Jul"; + months[19] = L"Aug"; + months[20] = L"Sep"; + months[21] = L"Oct"; + months[22] = L"Nov"; + months[23] = L"Dec"; + return months; +} +#endif + +template <> +const string* +__time_get_c_storage<char>::__months() const +{ + static const string* months = init_months(); + return months; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +const wstring* +__time_get_c_storage<wchar_t>::__months() const +{ + static const wstring* months = init_wmonths(); + return months; +} +#endif + +static +string* +init_am_pm() +{ + static string am_pm[2]; + am_pm[0] = "AM"; + am_pm[1] = "PM"; + return am_pm; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +static +wstring* +init_wam_pm() +{ + static wstring am_pm[2]; + am_pm[0] = L"AM"; + am_pm[1] = L"PM"; + return am_pm; +} +#endif + +template <> +const string* +__time_get_c_storage<char>::__am_pm() const +{ + static const string* am_pm = init_am_pm(); + return am_pm; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +const wstring* +__time_get_c_storage<wchar_t>::__am_pm() const +{ + static const wstring* am_pm = init_wam_pm(); + return am_pm; +} +#endif + +template <> +const string& +__time_get_c_storage<char>::__x() const +{ + static string s("%m/%d/%y"); + return s; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +const wstring& +__time_get_c_storage<wchar_t>::__x() const +{ + static wstring s(L"%m/%d/%y"); + return s; +} +#endif + +template <> +const string& +__time_get_c_storage<char>::__X() const +{ + static string s("%H:%M:%S"); + return s; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +const wstring& +__time_get_c_storage<wchar_t>::__X() const +{ + static wstring s(L"%H:%M:%S"); + return s; +} +#endif + +template <> +const string& +__time_get_c_storage<char>::__c() const +{ + static string s("%a %b %d %H:%M:%S %Y"); + return s; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +const wstring& +__time_get_c_storage<wchar_t>::__c() const +{ + static wstring s(L"%a %b %d %H:%M:%S %Y"); + return s; +} +#endif + +template <> +const string& +__time_get_c_storage<char>::__r() const +{ + static string s("%I:%M:%S %p"); + return s; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +const wstring& +__time_get_c_storage<wchar_t>::__r() const +{ + static wstring s(L"%I:%M:%S %p"); + return s; +} +#endif + +// time_get_byname + +__time_get::__time_get(const char* nm) + : __loc_(newlocale(LC_ALL_MASK, nm, 0)) +{ + if (__loc_ == 0) + __throw_runtime_error("time_get_byname" + " failed to construct for " + string(nm)); +} + +__time_get::__time_get(const string& nm) + : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) +{ + if (__loc_ == 0) + __throw_runtime_error("time_get_byname" + " failed to construct for " + nm); +} + +__time_get::~__time_get() +{ + freelocale(__loc_); +} +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wmissing-field-initializers" +#endif +#if defined(__GNUG__) +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +template <> +string +__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct) +{ + tm t = {0}; + t.tm_sec = 59; + t.tm_min = 55; + t.tm_hour = 23; + t.tm_mday = 31; + t.tm_mon = 11; + t.tm_year = 161; + t.tm_wday = 6; + t.tm_yday = 364; + t.tm_isdst = -1; + char buf[100]; + char f[3] = {0}; + f[0] = '%'; + f[1] = fmt; + size_t n = strftime_l(buf, countof(buf), f, &t, __loc_); + char* bb = buf; + char* be = buf + n; + string result; + while (bb != be) + { + if (ct.is(ctype_base::space, *bb)) + { + result.push_back(' '); + for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb) + ; + continue; + } + char* w = bb; + ios_base::iostate err = ios_base::goodbit; + ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14, + ct, err, false) + - this->__weeks_; + if (i < 14) + { + result.push_back('%'); + if (i < 7) + result.push_back('A'); + else + result.push_back('a'); + bb = w; + continue; + } + w = bb; + i = __scan_keyword(w, be, this->__months_, this->__months_+24, + ct, err, false) + - this->__months_; + if (i < 24) + { + result.push_back('%'); + if (i < 12) + result.push_back('B'); + else + result.push_back('b'); + if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) + result.back() = 'm'; + bb = w; + continue; + } + if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) + { + w = bb; + i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2, + ct, err, false) - this->__am_pm_; + if (i < 2) + { + result.push_back('%'); + result.push_back('p'); + bb = w; + continue; + } + } + w = bb; + if (ct.is(ctype_base::digit, *bb)) + { + switch(__get_up_to_n_digits(bb, be, err, ct, 4)) + { + case 6: + result.push_back('%'); + result.push_back('w'); + break; + case 7: + result.push_back('%'); + result.push_back('u'); + break; + case 11: + result.push_back('%'); + result.push_back('I'); + break; + case 12: + result.push_back('%'); + result.push_back('m'); + break; + case 23: + result.push_back('%'); + result.push_back('H'); + break; + case 31: + result.push_back('%'); + result.push_back('d'); + break; + case 55: + result.push_back('%'); + result.push_back('M'); + break; + case 59: + result.push_back('%'); + result.push_back('S'); + break; + case 61: + result.push_back('%'); + result.push_back('y'); + break; + case 364: + result.push_back('%'); + result.push_back('j'); + break; + case 2061: + result.push_back('%'); + result.push_back('Y'); + break; + default: + for (; w != bb; ++w) + result.push_back(*w); + break; + } + continue; + } + if (*bb == '%') + { + result.push_back('%'); + result.push_back('%'); + ++bb; + continue; + } + result.push_back(*bb); + ++bb; + } + return result; +} + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wmissing-braces" +#endif + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +wstring +__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct) +{ + tm t = {0}; + t.tm_sec = 59; + t.tm_min = 55; + t.tm_hour = 23; + t.tm_mday = 31; + t.tm_mon = 11; + t.tm_year = 161; + t.tm_wday = 6; + t.tm_yday = 364; + t.tm_isdst = -1; + char buf[100]; + char f[3] = {0}; + f[0] = '%'; + f[1] = fmt; + strftime_l(buf, countof(buf), f, &t, __loc_); + wchar_t wbuf[100]; + wchar_t* wbb = wbuf; + mbstate_t mb = {0}; + const char* bb = buf; + size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_); + if (j == size_t(-1)) + __throw_runtime_error("locale not supported"); + wchar_t* wbe = wbb + j; + wstring result; + while (wbb != wbe) + { + if (ct.is(ctype_base::space, *wbb)) + { + result.push_back(L' '); + for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb) + ; + continue; + } + wchar_t* w = wbb; + ios_base::iostate err = ios_base::goodbit; + ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14, + ct, err, false) + - this->__weeks_; + if (i < 14) + { + result.push_back(L'%'); + if (i < 7) + result.push_back(L'A'); + else + result.push_back(L'a'); + wbb = w; + continue; + } + w = wbb; + i = __scan_keyword(w, wbe, this->__months_, this->__months_+24, + ct, err, false) + - this->__months_; + if (i < 24) + { + result.push_back(L'%'); + if (i < 12) + result.push_back(L'B'); + else + result.push_back(L'b'); + if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) + result.back() = L'm'; + wbb = w; + continue; + } + if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) + { + w = wbb; + i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2, + ct, err, false) - this->__am_pm_; + if (i < 2) + { + result.push_back(L'%'); + result.push_back(L'p'); + wbb = w; + continue; + } + } + w = wbb; + if (ct.is(ctype_base::digit, *wbb)) + { + switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4)) + { + case 6: + result.push_back(L'%'); + result.push_back(L'w'); + break; + case 7: + result.push_back(L'%'); + result.push_back(L'u'); + break; + case 11: + result.push_back(L'%'); + result.push_back(L'I'); + break; + case 12: + result.push_back(L'%'); + result.push_back(L'm'); + break; + case 23: + result.push_back(L'%'); + result.push_back(L'H'); + break; + case 31: + result.push_back(L'%'); + result.push_back(L'd'); + break; + case 55: + result.push_back(L'%'); + result.push_back(L'M'); + break; + case 59: + result.push_back(L'%'); + result.push_back(L'S'); + break; + case 61: + result.push_back(L'%'); + result.push_back(L'y'); + break; + case 364: + result.push_back(L'%'); + result.push_back(L'j'); + break; + case 2061: + result.push_back(L'%'); + result.push_back(L'Y'); + break; + default: + for (; w != wbb; ++w) + result.push_back(*w); + break; + } + continue; + } + if (ct.narrow(*wbb, 0) == '%') + { + result.push_back(L'%'); + result.push_back(L'%'); + ++wbb; + continue; + } + result.push_back(*wbb); + ++wbb; + } + return result; +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +template <> +void +__time_get_storage<char>::init(const ctype<char>& ct) +{ + tm t = {0}; + char buf[100]; + // __weeks_ + for (int i = 0; i < 7; ++i) + { + t.tm_wday = i; + strftime_l(buf, countof(buf), "%A", &t, __loc_); + __weeks_[i] = buf; + strftime_l(buf, countof(buf), "%a", &t, __loc_); + __weeks_[i+7] = buf; + } + // __months_ + for (int i = 0; i < 12; ++i) + { + t.tm_mon = i; + strftime_l(buf, countof(buf), "%B", &t, __loc_); + __months_[i] = buf; + strftime_l(buf, countof(buf), "%b", &t, __loc_); + __months_[i+12] = buf; + } + // __am_pm_ + t.tm_hour = 1; + strftime_l(buf, countof(buf), "%p", &t, __loc_); + __am_pm_[0] = buf; + t.tm_hour = 13; + strftime_l(buf, countof(buf), "%p", &t, __loc_); + __am_pm_[1] = buf; + __c_ = __analyze('c', ct); + __r_ = __analyze('r', ct); + __x_ = __analyze('x', ct); + __X_ = __analyze('X', ct); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +void +__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) +{ + tm t = {0}; + char buf[100]; + wchar_t wbuf[100]; + wchar_t* wbe; + mbstate_t mb = {0}; + // __weeks_ + for (int i = 0; i < 7; ++i) + { + t.tm_wday = i; + strftime_l(buf, countof(buf), "%A", &t, __loc_); + mb = mbstate_t(); + const char* bb = buf; + size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); + if (j == size_t(-1) || j == 0) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __weeks_[i].assign(wbuf, wbe); + strftime_l(buf, countof(buf), "%a", &t, __loc_); + mb = mbstate_t(); + bb = buf; + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); + if (j == size_t(-1) || j == 0) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __weeks_[i+7].assign(wbuf, wbe); + } + // __months_ + for (int i = 0; i < 12; ++i) + { + t.tm_mon = i; + strftime_l(buf, countof(buf), "%B", &t, __loc_); + mb = mbstate_t(); + const char* bb = buf; + size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); + if (j == size_t(-1) || j == 0) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __months_[i].assign(wbuf, wbe); + strftime_l(buf, countof(buf), "%b", &t, __loc_); + mb = mbstate_t(); + bb = buf; + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); + if (j == size_t(-1) || j == 0) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __months_[i+12].assign(wbuf, wbe); + } + // __am_pm_ + t.tm_hour = 1; + strftime_l(buf, countof(buf), "%p", &t, __loc_); + mb = mbstate_t(); + const char* bb = buf; + size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); + if (j == size_t(-1)) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __am_pm_[0].assign(wbuf, wbe); + t.tm_hour = 13; + strftime_l(buf, countof(buf), "%p", &t, __loc_); + mb = mbstate_t(); + bb = buf; + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); + if (j == size_t(-1)) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __am_pm_[1].assign(wbuf, wbe); + __c_ = __analyze('c', ct); + __r_ = __analyze('r', ct); + __x_ = __analyze('x', ct); + __X_ = __analyze('X', ct); +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +template <class CharT> +struct _LIBCPP_HIDDEN __time_get_temp + : public ctype_byname<CharT> +{ + explicit __time_get_temp(const char* nm) + : ctype_byname<CharT>(nm, 1) {} + explicit __time_get_temp(const string& nm) + : ctype_byname<CharT>(nm, 1) {} +}; + +template <> +__time_get_storage<char>::__time_get_storage(const char* __nm) + : __time_get(__nm) +{ + const __time_get_temp<char> ct(__nm); + init(ct); +} + +template <> +__time_get_storage<char>::__time_get_storage(const string& __nm) + : __time_get(__nm) +{ + const __time_get_temp<char> ct(__nm); + init(ct); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +__time_get_storage<wchar_t>::__time_get_storage(const char* __nm) + : __time_get(__nm) +{ + const __time_get_temp<wchar_t> ct(__nm); + init(ct); +} + +template <> +__time_get_storage<wchar_t>::__time_get_storage(const string& __nm) + : __time_get(__nm) +{ + const __time_get_temp<wchar_t> ct(__nm); + init(ct); +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +template <> +time_base::dateorder +__time_get_storage<char>::__do_date_order() const +{ + unsigned i; + for (i = 0; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + ++i; + switch (__x_[i]) + { + case 'y': + case 'Y': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + switch (__x_[i]) + { + case 'm': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'd') + return time_base::ymd; + break; + case 'd': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'm') + return time_base::ydm; + break; + } + break; + case 'm': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'd') + { + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'y' || __x_[i] == 'Y') + return time_base::mdy; + break; + } + break; + case 'd': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'm') + { + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'y' || __x_[i] == 'Y') + return time_base::dmy; + break; + } + break; + } + return time_base::no_order; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +time_base::dateorder +__time_get_storage<wchar_t>::__do_date_order() const +{ + unsigned i; + for (i = 0; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + ++i; + switch (__x_[i]) + { + case L'y': + case L'Y': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + switch (__x_[i]) + { + case L'm': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'd') + return time_base::ymd; + break; + case L'd': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'm') + return time_base::ydm; + break; + } + break; + case L'm': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'd') + { + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'y' || __x_[i] == L'Y') + return time_base::mdy; + break; + } + break; + case L'd': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'm') + { + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'y' || __x_[i] == L'Y') + return time_base::dmy; + break; + } + break; + } + return time_base::no_order; +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// time_put + +__time_put::__time_put(const char* nm) + : __loc_(newlocale(LC_ALL_MASK, nm, 0)) +{ + if (__loc_ == 0) + __throw_runtime_error("time_put_byname" + " failed to construct for " + string(nm)); +} + +__time_put::__time_put(const string& nm) + : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) +{ + if (__loc_ == 0) + __throw_runtime_error("time_put_byname" + " failed to construct for " + nm); +} + +__time_put::~__time_put() +{ + if (__loc_ != _LIBCPP_GET_C_LOCALE) + freelocale(__loc_); +} + +void +__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm, + char __fmt, char __mod) const +{ + char fmt[] = {'%', __fmt, __mod, 0}; + if (__mod != 0) + swap(fmt[1], fmt[2]); + size_t n = strftime_l(__nb, countof(__nb, __ne), fmt, __tm, __loc_); + __ne = __nb + n; +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +void +__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, + char __fmt, char __mod) const +{ + char __nar[100]; + char* __ne = __nar + 100; + __do_put(__nar, __ne, __tm, __fmt, __mod); + mbstate_t mb = {0}; + const char* __nb = __nar; + size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_); + if (j == size_t(-1)) + __throw_runtime_error("locale not supported"); + __we = __wb + j; +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// moneypunct_byname + +template <class charT> +static +void +__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_, + bool intl, char cs_precedes, char sep_by_space, char sign_posn, + charT space_char) +{ + const char sign = static_cast<char>(money_base::sign); + const char space = static_cast<char>(money_base::space); + const char none = static_cast<char>(money_base::none); + const char symbol = static_cast<char>(money_base::symbol); + const char value = static_cast<char>(money_base::value); + const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4; + + // Comments on case branches reflect 'C11 7.11.2.1 The localeconv + // function'. "Space between sign and symbol or value" means that + // if the sign is adjacent to the symbol, there's a space between + // them, and otherwise there's a space between the sign and value. + // + // C11's localeconv specifies that the fourth character of an + // international curr_symbol is used to separate the sign and + // value when sep_by_space says to do so. C++ can't represent + // that, so we just use a space. When sep_by_space says to + // separate the symbol and value-or-sign with a space, we rearrange the + // curr_symbol to put its spacing character on the correct side of + // the symbol. + // + // We also need to avoid adding an extra space between the sign + // and value when the currency symbol is suppressed (by not + // setting showbase). We match glibc's strfmon by interpreting + // sep_by_space==1 as "omit the space when the currency symbol is + // absent". + // + // Users who want to get this right should use ICU instead. + + switch (cs_precedes) + { + case 0: // value before curr_symbol + if (symbol_contains_sep) { + // Move the separator to before the symbol, to place it + // between the value and symbol. + rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3, + __curr_symbol_.end()); + } + switch (sign_posn) + { + case 0: // Parentheses surround the quantity and currency symbol. + pat.field[0] = sign; + pat.field[1] = value; + pat.field[2] = none; // Any space appears in the symbol. + pat.field[3] = symbol; + switch (sep_by_space) + { + case 0: // No space separates the currency symbol and value. + // This case may have changed between C99 and C11; + // assume the currency symbol matches the intention. + case 2: // Space between sign and currency or value. + // The "sign" is two parentheses, so no space here either. + return; + case 1: // Space between currency-and-sign or currency and value. + if (!symbol_contains_sep) { + // We insert the space into the symbol instead of + // setting pat.field[2]=space so that when + // showbase is not set, the space goes away too. + __curr_symbol_.insert((size_t)0, 1, space_char); + } + return; + default: + break; + } + break; + case 1: // The sign string precedes the quantity and currency symbol. + pat.field[0] = sign; + pat.field[3] = symbol; + switch (sep_by_space) + { + case 0: // No space separates the currency symbol and value. + pat.field[1] = value; + pat.field[2] = none; + return; + case 1: // Space between currency-and-sign or currency and value. + pat.field[1] = value; + pat.field[2] = none; + if (!symbol_contains_sep) { + // We insert the space into the symbol instead of + // setting pat.field[2]=space so that when + // showbase is not set, the space goes away too. + __curr_symbol_.insert((size_t)0, 1, space_char); + } + return; + case 2: // Space between sign and currency or value. + pat.field[1] = space; + pat.field[2] = value; + if (symbol_contains_sep) { + // Remove the separator from the symbol, since it + // has already appeared after the sign. + __curr_symbol_.erase(__curr_symbol_.begin()); + } + return; + default: + break; + } + break; + case 2: // The sign string succeeds the quantity and currency symbol. + pat.field[0] = value; + pat.field[3] = sign; + switch (sep_by_space) + { + case 0: // No space separates the currency symbol and value. + pat.field[1] = none; + pat.field[2] = symbol; + return; + case 1: // Space between currency-and-sign or currency and value. + if (!symbol_contains_sep) { + // We insert the space into the symbol instead of + // setting pat.field[1]=space so that when + // showbase is not set, the space goes away too. + __curr_symbol_.insert((size_t)0, 1, space_char); + } + pat.field[1] = none; + pat.field[2] = symbol; + return; + case 2: // Space between sign and currency or value. + pat.field[1] = symbol; + pat.field[2] = space; + if (symbol_contains_sep) { + // Remove the separator from the symbol, since it + // should not be removed if showbase is absent. + __curr_symbol_.erase(__curr_symbol_.begin()); + } + return; + default: + break; + } + break; + case 3: // The sign string immediately precedes the currency symbol. + pat.field[0] = value; + pat.field[3] = symbol; + switch (sep_by_space) + { + case 0: // No space separates the currency symbol and value. + pat.field[1] = none; + pat.field[2] = sign; + return; + case 1: // Space between currency-and-sign or currency and value. + pat.field[1] = space; + pat.field[2] = sign; + if (symbol_contains_sep) { + // Remove the separator from the symbol, since it + // has already appeared before the sign. + __curr_symbol_.erase(__curr_symbol_.begin()); + } + return; + case 2: // Space between sign and currency or value. + pat.field[1] = sign; + pat.field[2] = none; + if (!symbol_contains_sep) { + // We insert the space into the symbol instead of + // setting pat.field[2]=space so that when + // showbase is not set, the space goes away too. + __curr_symbol_.insert((size_t)0, 1, space_char); + } + return; + default: + break; + } + break; + case 4: // The sign string immediately succeeds the currency symbol. + pat.field[0] = value; + pat.field[3] = sign; + switch (sep_by_space) + { + case 0: // No space separates the currency symbol and value. + pat.field[1] = none; + pat.field[2] = symbol; + return; + case 1: // Space between currency-and-sign or currency and value. + pat.field[1] = none; + pat.field[2] = symbol; + if (!symbol_contains_sep) { + // We insert the space into the symbol instead of + // setting pat.field[1]=space so that when + // showbase is not set, the space goes away too. + __curr_symbol_.insert((size_t)0, 1, space_char); + } + return; + case 2: // Space between sign and currency or value. + pat.field[1] = symbol; + pat.field[2] = space; + if (symbol_contains_sep) { + // Remove the separator from the symbol, since it + // should not disappear when showbase is absent. + __curr_symbol_.erase(__curr_symbol_.begin()); + } + return; + default: + break; + } + break; + default: + break; + } + break; + case 1: // curr_symbol before value + switch (sign_posn) + { + case 0: // Parentheses surround the quantity and currency symbol. + pat.field[0] = sign; + pat.field[1] = symbol; + pat.field[2] = none; // Any space appears in the symbol. + pat.field[3] = value; + switch (sep_by_space) + { + case 0: // No space separates the currency symbol and value. + // This case may have changed between C99 and C11; + // assume the currency symbol matches the intention. + case 2: // Space between sign and currency or value. + // The "sign" is two parentheses, so no space here either. + return; + case 1: // Space between currency-and-sign or currency and value. + if (!symbol_contains_sep) { + // We insert the space into the symbol instead of + // setting pat.field[2]=space so that when + // showbase is not set, the space goes away too. + __curr_symbol_.insert((size_t)0, 1, space_char); + } + return; + default: + break; + } + break; + case 1: // The sign string precedes the quantity and currency symbol. + pat.field[0] = sign; + pat.field[3] = value; + switch (sep_by_space) + { + case 0: // No space separates the currency symbol and value. + pat.field[1] = symbol; + pat.field[2] = none; + return; + case 1: // Space between currency-and-sign or currency and value. + pat.field[1] = symbol; + pat.field[2] = none; + if (!symbol_contains_sep) { + // We insert the space into the symbol instead of + // setting pat.field[2]=space so that when + // showbase is not set, the space goes away too. + __curr_symbol_.push_back(space_char); + } + return; + case 2: // Space between sign and currency or value. + pat.field[1] = space; + pat.field[2] = symbol; + if (symbol_contains_sep) { + // Remove the separator from the symbol, since it + // has already appeared after the sign. + __curr_symbol_.pop_back(); + } + return; + default: + break; + } + break; + case 2: // The sign string succeeds the quantity and currency symbol. + pat.field[0] = symbol; + pat.field[3] = sign; + switch (sep_by_space) + { + case 0: // No space separates the currency symbol and value. + pat.field[1] = none; + pat.field[2] = value; + return; + case 1: // Space between currency-and-sign or currency and value. + pat.field[1] = none; + pat.field[2] = value; + if (!symbol_contains_sep) { + // We insert the space into the symbol instead of + // setting pat.field[1]=space so that when + // showbase is not set, the space goes away too. + __curr_symbol_.push_back(space_char); + } + return; + case 2: // Space between sign and currency or value. + pat.field[1] = value; + pat.field[2] = space; + if (symbol_contains_sep) { + // Remove the separator from the symbol, since it + // will appear before the sign. + __curr_symbol_.pop_back(); + } + return; + default: + break; + } + break; + case 3: // The sign string immediately precedes the currency symbol. + pat.field[0] = sign; + pat.field[3] = value; + switch (sep_by_space) + { + case 0: // No space separates the currency symbol and value. + pat.field[1] = symbol; + pat.field[2] = none; + return; + case 1: // Space between currency-and-sign or currency and value. + pat.field[1] = symbol; + pat.field[2] = none; + if (!symbol_contains_sep) { + // We insert the space into the symbol instead of + // setting pat.field[2]=space so that when + // showbase is not set, the space goes away too. + __curr_symbol_.push_back(space_char); + } + return; + case 2: // Space between sign and currency or value. + pat.field[1] = space; + pat.field[2] = symbol; + if (symbol_contains_sep) { + // Remove the separator from the symbol, since it + // has already appeared after the sign. + __curr_symbol_.pop_back(); + } + return; + default: + break; + } + break; + case 4: // The sign string immediately succeeds the currency symbol. + pat.field[0] = symbol; + pat.field[3] = value; + switch (sep_by_space) + { + case 0: // No space separates the currency symbol and value. + pat.field[1] = sign; + pat.field[2] = none; + return; + case 1: // Space between currency-and-sign or currency and value. + pat.field[1] = sign; + pat.field[2] = space; + if (symbol_contains_sep) { + // Remove the separator from the symbol, since it + // should not disappear when showbase is absent. + __curr_symbol_.pop_back(); + } + return; + case 2: // Space between sign and currency or value. + pat.field[1] = none; + pat.field[2] = sign; + if (!symbol_contains_sep) { + // We insert the space into the symbol instead of + // setting pat.field[1]=space so that when + // showbase is not set, the space goes away too. + __curr_symbol_.push_back(space_char); + } + return; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + pat.field[0] = symbol; + pat.field[1] = sign; + pat.field[2] = none; + pat.field[3] = value; +} + +template<> +void +moneypunct_byname<char, false>::init(const char* nm) +{ + typedef moneypunct<char, false> base; + __libcpp_unique_locale loc(nm); + if (!loc) + __throw_runtime_error("moneypunct_byname" + " failed to construct for " + string(nm)); + + lconv* lc = __libcpp_localeconv_l(loc.get()); + if (!checked_string_to_char_convert(__decimal_point_, + lc->mon_decimal_point, + loc.get())) + __decimal_point_ = base::do_decimal_point(); + if (!checked_string_to_char_convert(__thousands_sep_, + lc->mon_thousands_sep, + loc.get())) + __thousands_sep_ = base::do_thousands_sep(); + + __grouping_ = lc->mon_grouping; + __curr_symbol_ = lc->currency_symbol; + if (lc->frac_digits != CHAR_MAX) + __frac_digits_ = lc->frac_digits; + else + __frac_digits_ = base::do_frac_digits(); + if (lc->p_sign_posn == 0) + __positive_sign_ = "()"; + else + __positive_sign_ = lc->positive_sign; + if (lc->n_sign_posn == 0) + __negative_sign_ = "()"; + else + __negative_sign_ = lc->negative_sign; + // Assume the positive and negative formats will want spaces in + // the same places in curr_symbol since there's no way to + // represent anything else. + string_type __dummy_curr_symbol = __curr_symbol_; + __init_pat(__pos_format_, __dummy_curr_symbol, false, + lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); + __init_pat(__neg_format_, __curr_symbol_, false, + lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); +} + +template<> +void +moneypunct_byname<char, true>::init(const char* nm) +{ + typedef moneypunct<char, true> base; + __libcpp_unique_locale loc(nm); + if (!loc) + __throw_runtime_error("moneypunct_byname" + " failed to construct for " + string(nm)); + + lconv* lc = __libcpp_localeconv_l(loc.get()); + if (!checked_string_to_char_convert(__decimal_point_, + lc->mon_decimal_point, + loc.get())) + __decimal_point_ = base::do_decimal_point(); + if (!checked_string_to_char_convert(__thousands_sep_, + lc->mon_thousands_sep, + loc.get())) + __thousands_sep_ = base::do_thousands_sep(); + __grouping_ = lc->mon_grouping; + __curr_symbol_ = lc->int_curr_symbol; + if (lc->int_frac_digits != CHAR_MAX) + __frac_digits_ = lc->int_frac_digits; + else + __frac_digits_ = base::do_frac_digits(); +#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) + if (lc->p_sign_posn == 0) +#else // _LIBCPP_MSVCRT + if (lc->int_p_sign_posn == 0) +#endif // !_LIBCPP_MSVCRT + __positive_sign_ = "()"; + else + __positive_sign_ = lc->positive_sign; +#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) + if(lc->n_sign_posn == 0) +#else // _LIBCPP_MSVCRT + if (lc->int_n_sign_posn == 0) +#endif // !_LIBCPP_MSVCRT + __negative_sign_ = "()"; + else + __negative_sign_ = lc->negative_sign; + // Assume the positive and negative formats will want spaces in + // the same places in curr_symbol since there's no way to + // represent anything else. + string_type __dummy_curr_symbol = __curr_symbol_; +#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) + __init_pat(__pos_format_, __dummy_curr_symbol, true, + lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); + __init_pat(__neg_format_, __curr_symbol_, true, + lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); +#else // _LIBCPP_MSVCRT + __init_pat(__pos_format_, __dummy_curr_symbol, true, + lc->int_p_cs_precedes, lc->int_p_sep_by_space, + lc->int_p_sign_posn, ' '); + __init_pat(__neg_format_, __curr_symbol_, true, + lc->int_n_cs_precedes, lc->int_n_sep_by_space, + lc->int_n_sign_posn, ' '); +#endif // !_LIBCPP_MSVCRT +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template<> +void +moneypunct_byname<wchar_t, false>::init(const char* nm) +{ + typedef moneypunct<wchar_t, false> base; + __libcpp_unique_locale loc(nm); + if (!loc) + __throw_runtime_error("moneypunct_byname" + " failed to construct for " + string(nm)); + lconv* lc = __libcpp_localeconv_l(loc.get()); + if (!checked_string_to_wchar_convert(__decimal_point_, + lc->mon_decimal_point, + loc.get())) + __decimal_point_ = base::do_decimal_point(); + if (!checked_string_to_wchar_convert(__thousands_sep_, + lc->mon_thousands_sep, + loc.get())) + __thousands_sep_ = base::do_thousands_sep(); + __grouping_ = lc->mon_grouping; + wchar_t wbuf[100]; + mbstate_t mb = {0}; + const char* bb = lc->currency_symbol; + size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); + if (j == size_t(-1)) + __throw_runtime_error("locale not supported"); + wchar_t* wbe = wbuf + j; + __curr_symbol_.assign(wbuf, wbe); + if (lc->frac_digits != CHAR_MAX) + __frac_digits_ = lc->frac_digits; + else + __frac_digits_ = base::do_frac_digits(); + if (lc->p_sign_posn == 0) + __positive_sign_ = L"()"; + else + { + mb = mbstate_t(); + bb = lc->positive_sign; + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); + if (j == size_t(-1)) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __positive_sign_.assign(wbuf, wbe); + } + if (lc->n_sign_posn == 0) + __negative_sign_ = L"()"; + else + { + mb = mbstate_t(); + bb = lc->negative_sign; + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); + if (j == size_t(-1)) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __negative_sign_.assign(wbuf, wbe); + } + // Assume the positive and negative formats will want spaces in + // the same places in curr_symbol since there's no way to + // represent anything else. + string_type __dummy_curr_symbol = __curr_symbol_; + __init_pat(__pos_format_, __dummy_curr_symbol, false, + lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); + __init_pat(__neg_format_, __curr_symbol_, false, + lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); +} + +template<> +void +moneypunct_byname<wchar_t, true>::init(const char* nm) +{ + typedef moneypunct<wchar_t, true> base; + __libcpp_unique_locale loc(nm); + if (!loc) + __throw_runtime_error("moneypunct_byname" + " failed to construct for " + string(nm)); + + lconv* lc = __libcpp_localeconv_l(loc.get()); + if (!checked_string_to_wchar_convert(__decimal_point_, + lc->mon_decimal_point, + loc.get())) + __decimal_point_ = base::do_decimal_point(); + if (!checked_string_to_wchar_convert(__thousands_sep_, + lc->mon_thousands_sep, + loc.get())) + __thousands_sep_ = base::do_thousands_sep(); + __grouping_ = lc->mon_grouping; + wchar_t wbuf[100]; + mbstate_t mb = {0}; + const char* bb = lc->int_curr_symbol; + size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); + if (j == size_t(-1)) + __throw_runtime_error("locale not supported"); + wchar_t* wbe = wbuf + j; + __curr_symbol_.assign(wbuf, wbe); + if (lc->int_frac_digits != CHAR_MAX) + __frac_digits_ = lc->int_frac_digits; + else + __frac_digits_ = base::do_frac_digits(); +#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) + if (lc->p_sign_posn == 0) +#else // _LIBCPP_MSVCRT + if (lc->int_p_sign_posn == 0) +#endif // !_LIBCPP_MSVCRT + __positive_sign_ = L"()"; + else + { + mb = mbstate_t(); + bb = lc->positive_sign; + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); + if (j == size_t(-1)) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __positive_sign_.assign(wbuf, wbe); + } +#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) + if (lc->n_sign_posn == 0) +#else // _LIBCPP_MSVCRT + if (lc->int_n_sign_posn == 0) +#endif // !_LIBCPP_MSVCRT + __negative_sign_ = L"()"; + else + { + mb = mbstate_t(); + bb = lc->negative_sign; + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); + if (j == size_t(-1)) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __negative_sign_.assign(wbuf, wbe); + } + // Assume the positive and negative formats will want spaces in + // the same places in curr_symbol since there's no way to + // represent anything else. + string_type __dummy_curr_symbol = __curr_symbol_; +#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) + __init_pat(__pos_format_, __dummy_curr_symbol, true, + lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); + __init_pat(__neg_format_, __curr_symbol_, true, + lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); +#else // _LIBCPP_MSVCRT + __init_pat(__pos_format_, __dummy_curr_symbol, true, + lc->int_p_cs_precedes, lc->int_p_sep_by_space, + lc->int_p_sign_posn, L' '); + __init_pat(__neg_format_, __curr_symbol_, true, + lc->int_n_cs_precedes, lc->int_n_sep_by_space, + lc->int_n_sign_posn, L' '); +#endif // !_LIBCPP_MSVCRT +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +void __do_nothing(void*) {} + +void __throw_runtime_error(const char* msg) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw runtime_error(msg); +#else + (void)msg; + _VSTD::abort(); +#endif +} + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;) + + template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;) + + template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>; + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;) +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>; + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;) +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;) + + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>; +_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;) +template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>; +template class _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>; +#ifndef _LIBCPP_HAS_NO_CHAR8_T +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char8_t, mbstate_t>; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char8_t, mbstate_t>; +#endif + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/memory.cpp b/contrib/libs/cxxsupp/libcxx/src/memory.cpp index bb8d682ee3..f9e8d44842 100644 --- a/contrib/libs/cxxsupp/libcxx/src/memory.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/memory.cpp @@ -1,258 +1,258 @@ -//===------------------------ memory.cpp ----------------------------------===// -// +//===------------------------ memory.cpp ----------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "memory" -#ifndef _LIBCPP_HAS_NO_THREADS -#include "mutex" -#include "thread" -#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -#pragma comment(lib, "pthread") -#endif -#endif -#if !defined(_LIBCPP_HAS_NO_THREADS) -#include <atomic> -#else -#include "include/atomic_support.h" -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -const allocator_arg_t allocator_arg = allocator_arg_t(); - -bad_weak_ptr::~bad_weak_ptr() noexcept {} - -const char* -bad_weak_ptr::what() const noexcept -{ - return "bad_weak_ptr"; -} - -__shared_count::~__shared_count() -{ -} - -__shared_weak_count::~__shared_weak_count() -{ -} - -#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) -void -__shared_count::__add_shared() noexcept -{ -#ifdef _LIBCPP_HAS_NO_THREADS - __libcpp_atomic_refcount_increment(__shared_owners_); -#else - ++__shared_owners_; -#endif -} - -bool -__shared_count::__release_shared() noexcept -{ -#ifdef _LIBCPP_HAS_NO_THREADS - if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) -#else - if (--__shared_owners_ == -1) -#endif - { - __on_zero_shared(); - return true; - } - return false; -} - -void -__shared_weak_count::__add_shared() noexcept -{ - __shared_count::__add_shared(); -} - -void -__shared_weak_count::__add_weak() noexcept -{ -#ifdef _LIBCPP_HAS_NO_THREADS - __libcpp_atomic_refcount_increment(__shared_weak_owners_); -#else - ++__shared_weak_owners_; -#endif -} - -void -__shared_weak_count::__release_shared() noexcept -{ - if (__shared_count::__release_shared()) - __release_weak(); -} - -#endif // _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS - -void -__shared_weak_count::__release_weak() noexcept -{ - // NOTE: The acquire load here is an optimization of the very - // common case where a shared pointer is being destructed while - // having no other contended references. - // - // BENEFIT: We avoid expensive atomic stores like XADD and STREX - // in a common case. Those instructions are slow and do nasty - // things to caches. - // - // IS THIS SAFE? Yes. During weak destruction, if we see that we - // are the last reference, we know that no-one else is accessing - // us. If someone were accessing us, then they would be doing so - // while the last shared / weak_ptr was being destructed, and - // that's undefined anyway. - // - // If we see anything other than a 0, then we have possible - // contention, and need to use an atomicrmw primitive. - // The same arguments don't apply for increment, where it is legal - // (though inadvisable) to share shared_ptr references between - // threads, and have them all get copied at once. The argument - // also doesn't apply for __release_shared, because an outstanding - // weak_ptr::lock() could read / modify the shared count. -#ifdef _LIBCPP_HAS_NO_THREADS - if (__libcpp_atomic_load(&__shared_weak_owners_, _AO_Acquire) == 0) -#else - if (__shared_weak_owners_.load(memory_order_acquire) == 0) -#endif - { - // no need to do this store, because we are about - // to destroy everything. - //__libcpp_atomic_store(&__shared_weak_owners_, -1, _AO_Release); - __on_zero_shared_weak(); - } -#ifdef _LIBCPP_HAS_NO_THREADS - else if (__libcpp_atomic_refcount_decrement(__shared_weak_owners_) == -1) -#else - else if (--__shared_weak_owners_ == -1) -#endif - __on_zero_shared_weak(); -} - -__shared_weak_count* -__shared_weak_count::lock() noexcept -{ -#ifdef _LIBCPP_HAS_NO_THREADS - long object_owners = __libcpp_atomic_load(&__shared_owners_); -#else - long object_owners = __shared_owners_.load(); -#endif - while (object_owners != -1) - { -#ifdef _LIBCPP_HAS_NO_THREADS - if (__libcpp_atomic_compare_exchange(&__shared_owners_, - &object_owners, - object_owners+1)) -#else - if (__shared_owners_.compare_exchange_weak(object_owners, object_owners+1)) -#endif - return this; - } - return nullptr; -} - -const void* -__shared_weak_count::__get_deleter(const type_info&) const noexcept -{ - return nullptr; -} - -#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) - -_LIBCPP_SAFE_STATIC static const std::size_t __sp_mut_count = 16; -_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut_back[__sp_mut_count] = -{ - _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, - _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, - _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, - _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER -}; - -_LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) noexcept - : __lx(p) -{ -} - -void -__sp_mut::lock() noexcept -{ - auto m = static_cast<__libcpp_mutex_t*>(__lx); - unsigned count = 0; - while (!__libcpp_mutex_trylock(m)) - { - if (++count > 16) - { - __libcpp_mutex_lock(m); - break; - } - this_thread::yield(); - } -} - -void -__sp_mut::unlock() noexcept -{ - __libcpp_mutex_unlock(static_cast<__libcpp_mutex_t*>(__lx)); -} - -__sp_mut& -__get_sp_mut(const void* p) -{ - static __sp_mut muts[__sp_mut_count] - { - &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3], - &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7], - &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11], - &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15] - }; - return muts[hash<const void*>()(p) & (__sp_mut_count-1)]; -} - -#endif // !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) - -void -declare_reachable(void*) -{ -} - -void -declare_no_pointers(char*, size_t) -{ -} - -void -undeclare_no_pointers(char*, size_t) -{ -} - -void* -__undeclare_reachable(void* p) -{ - return p; -} - -void* -align(size_t alignment, size_t size, void*& ptr, size_t& space) -{ - void* r = nullptr; - if (size <= space) - { - char* p1 = static_cast<char*>(ptr); - char* p2 = reinterpret_cast<char*>(reinterpret_cast<size_t>(p1 + (alignment - 1)) & -alignment); - size_t d = static_cast<size_t>(p2 - p1); - if (d <= space - size) - { - r = p2; - ptr = r; - space -= d; - } - } - return r; -} - -_LIBCPP_END_NAMESPACE_STD +// +//===----------------------------------------------------------------------===// + +#include "memory" +#ifndef _LIBCPP_HAS_NO_THREADS +#include "mutex" +#include "thread" +#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +#pragma comment(lib, "pthread") +#endif +#endif +#if !defined(_LIBCPP_HAS_NO_THREADS) +#include <atomic> +#else +#include "include/atomic_support.h" +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +const allocator_arg_t allocator_arg = allocator_arg_t(); + +bad_weak_ptr::~bad_weak_ptr() noexcept {} + +const char* +bad_weak_ptr::what() const noexcept +{ + return "bad_weak_ptr"; +} + +__shared_count::~__shared_count() +{ +} + +__shared_weak_count::~__shared_weak_count() +{ +} + +#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) +void +__shared_count::__add_shared() noexcept +{ +#ifdef _LIBCPP_HAS_NO_THREADS + __libcpp_atomic_refcount_increment(__shared_owners_); +#else + ++__shared_owners_; +#endif +} + +bool +__shared_count::__release_shared() noexcept +{ +#ifdef _LIBCPP_HAS_NO_THREADS + if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1) +#else + if (--__shared_owners_ == -1) +#endif + { + __on_zero_shared(); + return true; + } + return false; +} + +void +__shared_weak_count::__add_shared() noexcept +{ + __shared_count::__add_shared(); +} + +void +__shared_weak_count::__add_weak() noexcept +{ +#ifdef _LIBCPP_HAS_NO_THREADS + __libcpp_atomic_refcount_increment(__shared_weak_owners_); +#else + ++__shared_weak_owners_; +#endif +} + +void +__shared_weak_count::__release_shared() noexcept +{ + if (__shared_count::__release_shared()) + __release_weak(); +} + +#endif // _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS + +void +__shared_weak_count::__release_weak() noexcept +{ + // NOTE: The acquire load here is an optimization of the very + // common case where a shared pointer is being destructed while + // having no other contended references. + // + // BENEFIT: We avoid expensive atomic stores like XADD and STREX + // in a common case. Those instructions are slow and do nasty + // things to caches. + // + // IS THIS SAFE? Yes. During weak destruction, if we see that we + // are the last reference, we know that no-one else is accessing + // us. If someone were accessing us, then they would be doing so + // while the last shared / weak_ptr was being destructed, and + // that's undefined anyway. + // + // If we see anything other than a 0, then we have possible + // contention, and need to use an atomicrmw primitive. + // The same arguments don't apply for increment, where it is legal + // (though inadvisable) to share shared_ptr references between + // threads, and have them all get copied at once. The argument + // also doesn't apply for __release_shared, because an outstanding + // weak_ptr::lock() could read / modify the shared count. +#ifdef _LIBCPP_HAS_NO_THREADS + if (__libcpp_atomic_load(&__shared_weak_owners_, _AO_Acquire) == 0) +#else + if (__shared_weak_owners_.load(memory_order_acquire) == 0) +#endif + { + // no need to do this store, because we are about + // to destroy everything. + //__libcpp_atomic_store(&__shared_weak_owners_, -1, _AO_Release); + __on_zero_shared_weak(); + } +#ifdef _LIBCPP_HAS_NO_THREADS + else if (__libcpp_atomic_refcount_decrement(__shared_weak_owners_) == -1) +#else + else if (--__shared_weak_owners_ == -1) +#endif + __on_zero_shared_weak(); +} + +__shared_weak_count* +__shared_weak_count::lock() noexcept +{ +#ifdef _LIBCPP_HAS_NO_THREADS + long object_owners = __libcpp_atomic_load(&__shared_owners_); +#else + long object_owners = __shared_owners_.load(); +#endif + while (object_owners != -1) + { +#ifdef _LIBCPP_HAS_NO_THREADS + if (__libcpp_atomic_compare_exchange(&__shared_owners_, + &object_owners, + object_owners+1)) +#else + if (__shared_owners_.compare_exchange_weak(object_owners, object_owners+1)) +#endif + return this; + } + return nullptr; +} + +const void* +__shared_weak_count::__get_deleter(const type_info&) const noexcept +{ + return nullptr; +} + +#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) + +_LIBCPP_SAFE_STATIC static const std::size_t __sp_mut_count = 16; +_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut_back[__sp_mut_count] = +{ + _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, + _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, + _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, + _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER +}; + +_LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) noexcept + : __lx(p) +{ +} + +void +__sp_mut::lock() noexcept +{ + auto m = static_cast<__libcpp_mutex_t*>(__lx); + unsigned count = 0; + while (!__libcpp_mutex_trylock(m)) + { + if (++count > 16) + { + __libcpp_mutex_lock(m); + break; + } + this_thread::yield(); + } +} + +void +__sp_mut::unlock() noexcept +{ + __libcpp_mutex_unlock(static_cast<__libcpp_mutex_t*>(__lx)); +} + +__sp_mut& +__get_sp_mut(const void* p) +{ + static __sp_mut muts[__sp_mut_count] + { + &mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3], + &mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7], + &mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11], + &mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15] + }; + return muts[hash<const void*>()(p) & (__sp_mut_count-1)]; +} + +#endif // !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) + +void +declare_reachable(void*) +{ +} + +void +declare_no_pointers(char*, size_t) +{ +} + +void +undeclare_no_pointers(char*, size_t) +{ +} + +void* +__undeclare_reachable(void* p) +{ + return p; +} + +void* +align(size_t alignment, size_t size, void*& ptr, size_t& space) +{ + void* r = nullptr; + if (size <= space) + { + char* p1 = static_cast<char*>(ptr); + char* p2 = reinterpret_cast<char*>(reinterpret_cast<size_t>(p1 + (alignment - 1)) & -alignment); + size_t d = static_cast<size_t>(p2 - p1); + if (d <= space - size) + { + r = p2; + ptr = r; + space -= d; + } + } + return r; +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/mutex.cpp b/contrib/libs/cxxsupp/libcxx/src/mutex.cpp index 1a6d96e709..124d59bc64 100644 --- a/contrib/libs/cxxsupp/libcxx/src/mutex.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/mutex.cpp @@ -1,279 +1,279 @@ -//===------------------------- mutex.cpp ----------------------------------===// -// +//===------------------------- mutex.cpp ----------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "mutex" -#include "limits" -#include "system_error" -#if !defined(_LIBCPP_ABI_MICROSOFT) -#include "include/atomic_support.h" -#endif -#include "__undef_macros" - -#ifndef _LIBCPP_HAS_NO_THREADS -#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -#pragma comment(lib, "pthread") -#endif -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD -#ifndef _LIBCPP_HAS_NO_THREADS - -const defer_lock_t defer_lock{}; -const try_to_lock_t try_to_lock{}; -const adopt_lock_t adopt_lock{}; - -// ~mutex is defined elsewhere - -void -mutex::lock() -{ - int ec = __libcpp_mutex_lock(&__m_); - if (ec) - __throw_system_error(ec, "mutex lock failed"); -} - -bool -mutex::try_lock() noexcept -{ - return __libcpp_mutex_trylock(&__m_); -} - -void -mutex::unlock() noexcept -{ - int ec = __libcpp_mutex_unlock(&__m_); - (void)ec; - _LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed"); -} - -// recursive_mutex - -recursive_mutex::recursive_mutex() -{ - int ec = __libcpp_recursive_mutex_init(&__m_); - if (ec) - __throw_system_error(ec, "recursive_mutex constructor failed"); -} - -recursive_mutex::~recursive_mutex() -{ - int e = __libcpp_recursive_mutex_destroy(&__m_); - (void)e; - _LIBCPP_ASSERT(e == 0, "call to ~recursive_mutex() failed"); -} - -void -recursive_mutex::lock() -{ - int ec = __libcpp_recursive_mutex_lock(&__m_); - if (ec) - __throw_system_error(ec, "recursive_mutex lock failed"); -} - -void -recursive_mutex::unlock() noexcept -{ - int e = __libcpp_recursive_mutex_unlock(&__m_); - (void)e; - _LIBCPP_ASSERT(e == 0, "call to recursive_mutex::unlock() failed"); -} - -bool -recursive_mutex::try_lock() noexcept -{ - return __libcpp_recursive_mutex_trylock(&__m_); -} - -// timed_mutex - -timed_mutex::timed_mutex() - : __locked_(false) -{ -} - -timed_mutex::~timed_mutex() -{ - lock_guard<mutex> _(__m_); -} - -void -timed_mutex::lock() -{ - unique_lock<mutex> lk(__m_); - while (__locked_) - __cv_.wait(lk); - __locked_ = true; -} - -bool -timed_mutex::try_lock() noexcept -{ - unique_lock<mutex> lk(__m_, try_to_lock); - if (lk.owns_lock() && !__locked_) - { - __locked_ = true; - return true; - } - return false; -} - -void -timed_mutex::unlock() noexcept -{ - lock_guard<mutex> _(__m_); - __locked_ = false; - __cv_.notify_one(); -} - -// recursive_timed_mutex - -recursive_timed_mutex::recursive_timed_mutex() - : __count_(0), - __id_{} -{ -} - -recursive_timed_mutex::~recursive_timed_mutex() -{ - lock_guard<mutex> _(__m_); -} - -void -recursive_timed_mutex::lock() -{ - __thread_id id = this_thread::get_id(); - unique_lock<mutex> lk(__m_); - if (id ==__id_) - { - if (__count_ == numeric_limits<size_t>::max()) - __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached"); - ++__count_; - return; - } - while (__count_ != 0) - __cv_.wait(lk); - __count_ = 1; - __id_ = id; -} - -bool -recursive_timed_mutex::try_lock() noexcept -{ - __thread_id id = this_thread::get_id(); - unique_lock<mutex> lk(__m_, try_to_lock); - if (lk.owns_lock() && (__count_ == 0 || id == __id_)) - { - if (__count_ == numeric_limits<size_t>::max()) - return false; - ++__count_; - __id_ = id; - return true; - } - return false; -} - -void -recursive_timed_mutex::unlock() noexcept -{ - unique_lock<mutex> lk(__m_); - if (--__count_ == 0) - { - __id_.__reset(); - lk.unlock(); - __cv_.notify_one(); - } -} - -#endif // !_LIBCPP_HAS_NO_THREADS - -// If dispatch_once_f ever handles C++ exceptions, and if one can get to it -// without illegal macros (unexpected macros not beginning with _UpperCase or -// __lowercase), and if it stops spinning waiting threads, then call_once should -// call into dispatch_once_f instead of here. Relevant radar this code needs to -// keep in sync with: 7741191. - -#ifndef _LIBCPP_HAS_NO_THREADS -_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; -_LIBCPP_SAFE_STATIC static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; -#endif - -#ifdef _LIBCPP_ABI_MICROSOFT -void __call_once(volatile std::atomic<once_flag::_State_type>& flag, void* arg, +// +//===----------------------------------------------------------------------===// + +#include "mutex" +#include "limits" +#include "system_error" +#if !defined(_LIBCPP_ABI_MICROSOFT) +#include "include/atomic_support.h" +#endif +#include "__undef_macros" + +#ifndef _LIBCPP_HAS_NO_THREADS +#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +#pragma comment(lib, "pthread") +#endif +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD +#ifndef _LIBCPP_HAS_NO_THREADS + +const defer_lock_t defer_lock{}; +const try_to_lock_t try_to_lock{}; +const adopt_lock_t adopt_lock{}; + +// ~mutex is defined elsewhere + +void +mutex::lock() +{ + int ec = __libcpp_mutex_lock(&__m_); + if (ec) + __throw_system_error(ec, "mutex lock failed"); +} + +bool +mutex::try_lock() noexcept +{ + return __libcpp_mutex_trylock(&__m_); +} + +void +mutex::unlock() noexcept +{ + int ec = __libcpp_mutex_unlock(&__m_); + (void)ec; + _LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed"); +} + +// recursive_mutex + +recursive_mutex::recursive_mutex() +{ + int ec = __libcpp_recursive_mutex_init(&__m_); + if (ec) + __throw_system_error(ec, "recursive_mutex constructor failed"); +} + +recursive_mutex::~recursive_mutex() +{ + int e = __libcpp_recursive_mutex_destroy(&__m_); + (void)e; + _LIBCPP_ASSERT(e == 0, "call to ~recursive_mutex() failed"); +} + +void +recursive_mutex::lock() +{ + int ec = __libcpp_recursive_mutex_lock(&__m_); + if (ec) + __throw_system_error(ec, "recursive_mutex lock failed"); +} + +void +recursive_mutex::unlock() noexcept +{ + int e = __libcpp_recursive_mutex_unlock(&__m_); + (void)e; + _LIBCPP_ASSERT(e == 0, "call to recursive_mutex::unlock() failed"); +} + +bool +recursive_mutex::try_lock() noexcept +{ + return __libcpp_recursive_mutex_trylock(&__m_); +} + +// timed_mutex + +timed_mutex::timed_mutex() + : __locked_(false) +{ +} + +timed_mutex::~timed_mutex() +{ + lock_guard<mutex> _(__m_); +} + +void +timed_mutex::lock() +{ + unique_lock<mutex> lk(__m_); + while (__locked_) + __cv_.wait(lk); + __locked_ = true; +} + +bool +timed_mutex::try_lock() noexcept +{ + unique_lock<mutex> lk(__m_, try_to_lock); + if (lk.owns_lock() && !__locked_) + { + __locked_ = true; + return true; + } + return false; +} + +void +timed_mutex::unlock() noexcept +{ + lock_guard<mutex> _(__m_); + __locked_ = false; + __cv_.notify_one(); +} + +// recursive_timed_mutex + +recursive_timed_mutex::recursive_timed_mutex() + : __count_(0), + __id_{} +{ +} + +recursive_timed_mutex::~recursive_timed_mutex() +{ + lock_guard<mutex> _(__m_); +} + +void +recursive_timed_mutex::lock() +{ + __thread_id id = this_thread::get_id(); + unique_lock<mutex> lk(__m_); + if (id ==__id_) + { + if (__count_ == numeric_limits<size_t>::max()) + __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached"); + ++__count_; + return; + } + while (__count_ != 0) + __cv_.wait(lk); + __count_ = 1; + __id_ = id; +} + +bool +recursive_timed_mutex::try_lock() noexcept +{ + __thread_id id = this_thread::get_id(); + unique_lock<mutex> lk(__m_, try_to_lock); + if (lk.owns_lock() && (__count_ == 0 || id == __id_)) + { + if (__count_ == numeric_limits<size_t>::max()) + return false; + ++__count_; + __id_ = id; + return true; + } + return false; +} + +void +recursive_timed_mutex::unlock() noexcept +{ + unique_lock<mutex> lk(__m_); + if (--__count_ == 0) + { + __id_.__reset(); + lk.unlock(); + __cv_.notify_one(); + } +} + +#endif // !_LIBCPP_HAS_NO_THREADS + +// If dispatch_once_f ever handles C++ exceptions, and if one can get to it +// without illegal macros (unexpected macros not beginning with _UpperCase or +// __lowercase), and if it stops spinning waiting threads, then call_once should +// call into dispatch_once_f instead of here. Relevant radar this code needs to +// keep in sync with: 7741191. + +#ifndef _LIBCPP_HAS_NO_THREADS +_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; +_LIBCPP_SAFE_STATIC static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; +#endif + +#ifdef _LIBCPP_ABI_MICROSOFT +void __call_once(volatile std::atomic<once_flag::_State_type>& flag, void* arg, void (*func)(void*)) -#else -void __call_once(volatile once_flag::_State_type& flag, void* arg, +#else +void __call_once(volatile once_flag::_State_type& flag, void* arg, void (*func)(void*)) -#endif -{ -#if defined(_LIBCPP_HAS_NO_THREADS) - if (flag == 0) - { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - flag = 1; - func(arg); - flag = ~once_flag::_State_type(0); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - flag = 0; - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS - } -#else // !_LIBCPP_HAS_NO_THREADS - __libcpp_mutex_lock(&mut); - while (flag == 1) - __libcpp_condvar_wait(&cv, &mut); - if (flag == 0) - { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS -#ifdef _LIBCPP_ABI_MICROSOFT - flag.store(once_flag::_State_type(1)); -#else - __libcpp_relaxed_store(&flag, once_flag::_State_type(1)); -#endif - __libcpp_mutex_unlock(&mut); - func(arg); - __libcpp_mutex_lock(&mut); -#ifdef _LIBCPP_ABI_MICROSOFT - flag.store(~once_flag::_State_type(0), memory_order_release); -#else - __libcpp_atomic_store(&flag, ~once_flag::_State_type(0), - _AO_Release); -#endif - __libcpp_mutex_unlock(&mut); - __libcpp_condvar_broadcast(&cv); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - __libcpp_mutex_lock(&mut); -#ifdef _LIBCPP_ABI_MICROSOFT - flag.store(once_flag::_State_type(0), memory_order_relaxed); -#else - __libcpp_relaxed_store(&flag, once_flag::_State_type(0)); -#endif - __libcpp_mutex_unlock(&mut); - __libcpp_condvar_broadcast(&cv); - throw; - } -#endif // _LIBCPP_NO_EXCEPTIONS - } - else - __libcpp_mutex_unlock(&mut); -#endif // !_LIBCPP_HAS_NO_THREADS -} - -_LIBCPP_END_NAMESPACE_STD +#endif +{ +#if defined(_LIBCPP_HAS_NO_THREADS) + if (flag == 0) + { +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + flag = 1; + func(arg); + flag = ~once_flag::_State_type(0); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + flag = 0; + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + } +#else // !_LIBCPP_HAS_NO_THREADS + __libcpp_mutex_lock(&mut); + while (flag == 1) + __libcpp_condvar_wait(&cv, &mut); + if (flag == 0) + { +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS +#ifdef _LIBCPP_ABI_MICROSOFT + flag.store(once_flag::_State_type(1)); +#else + __libcpp_relaxed_store(&flag, once_flag::_State_type(1)); +#endif + __libcpp_mutex_unlock(&mut); + func(arg); + __libcpp_mutex_lock(&mut); +#ifdef _LIBCPP_ABI_MICROSOFT + flag.store(~once_flag::_State_type(0), memory_order_release); +#else + __libcpp_atomic_store(&flag, ~once_flag::_State_type(0), + _AO_Release); +#endif + __libcpp_mutex_unlock(&mut); + __libcpp_condvar_broadcast(&cv); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + __libcpp_mutex_lock(&mut); +#ifdef _LIBCPP_ABI_MICROSOFT + flag.store(once_flag::_State_type(0), memory_order_relaxed); +#else + __libcpp_relaxed_store(&flag, once_flag::_State_type(0)); +#endif + __libcpp_mutex_unlock(&mut); + __libcpp_condvar_broadcast(&cv); + throw; + } +#endif // _LIBCPP_NO_EXCEPTIONS + } + else + __libcpp_mutex_unlock(&mut); +#endif // !_LIBCPP_HAS_NO_THREADS +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/mutex_destructor.cpp b/contrib/libs/cxxsupp/libcxx/src/mutex_destructor.cpp index 857d7a2c48..07197c3fb4 100644 --- a/contrib/libs/cxxsupp/libcxx/src/mutex_destructor.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/mutex_destructor.cpp @@ -1,50 +1,50 @@ -//===--------------------- mutex_destructor.cpp ---------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -// Define ~mutex. -// -// On some platforms ~mutex has been made trivial and the definition is only -// provided for ABI compatibility. -// -// In order to avoid ODR violations within libc++ itself, we need to ensure -// that *nothing* sees the non-trivial mutex declaration. For this reason -// we re-declare the entire class in this file instead of using -// _LIBCPP_BUILDING_LIBRARY to change the definition in the headers. - -#include "__config" -#include "__threading_support" - -#if !defined(_LIBCPP_HAS_NO_THREADS) -#if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) -#define NEEDS_MUTEX_DESTRUCTOR -#endif -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -#ifdef NEEDS_MUTEX_DESTRUCTOR -class _LIBCPP_TYPE_VIS mutex -{ - __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; - -public: - _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY - constexpr mutex() = default; - mutex(const mutex&) = delete; - mutex& operator=(const mutex&) = delete; - ~mutex() noexcept; -}; - - -mutex::~mutex() noexcept -{ - __libcpp_mutex_destroy(&__m_); -} - -#endif // !_LIBCPP_HAS_NO_THREADS -_LIBCPP_END_NAMESPACE_STD +//===--------------------- mutex_destructor.cpp ---------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// Define ~mutex. +// +// On some platforms ~mutex has been made trivial and the definition is only +// provided for ABI compatibility. +// +// In order to avoid ODR violations within libc++ itself, we need to ensure +// that *nothing* sees the non-trivial mutex declaration. For this reason +// we re-declare the entire class in this file instead of using +// _LIBCPP_BUILDING_LIBRARY to change the definition in the headers. + +#include "__config" +#include "__threading_support" + +#if !defined(_LIBCPP_HAS_NO_THREADS) +#if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION) +#define NEEDS_MUTEX_DESTRUCTOR +#endif +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifdef NEEDS_MUTEX_DESTRUCTOR +class _LIBCPP_TYPE_VIS mutex +{ + __libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER; + +public: + _LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY + constexpr mutex() = default; + mutex(const mutex&) = delete; + mutex& operator=(const mutex&) = delete; + ~mutex() noexcept; +}; + + +mutex::~mutex() noexcept +{ + __libcpp_mutex_destroy(&__m_); +} + +#endif // !_LIBCPP_HAS_NO_THREADS +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/new.cpp b/contrib/libs/cxxsupp/libcxx/src/new.cpp index 98bc8c9a42..85afe3039e 100644 --- a/contrib/libs/cxxsupp/libcxx/src/new.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/new.cpp @@ -1,292 +1,292 @@ -//===--------------------------- new.cpp ----------------------------------===// -// +//===--------------------------- new.cpp ----------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include <stdlib.h> - -#include "new" - -#if defined(_LIBCPP_ABI_MICROSOFT) -# if !defined(_LIBCPP_ABI_VCRUNTIME) +// +//===----------------------------------------------------------------------===// + +#include <stdlib.h> + +#include "new" + +#if defined(_LIBCPP_ABI_MICROSOFT) +# if !defined(_LIBCPP_ABI_VCRUNTIME) # include "support/runtime/new_handler_fallback.ipp" # endif -#elif defined(LIBCXX_BUILDING_LIBCXXABI) +#elif defined(LIBCXX_BUILDING_LIBCXXABI) # include <cxxabi.h> #elif defined(LIBCXX_BUILDING_LIBCXXRT) # include <cxxabi.h> # include "support/runtime/new_handler_fallback.ipp" -#elif defined(__GLIBCXX__) +#elif defined(__GLIBCXX__) // nothing to do -#else -# include "support/runtime/new_handler_fallback.ipp" -#endif - -namespace std -{ - -#ifndef __GLIBCXX__ +#else +# include "support/runtime/new_handler_fallback.ipp" +#endif + +namespace std +{ + +#ifndef __GLIBCXX__ const nothrow_t nothrow{}; -#endif - -#ifndef LIBSTDCXX - -void -__throw_bad_alloc() -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - throw bad_alloc(); -#else - _VSTD::abort(); -#endif -} - -#endif // !LIBSTDCXX - -} // std - -#if !defined(__GLIBCXX__) && \ - !defined(_LIBCPP_ABI_VCRUNTIME) && \ - !defined(_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS) - -// Implement all new and delete operators as weak definitions -// in this shared library, so that they can be overridden by programs -// that define non-weak copies of the functions. - +#endif + +#ifndef LIBSTDCXX + +void +__throw_bad_alloc() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw bad_alloc(); +#else + _VSTD::abort(); +#endif +} + +#endif // !LIBSTDCXX + +} // std + +#if !defined(__GLIBCXX__) && \ + !defined(_LIBCPP_ABI_VCRUNTIME) && \ + !defined(_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS) + +// Implement all new and delete operators as weak definitions +// in this shared library, so that they can be overridden by programs +// that define non-weak copies of the functions. + +_LIBCPP_WEAK +void * +operator new(std::size_t size) _THROW_BAD_ALLOC +{ + if (size == 0) + size = 1; + void* p; + while ((p = ::malloc(size)) == nullptr) + { + // If malloc fails and there is a new_handler, + // call it to try free up memory. + std::new_handler nh = std::get_new_handler(); + if (nh) + nh(); + else +#ifndef _LIBCPP_NO_EXCEPTIONS + throw std::bad_alloc(); +#else + break; +#endif + } + return p; +} + _LIBCPP_WEAK -void * -operator new(std::size_t size) _THROW_BAD_ALLOC -{ - if (size == 0) - size = 1; - void* p; - while ((p = ::malloc(size)) == nullptr) - { - // If malloc fails and there is a new_handler, - // call it to try free up memory. - std::new_handler nh = std::get_new_handler(); - if (nh) - nh(); - else -#ifndef _LIBCPP_NO_EXCEPTIONS - throw std::bad_alloc(); -#else - break; -#endif - } - return p; -} - +void* +operator new(size_t size, const std::nothrow_t&) noexcept +{ + void* p = nullptr; +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + p = ::operator new(size); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + } +#endif // _LIBCPP_NO_EXCEPTIONS + return p; +} + _LIBCPP_WEAK -void* -operator new(size_t size, const std::nothrow_t&) noexcept -{ - void* p = nullptr; -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - p = ::operator new(size); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCPP_NO_EXCEPTIONS - return p; -} - +void* +operator new[](size_t size) _THROW_BAD_ALLOC +{ + return ::operator new(size); +} + _LIBCPP_WEAK -void* -operator new[](size_t size) _THROW_BAD_ALLOC -{ - return ::operator new(size); -} - -_LIBCPP_WEAK -void* -operator new[](size_t size, const std::nothrow_t&) noexcept -{ - void* p = nullptr; -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - p = ::operator new[](size); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCPP_NO_EXCEPTIONS - return p; -} - +void* +operator new[](size_t size, const std::nothrow_t&) noexcept +{ + void* p = nullptr; +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + p = ::operator new[](size); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + } +#endif // _LIBCPP_NO_EXCEPTIONS + return p; +} + _LIBCPP_WEAK -void -operator delete(void* ptr) noexcept -{ +void +operator delete(void* ptr) noexcept +{ ::free(ptr); -} - +} + +_LIBCPP_WEAK +void +operator delete(void* ptr, const std::nothrow_t&) noexcept +{ + ::operator delete(ptr); +} + +_LIBCPP_WEAK +void +operator delete(void* ptr, size_t) noexcept +{ + ::operator delete(ptr); +} + _LIBCPP_WEAK -void -operator delete(void* ptr, const std::nothrow_t&) noexcept -{ - ::operator delete(ptr); -} - +void +operator delete[] (void* ptr) noexcept +{ + ::operator delete(ptr); +} + _LIBCPP_WEAK -void -operator delete(void* ptr, size_t) noexcept -{ - ::operator delete(ptr); -} - -_LIBCPP_WEAK -void -operator delete[] (void* ptr) noexcept -{ - ::operator delete(ptr); -} - -_LIBCPP_WEAK -void -operator delete[] (void* ptr, const std::nothrow_t&) noexcept -{ - ::operator delete[](ptr); -} - -_LIBCPP_WEAK -void -operator delete[] (void* ptr, size_t) noexcept -{ - ::operator delete[](ptr); -} - +void +operator delete[] (void* ptr, const std::nothrow_t&) noexcept +{ + ::operator delete[](ptr); +} + +_LIBCPP_WEAK +void +operator delete[] (void* ptr, size_t) noexcept +{ + ::operator delete[](ptr); +} + #if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) - -_LIBCPP_WEAK -void * -operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC -{ - if (size == 0) - size = 1; - if (static_cast<size_t>(alignment) < sizeof(void*)) - alignment = std::align_val_t(sizeof(void*)); - - // Try allocating memory. If allocation fails and there is a new_handler, - // call it to try free up memory, and try again until it succeeds, or until - // the new_handler decides to terminate. - // - // If allocation fails and there is no new_handler, we throw bad_alloc - // (or return nullptr if exceptions are disabled). - void* p; - while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) - { - std::new_handler nh = std::get_new_handler(); - if (nh) - nh(); - else { -#ifndef _LIBCPP_NO_EXCEPTIONS - throw std::bad_alloc(); -#else - break; -#endif - } - } - return p; -} - -_LIBCPP_WEAK -void* -operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - void* p = nullptr; -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - p = ::operator new(size, alignment); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCPP_NO_EXCEPTIONS - return p; -} - + +_LIBCPP_WEAK +void * +operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC +{ + if (size == 0) + size = 1; + if (static_cast<size_t>(alignment) < sizeof(void*)) + alignment = std::align_val_t(sizeof(void*)); + + // Try allocating memory. If allocation fails and there is a new_handler, + // call it to try free up memory, and try again until it succeeds, or until + // the new_handler decides to terminate. + // + // If allocation fails and there is no new_handler, we throw bad_alloc + // (or return nullptr if exceptions are disabled). + void* p; + while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) + { + std::new_handler nh = std::get_new_handler(); + if (nh) + nh(); + else { +#ifndef _LIBCPP_NO_EXCEPTIONS + throw std::bad_alloc(); +#else + break; +#endif + } + } + return p; +} + +_LIBCPP_WEAK +void* +operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + void* p = nullptr; +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + p = ::operator new(size, alignment); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + } +#endif // _LIBCPP_NO_EXCEPTIONS + return p; +} + +_LIBCPP_WEAK +void* +operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC +{ + return ::operator new(size, alignment); +} + _LIBCPP_WEAK -void* -operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC -{ - return ::operator new(size, alignment); -} - -_LIBCPP_WEAK -void* -operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - void* p = nullptr; -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - p = ::operator new[](size, alignment); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - } -#endif // _LIBCPP_NO_EXCEPTIONS - return p; -} - +void* +operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + void* p = nullptr; +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + p = ::operator new[](size, alignment); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + } +#endif // _LIBCPP_NO_EXCEPTIONS + return p; +} + _LIBCPP_WEAK -void -operator delete(void* ptr, std::align_val_t) noexcept -{ - std::__libcpp_aligned_free(ptr); - } - +void +operator delete(void* ptr, std::align_val_t) noexcept +{ + std::__libcpp_aligned_free(ptr); + } + _LIBCPP_WEAK -void -operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - ::operator delete(ptr, alignment); -} - +void +operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + ::operator delete(ptr, alignment); +} + _LIBCPP_WEAK -void -operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept -{ - ::operator delete(ptr, alignment); -} - +void +operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept +{ + ::operator delete(ptr, alignment); +} + _LIBCPP_WEAK -void -operator delete[] (void* ptr, std::align_val_t alignment) noexcept -{ - ::operator delete(ptr, alignment); -} - +void +operator delete[] (void* ptr, std::align_val_t alignment) noexcept +{ + ::operator delete(ptr, alignment); +} + _LIBCPP_WEAK -void -operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept -{ - ::operator delete[](ptr, alignment); -} - +void +operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept +{ + ::operator delete[](ptr, alignment); +} + _LIBCPP_WEAK -void -operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept -{ - ::operator delete[](ptr, alignment); -} - +void +operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept +{ + ::operator delete[](ptr, alignment); +} + #endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION -#endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME && !_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS +#endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME && !_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS diff --git a/contrib/libs/cxxsupp/libcxx/src/optional.cpp b/contrib/libs/cxxsupp/libcxx/src/optional.cpp index 6f8698eff2..39405bec12 100644 --- a/contrib/libs/cxxsupp/libcxx/src/optional.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/optional.cpp @@ -1,42 +1,42 @@ -//===------------------------ optional.cpp --------------------------------===// -// +//===------------------------ optional.cpp --------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "optional" -#include "__availability" - -namespace std -{ - -bad_optional_access::~bad_optional_access() noexcept = default; - -const char* bad_optional_access::what() const noexcept { - return "bad_optional_access"; - } - -} // std - - -#include <experimental/__config> - -// Preserve std::experimental::bad_optional_access for ABI compatibility -// Even though it no longer exists in a header file -_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL - -class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access - : public std::logic_error -{ -public: +// +//===----------------------------------------------------------------------===// + +#include "optional" +#include "__availability" + +namespace std +{ + +bad_optional_access::~bad_optional_access() noexcept = default; + +const char* bad_optional_access::what() const noexcept { + return "bad_optional_access"; + } + +} // std + + +#include <experimental/__config> + +// Preserve std::experimental::bad_optional_access for ABI compatibility +// Even though it no longer exists in a header file +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL + +class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS bad_optional_access + : public std::logic_error +{ +public: bad_optional_access() : std::logic_error("Bad optional Access") {} - + // Get the key function ~bad_optional_access() into the dylib - virtual ~bad_optional_access() noexcept; -}; - -bad_optional_access::~bad_optional_access() noexcept = default; - -_LIBCPP_END_NAMESPACE_EXPERIMENTAL + virtual ~bad_optional_access() noexcept; +}; + +bad_optional_access::~bad_optional_access() noexcept = default; + +_LIBCPP_END_NAMESPACE_EXPERIMENTAL diff --git a/contrib/libs/cxxsupp/libcxx/src/random.cpp b/contrib/libs/cxxsupp/libcxx/src/random.cpp index d1610e6524..d9833b0900 100644 --- a/contrib/libs/cxxsupp/libcxx/src/random.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/random.cpp @@ -1,199 +1,199 @@ -//===-------------------------- random.cpp --------------------------------===// -// +//===-------------------------- random.cpp --------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include <__config> - -#if defined(_LIBCPP_USING_WIN32_RANDOM) -// Must be defined before including stdlib.h to enable rand_s(). -#define _CRT_RAND_S -#endif // defined(_LIBCPP_USING_WIN32_RANDOM) - -#include "limits" -#include "random" -#include "system_error" - -#if defined(__sun__) -#define rename solaris_headers_are_broken -#endif // defined(__sun__) - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> - -#if defined(_LIBCPP_USING_GETENTROPY) -#include <sys/random.h> -#elif defined(_LIBCPP_USING_DEV_RANDOM) -#include <fcntl.h> -#include <unistd.h> -#if __has_include(<sys/ioctl.h>) && __has_include(<linux/random.h>) -#include <sys/ioctl.h> -#include <linux/random.h> -#endif -#elif defined(_LIBCPP_USING_NACL_RANDOM) -#include <nacl/nacl_random.h> -#endif - - -_LIBCPP_BEGIN_NAMESPACE_STD - -#if defined(_LIBCPP_USING_GETENTROPY) - -random_device::random_device(const string& __token) -{ - if (__token != "/dev/urandom") - __throw_system_error(ENOENT, ("random device not supported " + __token).c_str()); -} - -random_device::~random_device() -{ -} - -unsigned -random_device::operator()() -{ - unsigned r; - size_t n = sizeof(r); - int err = getentropy(&r, n); - if (err) - __throw_system_error(errno, "random_device getentropy failed"); - return r; -} - -#elif defined(_LIBCPP_USING_ARC4_RANDOM) - -random_device::random_device(const string& __token) -{ - if (__token != "/dev/urandom") - __throw_system_error(ENOENT, ("random device not supported " + __token).c_str()); -} - -random_device::~random_device() -{ -} - -unsigned -random_device::operator()() -{ - return arc4random(); -} - -#elif defined(_LIBCPP_USING_DEV_RANDOM) - -random_device::random_device(const string& __token) - : __f_(open(__token.c_str(), O_RDONLY)) -{ - if (__f_ < 0) - __throw_system_error(errno, ("random_device failed to open " + __token).c_str()); -} - -random_device::~random_device() -{ - close(__f_); -} - -unsigned -random_device::operator()() -{ - unsigned r; - size_t n = sizeof(r); - char* p = reinterpret_cast<char*>(&r); - while (n > 0) - { - ssize_t s = read(__f_, p, n); - if (s == 0) - __throw_system_error(ENODATA, "random_device got EOF"); - if (s == -1) - { - if (errno != EINTR) - __throw_system_error(errno, "random_device got an unexpected error"); - continue; - } - n -= static_cast<size_t>(s); - p += static_cast<size_t>(s); - } - return r; -} - -#elif defined(_LIBCPP_USING_NACL_RANDOM) - -random_device::random_device(const string& __token) -{ - if (__token != "/dev/urandom") - __throw_system_error(ENOENT, ("random device not supported " + __token).c_str()); - int error = nacl_secure_random_init(); - if (error) - __throw_system_error(error, ("random device failed to open " + __token).c_str()); -} - -random_device::~random_device() -{ -} - -unsigned -random_device::operator()() -{ - unsigned r; - size_t n = sizeof(r); - size_t bytes_written; - int error = nacl_secure_random(&r, n, &bytes_written); - if (error != 0) - __throw_system_error(error, "random_device failed getting bytes"); - else if (bytes_written != n) - __throw_runtime_error("random_device failed to obtain enough bytes"); - return r; -} - -#elif defined(_LIBCPP_USING_WIN32_RANDOM) - -random_device::random_device(const string& __token) -{ - if (__token != "/dev/urandom") - __throw_system_error(ENOENT, ("random device not supported " + __token).c_str()); -} - -random_device::~random_device() -{ -} - -unsigned -random_device::operator()() -{ - unsigned r; - errno_t err = rand_s(&r); - if (err) - __throw_system_error(err, "random_device rand_s failed."); - return r; -} - -#else -#error "Random device not implemented for this architecture" -#endif - -double -random_device::entropy() const noexcept -{ -#if defined(_LIBCPP_USING_DEV_RANDOM) && defined(RNDGETENTCNT) - int ent; - if (::ioctl(__f_, RNDGETENTCNT, &ent) < 0) - return 0; - - if (ent < 0) - return 0; - - if (ent > std::numeric_limits<result_type>::digits) - return std::numeric_limits<result_type>::digits; - - return ent; -#elif defined(__OpenBSD__) - return std::numeric_limits<result_type>::digits; -#else - return 0; -#endif -} - -_LIBCPP_END_NAMESPACE_STD +// +//===----------------------------------------------------------------------===// + +#include <__config> + +#if defined(_LIBCPP_USING_WIN32_RANDOM) +// Must be defined before including stdlib.h to enable rand_s(). +#define _CRT_RAND_S +#endif // defined(_LIBCPP_USING_WIN32_RANDOM) + +#include "limits" +#include "random" +#include "system_error" + +#if defined(__sun__) +#define rename solaris_headers_are_broken +#endif // defined(__sun__) + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#if defined(_LIBCPP_USING_GETENTROPY) +#include <sys/random.h> +#elif defined(_LIBCPP_USING_DEV_RANDOM) +#include <fcntl.h> +#include <unistd.h> +#if __has_include(<sys/ioctl.h>) && __has_include(<linux/random.h>) +#include <sys/ioctl.h> +#include <linux/random.h> +#endif +#elif defined(_LIBCPP_USING_NACL_RANDOM) +#include <nacl/nacl_random.h> +#endif + + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if defined(_LIBCPP_USING_GETENTROPY) + +random_device::random_device(const string& __token) +{ + if (__token != "/dev/urandom") + __throw_system_error(ENOENT, ("random device not supported " + __token).c_str()); +} + +random_device::~random_device() +{ +} + +unsigned +random_device::operator()() +{ + unsigned r; + size_t n = sizeof(r); + int err = getentropy(&r, n); + if (err) + __throw_system_error(errno, "random_device getentropy failed"); + return r; +} + +#elif defined(_LIBCPP_USING_ARC4_RANDOM) + +random_device::random_device(const string& __token) +{ + if (__token != "/dev/urandom") + __throw_system_error(ENOENT, ("random device not supported " + __token).c_str()); +} + +random_device::~random_device() +{ +} + +unsigned +random_device::operator()() +{ + return arc4random(); +} + +#elif defined(_LIBCPP_USING_DEV_RANDOM) + +random_device::random_device(const string& __token) + : __f_(open(__token.c_str(), O_RDONLY)) +{ + if (__f_ < 0) + __throw_system_error(errno, ("random_device failed to open " + __token).c_str()); +} + +random_device::~random_device() +{ + close(__f_); +} + +unsigned +random_device::operator()() +{ + unsigned r; + size_t n = sizeof(r); + char* p = reinterpret_cast<char*>(&r); + while (n > 0) + { + ssize_t s = read(__f_, p, n); + if (s == 0) + __throw_system_error(ENODATA, "random_device got EOF"); + if (s == -1) + { + if (errno != EINTR) + __throw_system_error(errno, "random_device got an unexpected error"); + continue; + } + n -= static_cast<size_t>(s); + p += static_cast<size_t>(s); + } + return r; +} + +#elif defined(_LIBCPP_USING_NACL_RANDOM) + +random_device::random_device(const string& __token) +{ + if (__token != "/dev/urandom") + __throw_system_error(ENOENT, ("random device not supported " + __token).c_str()); + int error = nacl_secure_random_init(); + if (error) + __throw_system_error(error, ("random device failed to open " + __token).c_str()); +} + +random_device::~random_device() +{ +} + +unsigned +random_device::operator()() +{ + unsigned r; + size_t n = sizeof(r); + size_t bytes_written; + int error = nacl_secure_random(&r, n, &bytes_written); + if (error != 0) + __throw_system_error(error, "random_device failed getting bytes"); + else if (bytes_written != n) + __throw_runtime_error("random_device failed to obtain enough bytes"); + return r; +} + +#elif defined(_LIBCPP_USING_WIN32_RANDOM) + +random_device::random_device(const string& __token) +{ + if (__token != "/dev/urandom") + __throw_system_error(ENOENT, ("random device not supported " + __token).c_str()); +} + +random_device::~random_device() +{ +} + +unsigned +random_device::operator()() +{ + unsigned r; + errno_t err = rand_s(&r); + if (err) + __throw_system_error(err, "random_device rand_s failed."); + return r; +} + +#else +#error "Random device not implemented for this architecture" +#endif + +double +random_device::entropy() const noexcept +{ +#if defined(_LIBCPP_USING_DEV_RANDOM) && defined(RNDGETENTCNT) + int ent; + if (::ioctl(__f_, RNDGETENTCNT, &ent) < 0) + return 0; + + if (ent < 0) + return 0; + + if (ent > std::numeric_limits<result_type>::digits) + return std::numeric_limits<result_type>::digits; + + return ent; +#elif defined(__OpenBSD__) + return std::numeric_limits<result_type>::digits; +#else + return 0; +#endif +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/random_shuffle.cpp b/contrib/libs/cxxsupp/libcxx/src/random_shuffle.cpp index 11e77d453c..be2c47fa0d 100644 --- a/contrib/libs/cxxsupp/libcxx/src/random_shuffle.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/random_shuffle.cpp @@ -1,61 +1,61 @@ -//===----------------------- random_shuffle.cpp ---------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "algorithm" -#include "random" -#ifndef _LIBCPP_HAS_NO_THREADS -# include "mutex" -# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -# pragma comment(lib, "pthread") -# endif -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -#ifndef _LIBCPP_HAS_NO_THREADS -_LIBCPP_SAFE_STATIC static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER; -#endif -unsigned __rs_default::__c_ = 0; - -__rs_default::__rs_default() -{ -#ifndef _LIBCPP_HAS_NO_THREADS - __libcpp_mutex_lock(&__rs_mut); -#endif - __c_ = 1; -} - -__rs_default::__rs_default(const __rs_default&) -{ - ++__c_; -} - -__rs_default::~__rs_default() -{ -#ifndef _LIBCPP_HAS_NO_THREADS - if (--__c_ == 0) - __libcpp_mutex_unlock(&__rs_mut); -#else - --__c_; -#endif -} - -__rs_default::result_type -__rs_default::operator()() -{ - static mt19937 __rs_g; - return __rs_g(); -} - -__rs_default -__rs_get() -{ - return __rs_default(); -} - -_LIBCPP_END_NAMESPACE_STD +//===----------------------- random_shuffle.cpp ---------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "algorithm" +#include "random" +#ifndef _LIBCPP_HAS_NO_THREADS +# include "mutex" +# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +# pragma comment(lib, "pthread") +# endif +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifndef _LIBCPP_HAS_NO_THREADS +_LIBCPP_SAFE_STATIC static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER; +#endif +unsigned __rs_default::__c_ = 0; + +__rs_default::__rs_default() +{ +#ifndef _LIBCPP_HAS_NO_THREADS + __libcpp_mutex_lock(&__rs_mut); +#endif + __c_ = 1; +} + +__rs_default::__rs_default(const __rs_default&) +{ + ++__c_; +} + +__rs_default::~__rs_default() +{ +#ifndef _LIBCPP_HAS_NO_THREADS + if (--__c_ == 0) + __libcpp_mutex_unlock(&__rs_mut); +#else + --__c_; +#endif +} + +__rs_default::result_type +__rs_default::operator()() +{ + static mt19937 __rs_g; + return __rs_g(); +} + +__rs_default +__rs_get() +{ + return __rs_default(); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/regex.cpp b/contrib/libs/cxxsupp/libcxx/src/regex.cpp index e7c23deea4..d31e494874 100644 --- a/contrib/libs/cxxsupp/libcxx/src/regex.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/regex.cpp @@ -1,316 +1,316 @@ -//===-------------------------- regex.cpp ---------------------------------===// -// +//===-------------------------- regex.cpp ---------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "regex" -#include "algorithm" -#include "iterator" - -_LIBCPP_BEGIN_NAMESPACE_STD - -static -const char* -make_error_type_string(regex_constants::error_type ecode) -{ - switch (ecode) - { - case regex_constants::error_collate: - return "The expression contained an invalid collating element name."; - case regex_constants::error_ctype: - return "The expression contained an invalid character class name."; - case regex_constants::error_escape: - return "The expression contained an invalid escaped character, or a " - "trailing escape."; - case regex_constants::error_backref: - return "The expression contained an invalid back reference."; - case regex_constants::error_brack: - return "The expression contained mismatched [ and ]."; - case regex_constants::error_paren: - return "The expression contained mismatched ( and )."; - case regex_constants::error_brace: - return "The expression contained mismatched { and }."; - case regex_constants::error_badbrace: - return "The expression contained an invalid range in a {} expression."; - case regex_constants::error_range: - return "The expression contained an invalid character range, " - "such as [b-a] in most encodings."; - case regex_constants::error_space: - return "There was insufficient memory to convert the expression into " - "a finite state machine."; - case regex_constants::error_badrepeat: - return "One of *?+{ was not preceded by a valid regular expression."; - case regex_constants::error_complexity: - return "The complexity of an attempted match against a regular " - "expression exceeded a pre-set level."; - case regex_constants::error_stack: - return "There was insufficient memory to determine whether the regular " - "expression could match the specified character sequence."; - case regex_constants::__re_err_grammar: - return "An invalid regex grammar has been requested."; - case regex_constants::__re_err_empty: - return "An empty regex is not allowed in the POSIX grammar."; - case regex_constants::__re_err_parse: - return "The parser did not consume the entire regular expression."; - default: - break; - } - return "Unknown error type"; -} - -regex_error::regex_error(regex_constants::error_type ecode) - : runtime_error(make_error_type_string(ecode)), - __code_(ecode) -{} - +// +//===----------------------------------------------------------------------===// + +#include "regex" +#include "algorithm" +#include "iterator" + +_LIBCPP_BEGIN_NAMESPACE_STD + +static +const char* +make_error_type_string(regex_constants::error_type ecode) +{ + switch (ecode) + { + case regex_constants::error_collate: + return "The expression contained an invalid collating element name."; + case regex_constants::error_ctype: + return "The expression contained an invalid character class name."; + case regex_constants::error_escape: + return "The expression contained an invalid escaped character, or a " + "trailing escape."; + case regex_constants::error_backref: + return "The expression contained an invalid back reference."; + case regex_constants::error_brack: + return "The expression contained mismatched [ and ]."; + case regex_constants::error_paren: + return "The expression contained mismatched ( and )."; + case regex_constants::error_brace: + return "The expression contained mismatched { and }."; + case regex_constants::error_badbrace: + return "The expression contained an invalid range in a {} expression."; + case regex_constants::error_range: + return "The expression contained an invalid character range, " + "such as [b-a] in most encodings."; + case regex_constants::error_space: + return "There was insufficient memory to convert the expression into " + "a finite state machine."; + case regex_constants::error_badrepeat: + return "One of *?+{ was not preceded by a valid regular expression."; + case regex_constants::error_complexity: + return "The complexity of an attempted match against a regular " + "expression exceeded a pre-set level."; + case regex_constants::error_stack: + return "There was insufficient memory to determine whether the regular " + "expression could match the specified character sequence."; + case regex_constants::__re_err_grammar: + return "An invalid regex grammar has been requested."; + case regex_constants::__re_err_empty: + return "An empty regex is not allowed in the POSIX grammar."; + case regex_constants::__re_err_parse: + return "The parser did not consume the entire regular expression."; + default: + break; + } + return "Unknown error type"; +} + +regex_error::regex_error(regex_constants::error_type ecode) + : runtime_error(make_error_type_string(ecode)), + __code_(ecode) +{} + regex_error::~regex_error() throw() {} - -namespace { - -struct collationnames -{ - const char* elem_; - char char_; -}; - -const collationnames collatenames[] = -{ - {"A", 0x41}, - {"B", 0x42}, - {"C", 0x43}, - {"D", 0x44}, - {"E", 0x45}, - {"F", 0x46}, - {"G", 0x47}, - {"H", 0x48}, - {"I", 0x49}, - {"J", 0x4a}, - {"K", 0x4b}, - {"L", 0x4c}, - {"M", 0x4d}, - {"N", 0x4e}, - {"NUL", 0x00}, - {"O", 0x4f}, - {"P", 0x50}, - {"Q", 0x51}, - {"R", 0x52}, - {"S", 0x53}, - {"T", 0x54}, - {"U", 0x55}, - {"V", 0x56}, - {"W", 0x57}, - {"X", 0x58}, - {"Y", 0x59}, - {"Z", 0x5a}, - {"a", 0x61}, - {"alert", 0x07}, - {"ampersand", 0x26}, - {"apostrophe", 0x27}, - {"asterisk", 0x2a}, - {"b", 0x62}, - {"backslash", 0x5c}, - {"backspace", 0x08}, - {"c", 0x63}, - {"carriage-return", 0x0d}, - {"circumflex", 0x5e}, - {"circumflex-accent", 0x5e}, - {"colon", 0x3a}, - {"comma", 0x2c}, - {"commercial-at", 0x40}, - {"d", 0x64}, - {"dollar-sign", 0x24}, - {"e", 0x65}, - {"eight", 0x38}, - {"equals-sign", 0x3d}, - {"exclamation-mark", 0x21}, - {"f", 0x66}, - {"five", 0x35}, - {"form-feed", 0x0c}, - {"four", 0x34}, - {"full-stop", 0x2e}, - {"g", 0x67}, - {"grave-accent", 0x60}, - {"greater-than-sign", 0x3e}, - {"h", 0x68}, - {"hyphen", 0x2d}, - {"hyphen-minus", 0x2d}, - {"i", 0x69}, - {"j", 0x6a}, - {"k", 0x6b}, - {"l", 0x6c}, - {"left-brace", 0x7b}, - {"left-curly-bracket", 0x7b}, - {"left-parenthesis", 0x28}, - {"left-square-bracket", 0x5b}, - {"less-than-sign", 0x3c}, - {"low-line", 0x5f}, - {"m", 0x6d}, - {"n", 0x6e}, - {"newline", 0x0a}, - {"nine", 0x39}, - {"number-sign", 0x23}, - {"o", 0x6f}, - {"one", 0x31}, - {"p", 0x70}, - {"percent-sign", 0x25}, - {"period", 0x2e}, - {"plus-sign", 0x2b}, - {"q", 0x71}, - {"question-mark", 0x3f}, - {"quotation-mark", 0x22}, - {"r", 0x72}, - {"reverse-solidus", 0x5c}, - {"right-brace", 0x7d}, - {"right-curly-bracket", 0x7d}, - {"right-parenthesis", 0x29}, - {"right-square-bracket", 0x5d}, - {"s", 0x73}, - {"semicolon", 0x3b}, - {"seven", 0x37}, - {"six", 0x36}, - {"slash", 0x2f}, - {"solidus", 0x2f}, - {"space", 0x20}, - {"t", 0x74}, - {"tab", 0x09}, - {"three", 0x33}, - {"tilde", 0x7e}, - {"two", 0x32}, - {"u", 0x75}, - {"underscore", 0x5f}, - {"v", 0x76}, - {"vertical-line", 0x7c}, - {"vertical-tab", 0x0b}, - {"w", 0x77}, - {"x", 0x78}, - {"y", 0x79}, - {"z", 0x7a}, - {"zero", 0x30} -}; - -struct classnames -{ - const char* elem_; - regex_traits<char>::char_class_type mask_; -}; - -const classnames ClassNames[] = -{ - {"alnum", ctype_base::alnum}, - {"alpha", ctype_base::alpha}, - {"blank", ctype_base::blank}, - {"cntrl", ctype_base::cntrl}, - {"d", ctype_base::digit}, - {"digit", ctype_base::digit}, - {"graph", ctype_base::graph}, - {"lower", ctype_base::lower}, - {"print", ctype_base::print}, - {"punct", ctype_base::punct}, - {"s", ctype_base::space}, - {"space", ctype_base::space}, - {"upper", ctype_base::upper}, - {"w", regex_traits<char>::__regex_word}, - {"xdigit", ctype_base::xdigit} -}; - -struct use_strcmp -{ - bool operator()(const collationnames& x, const char* y) - {return strcmp(x.elem_, y) < 0;} - bool operator()(const classnames& x, const char* y) - {return strcmp(x.elem_, y) < 0;} -}; - -} - -string -__get_collation_name(const char* s) -{ - const collationnames* i = - _VSTD::lower_bound(begin(collatenames), end(collatenames), s, use_strcmp()); - string r; - if (i != end(collatenames) && strcmp(s, i->elem_) == 0) - r = char(i->char_); - return r; -} - -regex_traits<char>::char_class_type -__get_classname(const char* s, bool __icase) -{ - const classnames* i = - _VSTD::lower_bound(begin(ClassNames), end(ClassNames), s, use_strcmp()); - regex_traits<char>::char_class_type r = 0; - if (i != end(ClassNames) && strcmp(s, i->elem_) == 0) - { - r = i->mask_; - if (r == regex_traits<char>::__regex_word) - r |= ctype_base::alnum | ctype_base::upper | ctype_base::lower; - else if (__icase) - { - if (r & (ctype_base::lower | ctype_base::upper)) - r |= ctype_base::alpha; - } - } - return r; -} - -template <> -void -__match_any_but_newline<char>::__exec(__state& __s) const -{ - if (__s.__current_ != __s.__last_) - { - switch (*__s.__current_) - { - case '\r': - case '\n': - __s.__do_ = __state::__reject; - __s.__node_ = nullptr; - break; - default: - __s.__do_ = __state::__accept_and_consume; - ++__s.__current_; - __s.__node_ = this->first(); - break; - } - } - else - { - __s.__do_ = __state::__reject; - __s.__node_ = nullptr; - } -} - -template <> -void -__match_any_but_newline<wchar_t>::__exec(__state& __s) const -{ - if (__s.__current_ != __s.__last_) - { - switch (*__s.__current_) - { - case '\r': - case '\n': - case 0x2028: - case 0x2029: - __s.__do_ = __state::__reject; - __s.__node_ = nullptr; - break; - default: - __s.__do_ = __state::__accept_and_consume; - ++__s.__current_; - __s.__node_ = this->first(); - break; - } - } - else - { - __s.__do_ = __state::__reject; - __s.__node_ = nullptr; - } -} - -_LIBCPP_END_NAMESPACE_STD + +namespace { + +struct collationnames +{ + const char* elem_; + char char_; +}; + +const collationnames collatenames[] = +{ + {"A", 0x41}, + {"B", 0x42}, + {"C", 0x43}, + {"D", 0x44}, + {"E", 0x45}, + {"F", 0x46}, + {"G", 0x47}, + {"H", 0x48}, + {"I", 0x49}, + {"J", 0x4a}, + {"K", 0x4b}, + {"L", 0x4c}, + {"M", 0x4d}, + {"N", 0x4e}, + {"NUL", 0x00}, + {"O", 0x4f}, + {"P", 0x50}, + {"Q", 0x51}, + {"R", 0x52}, + {"S", 0x53}, + {"T", 0x54}, + {"U", 0x55}, + {"V", 0x56}, + {"W", 0x57}, + {"X", 0x58}, + {"Y", 0x59}, + {"Z", 0x5a}, + {"a", 0x61}, + {"alert", 0x07}, + {"ampersand", 0x26}, + {"apostrophe", 0x27}, + {"asterisk", 0x2a}, + {"b", 0x62}, + {"backslash", 0x5c}, + {"backspace", 0x08}, + {"c", 0x63}, + {"carriage-return", 0x0d}, + {"circumflex", 0x5e}, + {"circumflex-accent", 0x5e}, + {"colon", 0x3a}, + {"comma", 0x2c}, + {"commercial-at", 0x40}, + {"d", 0x64}, + {"dollar-sign", 0x24}, + {"e", 0x65}, + {"eight", 0x38}, + {"equals-sign", 0x3d}, + {"exclamation-mark", 0x21}, + {"f", 0x66}, + {"five", 0x35}, + {"form-feed", 0x0c}, + {"four", 0x34}, + {"full-stop", 0x2e}, + {"g", 0x67}, + {"grave-accent", 0x60}, + {"greater-than-sign", 0x3e}, + {"h", 0x68}, + {"hyphen", 0x2d}, + {"hyphen-minus", 0x2d}, + {"i", 0x69}, + {"j", 0x6a}, + {"k", 0x6b}, + {"l", 0x6c}, + {"left-brace", 0x7b}, + {"left-curly-bracket", 0x7b}, + {"left-parenthesis", 0x28}, + {"left-square-bracket", 0x5b}, + {"less-than-sign", 0x3c}, + {"low-line", 0x5f}, + {"m", 0x6d}, + {"n", 0x6e}, + {"newline", 0x0a}, + {"nine", 0x39}, + {"number-sign", 0x23}, + {"o", 0x6f}, + {"one", 0x31}, + {"p", 0x70}, + {"percent-sign", 0x25}, + {"period", 0x2e}, + {"plus-sign", 0x2b}, + {"q", 0x71}, + {"question-mark", 0x3f}, + {"quotation-mark", 0x22}, + {"r", 0x72}, + {"reverse-solidus", 0x5c}, + {"right-brace", 0x7d}, + {"right-curly-bracket", 0x7d}, + {"right-parenthesis", 0x29}, + {"right-square-bracket", 0x5d}, + {"s", 0x73}, + {"semicolon", 0x3b}, + {"seven", 0x37}, + {"six", 0x36}, + {"slash", 0x2f}, + {"solidus", 0x2f}, + {"space", 0x20}, + {"t", 0x74}, + {"tab", 0x09}, + {"three", 0x33}, + {"tilde", 0x7e}, + {"two", 0x32}, + {"u", 0x75}, + {"underscore", 0x5f}, + {"v", 0x76}, + {"vertical-line", 0x7c}, + {"vertical-tab", 0x0b}, + {"w", 0x77}, + {"x", 0x78}, + {"y", 0x79}, + {"z", 0x7a}, + {"zero", 0x30} +}; + +struct classnames +{ + const char* elem_; + regex_traits<char>::char_class_type mask_; +}; + +const classnames ClassNames[] = +{ + {"alnum", ctype_base::alnum}, + {"alpha", ctype_base::alpha}, + {"blank", ctype_base::blank}, + {"cntrl", ctype_base::cntrl}, + {"d", ctype_base::digit}, + {"digit", ctype_base::digit}, + {"graph", ctype_base::graph}, + {"lower", ctype_base::lower}, + {"print", ctype_base::print}, + {"punct", ctype_base::punct}, + {"s", ctype_base::space}, + {"space", ctype_base::space}, + {"upper", ctype_base::upper}, + {"w", regex_traits<char>::__regex_word}, + {"xdigit", ctype_base::xdigit} +}; + +struct use_strcmp +{ + bool operator()(const collationnames& x, const char* y) + {return strcmp(x.elem_, y) < 0;} + bool operator()(const classnames& x, const char* y) + {return strcmp(x.elem_, y) < 0;} +}; + +} + +string +__get_collation_name(const char* s) +{ + const collationnames* i = + _VSTD::lower_bound(begin(collatenames), end(collatenames), s, use_strcmp()); + string r; + if (i != end(collatenames) && strcmp(s, i->elem_) == 0) + r = char(i->char_); + return r; +} + +regex_traits<char>::char_class_type +__get_classname(const char* s, bool __icase) +{ + const classnames* i = + _VSTD::lower_bound(begin(ClassNames), end(ClassNames), s, use_strcmp()); + regex_traits<char>::char_class_type r = 0; + if (i != end(ClassNames) && strcmp(s, i->elem_) == 0) + { + r = i->mask_; + if (r == regex_traits<char>::__regex_word) + r |= ctype_base::alnum | ctype_base::upper | ctype_base::lower; + else if (__icase) + { + if (r & (ctype_base::lower | ctype_base::upper)) + r |= ctype_base::alpha; + } + } + return r; +} + +template <> +void +__match_any_but_newline<char>::__exec(__state& __s) const +{ + if (__s.__current_ != __s.__last_) + { + switch (*__s.__current_) + { + case '\r': + case '\n': + __s.__do_ = __state::__reject; + __s.__node_ = nullptr; + break; + default: + __s.__do_ = __state::__accept_and_consume; + ++__s.__current_; + __s.__node_ = this->first(); + break; + } + } + else + { + __s.__do_ = __state::__reject; + __s.__node_ = nullptr; + } +} + +template <> +void +__match_any_but_newline<wchar_t>::__exec(__state& __s) const +{ + if (__s.__current_ != __s.__last_) + { + switch (*__s.__current_) + { + case '\r': + case '\n': + case 0x2028: + case 0x2029: + __s.__do_ = __state::__reject; + __s.__node_ = nullptr; + break; + default: + __s.__do_ = __state::__accept_and_consume; + ++__s.__current_; + __s.__node_ = this->first(); + break; + } + } + else + { + __s.__do_ = __state::__reject; + __s.__node_ = nullptr; + } +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/shared_mutex.cpp b/contrib/libs/cxxsupp/libcxx/src/shared_mutex.cpp index fb84edec6f..5feef9f488 100644 --- a/contrib/libs/cxxsupp/libcxx/src/shared_mutex.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/shared_mutex.cpp @@ -1,118 +1,118 @@ -//===---------------------- shared_mutex.cpp ------------------------------===// -// +//===---------------------- shared_mutex.cpp ------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "__config" -#ifndef _LIBCPP_HAS_NO_THREADS - -#include "shared_mutex" -#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -#pragma comment(lib, "pthread") -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -// Shared Mutex Base -__shared_mutex_base::__shared_mutex_base() - : __state_(0) -{ -} - -// Exclusive ownership - -void -__shared_mutex_base::lock() -{ - unique_lock<mutex> lk(__mut_); - while (__state_ & __write_entered_) - __gate1_.wait(lk); - __state_ |= __write_entered_; - while (__state_ & __n_readers_) - __gate2_.wait(lk); -} - -bool -__shared_mutex_base::try_lock() -{ - unique_lock<mutex> lk(__mut_); - if (__state_ == 0) - { - __state_ = __write_entered_; - return true; - } - return false; -} - -void -__shared_mutex_base::unlock() -{ - lock_guard<mutex> _(__mut_); - __state_ = 0; - __gate1_.notify_all(); -} - -// Shared ownership - -void -__shared_mutex_base::lock_shared() -{ - unique_lock<mutex> lk(__mut_); - while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_) - __gate1_.wait(lk); - unsigned num_readers = (__state_ & __n_readers_) + 1; - __state_ &= ~__n_readers_; - __state_ |= num_readers; -} - -bool -__shared_mutex_base::try_lock_shared() -{ - unique_lock<mutex> lk(__mut_); - unsigned num_readers = __state_ & __n_readers_; - if (!(__state_ & __write_entered_) && num_readers != __n_readers_) - { - ++num_readers; - __state_ &= ~__n_readers_; - __state_ |= num_readers; - return true; - } - return false; -} - -void -__shared_mutex_base::unlock_shared() -{ - lock_guard<mutex> _(__mut_); - unsigned num_readers = (__state_ & __n_readers_) - 1; - __state_ &= ~__n_readers_; - __state_ |= num_readers; - if (__state_ & __write_entered_) - { - if (num_readers == 0) - __gate2_.notify_one(); - } - else - { - if (num_readers == __n_readers_ - 1) - __gate1_.notify_one(); - } -} - - -// Shared Timed Mutex -// These routines are here for ABI stability -shared_timed_mutex::shared_timed_mutex() : __base() {} -void shared_timed_mutex::lock() { return __base.lock(); } -bool shared_timed_mutex::try_lock() { return __base.try_lock(); } -void shared_timed_mutex::unlock() { return __base.unlock(); } -void shared_timed_mutex::lock_shared() { return __base.lock_shared(); } -bool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); } -void shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); } - -_LIBCPP_END_NAMESPACE_STD - -#endif // !_LIBCPP_HAS_NO_THREADS +// +//===----------------------------------------------------------------------===// + +#include "__config" +#ifndef _LIBCPP_HAS_NO_THREADS + +#include "shared_mutex" +#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +#pragma comment(lib, "pthread") +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Shared Mutex Base +__shared_mutex_base::__shared_mutex_base() + : __state_(0) +{ +} + +// Exclusive ownership + +void +__shared_mutex_base::lock() +{ + unique_lock<mutex> lk(__mut_); + while (__state_ & __write_entered_) + __gate1_.wait(lk); + __state_ |= __write_entered_; + while (__state_ & __n_readers_) + __gate2_.wait(lk); +} + +bool +__shared_mutex_base::try_lock() +{ + unique_lock<mutex> lk(__mut_); + if (__state_ == 0) + { + __state_ = __write_entered_; + return true; + } + return false; +} + +void +__shared_mutex_base::unlock() +{ + lock_guard<mutex> _(__mut_); + __state_ = 0; + __gate1_.notify_all(); +} + +// Shared ownership + +void +__shared_mutex_base::lock_shared() +{ + unique_lock<mutex> lk(__mut_); + while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_) + __gate1_.wait(lk); + unsigned num_readers = (__state_ & __n_readers_) + 1; + __state_ &= ~__n_readers_; + __state_ |= num_readers; +} + +bool +__shared_mutex_base::try_lock_shared() +{ + unique_lock<mutex> lk(__mut_); + unsigned num_readers = __state_ & __n_readers_; + if (!(__state_ & __write_entered_) && num_readers != __n_readers_) + { + ++num_readers; + __state_ &= ~__n_readers_; + __state_ |= num_readers; + return true; + } + return false; +} + +void +__shared_mutex_base::unlock_shared() +{ + lock_guard<mutex> _(__mut_); + unsigned num_readers = (__state_ & __n_readers_) - 1; + __state_ &= ~__n_readers_; + __state_ |= num_readers; + if (__state_ & __write_entered_) + { + if (num_readers == 0) + __gate2_.notify_one(); + } + else + { + if (num_readers == __n_readers_ - 1) + __gate1_.notify_one(); + } +} + + +// Shared Timed Mutex +// These routines are here for ABI stability +shared_timed_mutex::shared_timed_mutex() : __base() {} +void shared_timed_mutex::lock() { return __base.lock(); } +bool shared_timed_mutex::try_lock() { return __base.try_lock(); } +void shared_timed_mutex::unlock() { return __base.unlock(); } +void shared_timed_mutex::lock_shared() { return __base.lock_shared(); } +bool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); } +void shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); } + +_LIBCPP_END_NAMESPACE_STD + +#endif // !_LIBCPP_HAS_NO_THREADS diff --git a/contrib/libs/cxxsupp/libcxx/src/stdexcept.cpp b/contrib/libs/cxxsupp/libcxx/src/stdexcept.cpp index c818d4c3ae..f8f335f34a 100644 --- a/contrib/libs/cxxsupp/libcxx/src/stdexcept.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/stdexcept.cpp @@ -1,19 +1,19 @@ -//===------------------------ stdexcept.cpp -------------------------------===// -// +//===------------------------ stdexcept.cpp -------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "stdexcept" -#include "new" -#include "string" -#include "system_error" - +// +//===----------------------------------------------------------------------===// -#ifdef _LIBCPP_ABI_VCRUNTIME -#include "support/runtime/stdexcept_vcruntime.ipp" -#else -#include "support/runtime/stdexcept_default.ipp" -#endif +#include "stdexcept" +#include "new" +#include "string" +#include "system_error" + + +#ifdef _LIBCPP_ABI_VCRUNTIME +#include "support/runtime/stdexcept_vcruntime.ipp" +#else +#include "support/runtime/stdexcept_default.ipp" +#endif diff --git a/contrib/libs/cxxsupp/libcxx/src/string.cpp b/contrib/libs/cxxsupp/libcxx/src/string.cpp index 79f9a1b1f9..c8dae34272 100644 --- a/contrib/libs/cxxsupp/libcxx/src/string.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/string.cpp @@ -1,501 +1,501 @@ -//===------------------------- string.cpp ---------------------------------===// -// +//===------------------------- string.cpp ---------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "string" -#include "charconv" -#include "cstdlib" -#include "cerrno" -#include "limits" -#include "stdexcept" -#include <stdio.h> -#include "__debug" - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -# include "cwchar" -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -void __basic_string_common<true>::__throw_length_error() const { - _VSTD::__throw_length_error("basic_string"); -} - -void __basic_string_common<true>::__throw_out_of_range() const { - _VSTD::__throw_out_of_range("basic_string"); -} - -#define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__; -#ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION - _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) -# endif -#else - _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) -# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS - _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) -# endif -#endif -#undef _LIBCPP_EXTERN_TEMPLATE_DEFINE - -template string operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); - -namespace -{ - -template<typename T> -inline -void throw_helper( const string& msg ) -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - throw T( msg ); -#else - fprintf(stderr, "%s\n", msg.c_str()); - _VSTD::abort(); -#endif -} - -inline -void throw_from_string_out_of_range( const string& func ) -{ - throw_helper<out_of_range>(func + ": out of range"); -} - -inline -void throw_from_string_invalid_arg( const string& func ) -{ - throw_helper<invalid_argument>(func + ": no conversion"); -} - -// as_integer - -template<typename V, typename S, typename F> -inline -V -as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) -{ - typename S::value_type* ptr = nullptr; - const typename S::value_type* const p = str.c_str(); - typename remove_reference<decltype(errno)>::type errno_save = errno; - errno = 0; - V r = f(p, &ptr, base); - swap(errno, errno_save); - if (errno_save == ERANGE) - throw_from_string_out_of_range(func); - if (ptr == p) - throw_from_string_invalid_arg(func); - if (idx) - *idx = static_cast<size_t>(ptr - p); - return r; -} - -template<typename V, typename S> -inline -V -as_integer(const string& func, const S& s, size_t* idx, int base); - -// string -template<> -inline -int -as_integer(const string& func, const string& s, size_t* idx, int base ) -{ - // Use long as no Standard string to integer exists. - long r = as_integer_helper<long>( func, s, idx, base, strtol ); - if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) - throw_from_string_out_of_range(func); - return static_cast<int>(r); -} - -template<> -inline -long -as_integer(const string& func, const string& s, size_t* idx, int base ) -{ - return as_integer_helper<long>( func, s, idx, base, strtol ); -} - -template<> -inline -unsigned long -as_integer( const string& func, const string& s, size_t* idx, int base ) -{ - return as_integer_helper<unsigned long>( func, s, idx, base, strtoul ); -} - -template<> -inline -long long -as_integer( const string& func, const string& s, size_t* idx, int base ) -{ - return as_integer_helper<long long>( func, s, idx, base, strtoll ); -} - -template<> -inline -unsigned long long -as_integer( const string& func, const string& s, size_t* idx, int base ) -{ - return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull ); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -// wstring -template<> -inline -int -as_integer( const string& func, const wstring& s, size_t* idx, int base ) -{ - // Use long as no Stantard string to integer exists. - long r = as_integer_helper<long>( func, s, idx, base, wcstol ); - if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) - throw_from_string_out_of_range(func); - return static_cast<int>(r); -} - -template<> -inline -long -as_integer( const string& func, const wstring& s, size_t* idx, int base ) -{ - return as_integer_helper<long>( func, s, idx, base, wcstol ); -} - -template<> -inline -unsigned long -as_integer( const string& func, const wstring& s, size_t* idx, int base ) -{ - return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul ); -} - -template<> -inline -long long -as_integer( const string& func, const wstring& s, size_t* idx, int base ) -{ - return as_integer_helper<long long>( func, s, idx, base, wcstoll ); -} - -template<> -inline -unsigned long long -as_integer( const string& func, const wstring& s, size_t* idx, int base ) -{ - return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull ); -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -// as_float - +// +//===----------------------------------------------------------------------===// + +#include "string" +#include "charconv" +#include "cstdlib" +#include "cerrno" +#include "limits" +#include "stdexcept" +#include <stdio.h> +#include "__debug" + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +# include "cwchar" +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +void __basic_string_common<true>::__throw_length_error() const { + _VSTD::__throw_length_error("basic_string"); +} + +void __basic_string_common<true>::__throw_out_of_range() const { + _VSTD::__throw_out_of_range("basic_string"); +} + +#define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__; +#ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION + _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) +# endif +#else + _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) +# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS + _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) +# endif +#endif +#undef _LIBCPP_EXTERN_TEMPLATE_DEFINE + +template string operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); + +namespace +{ + +template<typename T> +inline +void throw_helper( const string& msg ) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw T( msg ); +#else + fprintf(stderr, "%s\n", msg.c_str()); + _VSTD::abort(); +#endif +} + +inline +void throw_from_string_out_of_range( const string& func ) +{ + throw_helper<out_of_range>(func + ": out of range"); +} + +inline +void throw_from_string_invalid_arg( const string& func ) +{ + throw_helper<invalid_argument>(func + ": no conversion"); +} + +// as_integer + template<typename V, typename S, typename F> -inline -V -as_float_helper(const string& func, const S& str, size_t* idx, F f ) -{ - typename S::value_type* ptr = nullptr; - const typename S::value_type* const p = str.c_str(); - typename remove_reference<decltype(errno)>::type errno_save = errno; - errno = 0; - V r = f(p, &ptr); - swap(errno, errno_save); - if (errno_save == ERANGE) - throw_from_string_out_of_range(func); - if (ptr == p) - throw_from_string_invalid_arg(func); - if (idx) - *idx = static_cast<size_t>(ptr - p); - return r; -} - -template<typename V, typename S> -inline -V as_float( const string& func, const S& s, size_t* idx = nullptr ); - -template<> -inline -float -as_float( const string& func, const string& s, size_t* idx ) -{ - return as_float_helper<float>( func, s, idx, strtof ); -} - -template<> -inline -double -as_float(const string& func, const string& s, size_t* idx ) -{ - return as_float_helper<double>( func, s, idx, strtod ); -} - -template<> -inline -long double -as_float( const string& func, const string& s, size_t* idx ) -{ - return as_float_helper<long double>( func, s, idx, strtold ); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template<> -inline -float -as_float( const string& func, const wstring& s, size_t* idx ) -{ - return as_float_helper<float>( func, s, idx, wcstof ); -} - -template<> -inline -double -as_float( const string& func, const wstring& s, size_t* idx ) -{ - return as_float_helper<double>( func, s, idx, wcstod ); -} - -template<> -inline -long double -as_float( const string& func, const wstring& s, size_t* idx ) -{ - return as_float_helper<long double>( func, s, idx, wcstold ); -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -} // unnamed namespace - -int -stoi(const string& str, size_t* idx, int base) -{ - return as_integer<int>( "stoi", str, idx, base ); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -int -stoi(const wstring& str, size_t* idx, int base) -{ - return as_integer<int>( "stoi", str, idx, base ); -} -#endif - -long -stol(const string& str, size_t* idx, int base) -{ - return as_integer<long>( "stol", str, idx, base ); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -long -stol(const wstring& str, size_t* idx, int base) -{ - return as_integer<long>( "stol", str, idx, base ); -} -#endif - -unsigned long -stoul(const string& str, size_t* idx, int base) -{ - return as_integer<unsigned long>( "stoul", str, idx, base ); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -unsigned long -stoul(const wstring& str, size_t* idx, int base) -{ - return as_integer<unsigned long>( "stoul", str, idx, base ); -} -#endif - -long long -stoll(const string& str, size_t* idx, int base) -{ - return as_integer<long long>( "stoll", str, idx, base ); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -long long -stoll(const wstring& str, size_t* idx, int base) -{ - return as_integer<long long>( "stoll", str, idx, base ); -} -#endif - -unsigned long long -stoull(const string& str, size_t* idx, int base) -{ - return as_integer<unsigned long long>( "stoull", str, idx, base ); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -unsigned long long -stoull(const wstring& str, size_t* idx, int base) -{ - return as_integer<unsigned long long>( "stoull", str, idx, base ); -} -#endif - -float -stof(const string& str, size_t* idx) -{ - return as_float<float>( "stof", str, idx ); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -float -stof(const wstring& str, size_t* idx) -{ - return as_float<float>( "stof", str, idx ); -} -#endif - -double -stod(const string& str, size_t* idx) -{ - return as_float<double>( "stod", str, idx ); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -double -stod(const wstring& str, size_t* idx) -{ - return as_float<double>( "stod", str, idx ); -} -#endif - -long double -stold(const string& str, size_t* idx) -{ - return as_float<long double>( "stold", str, idx ); -} - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -long double -stold(const wstring& str, size_t* idx) -{ - return as_float<long double>( "stold", str, idx ); -} -#endif - -// to_string - -namespace -{ - -// as_string - -template<typename S, typename P, typename V > -inline -S -as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) -{ - typedef typename S::size_type size_type; - size_type available = s.size(); - while (true) - { - int status = sprintf_like(&s[0], available + 1, fmt, a); - if ( status >= 0 ) - { - size_type used = static_cast<size_type>(status); - if ( used <= available ) - { - s.resize( used ); - break; - } - available = used; // Assume this is advice of how much space we need. - } - else - available = available * 2 + 1; - s.resize(available); - } - return s; -} - -template <class S> -struct initial_string; - -template <> -struct initial_string<string> -{ - string - operator()() const - { - string s; - s.resize(s.capacity()); - return s; - } -}; - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -template <> -struct initial_string<wstring> -{ - wstring - operator()() const - { - wstring s(20, wchar_t()); - s.resize(s.capacity()); - return s; - } -}; - -typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); - -inline -wide_printf -get_swprintf() -{ -#ifndef _LIBCPP_MSVCRT - return swprintf; -#else - return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf); -#endif -} -#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS - -template <typename S, typename V> -S i_to_string(V v) -{ -// numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. -// For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), -// so we need +1 here. - constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10 - char buf[bufsize]; - const auto res = to_chars(buf, buf + bufsize, v); - _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value"); - return S(buf, res.ptr); -} - -} // unnamed namespace - -string to_string (int val) { return i_to_string< string>(val); } -string to_string (long val) { return i_to_string< string>(val); } -string to_string (long long val) { return i_to_string< string>(val); } -string to_string (unsigned val) { return i_to_string< string>(val); } -string to_string (unsigned long val) { return i_to_string< string>(val); } -string to_string (unsigned long long val) { return i_to_string< string>(val); } - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -wstring to_wstring(int val) { return i_to_string<wstring>(val); } -wstring to_wstring(long val) { return i_to_string<wstring>(val); } -wstring to_wstring(long long val) { return i_to_string<wstring>(val); } -wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); } -wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); } -wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); } -#endif - -string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } -string to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } -string to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); } - -#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS -wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } -wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } -wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); } -#endif - -_LIBCPP_END_NAMESPACE_STD +inline +V +as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) +{ + typename S::value_type* ptr = nullptr; + const typename S::value_type* const p = str.c_str(); + typename remove_reference<decltype(errno)>::type errno_save = errno; + errno = 0; + V r = f(p, &ptr, base); + swap(errno, errno_save); + if (errno_save == ERANGE) + throw_from_string_out_of_range(func); + if (ptr == p) + throw_from_string_invalid_arg(func); + if (idx) + *idx = static_cast<size_t>(ptr - p); + return r; +} + +template<typename V, typename S> +inline +V +as_integer(const string& func, const S& s, size_t* idx, int base); + +// string +template<> +inline +int +as_integer(const string& func, const string& s, size_t* idx, int base ) +{ + // Use long as no Standard string to integer exists. + long r = as_integer_helper<long>( func, s, idx, base, strtol ); + if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) + throw_from_string_out_of_range(func); + return static_cast<int>(r); +} + +template<> +inline +long +as_integer(const string& func, const string& s, size_t* idx, int base ) +{ + return as_integer_helper<long>( func, s, idx, base, strtol ); +} + +template<> +inline +unsigned long +as_integer( const string& func, const string& s, size_t* idx, int base ) +{ + return as_integer_helper<unsigned long>( func, s, idx, base, strtoul ); +} + +template<> +inline +long long +as_integer( const string& func, const string& s, size_t* idx, int base ) +{ + return as_integer_helper<long long>( func, s, idx, base, strtoll ); +} + +template<> +inline +unsigned long long +as_integer( const string& func, const string& s, size_t* idx, int base ) +{ + return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull ); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +// wstring +template<> +inline +int +as_integer( const string& func, const wstring& s, size_t* idx, int base ) +{ + // Use long as no Stantard string to integer exists. + long r = as_integer_helper<long>( func, s, idx, base, wcstol ); + if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) + throw_from_string_out_of_range(func); + return static_cast<int>(r); +} + +template<> +inline +long +as_integer( const string& func, const wstring& s, size_t* idx, int base ) +{ + return as_integer_helper<long>( func, s, idx, base, wcstol ); +} + +template<> +inline +unsigned long +as_integer( const string& func, const wstring& s, size_t* idx, int base ) +{ + return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul ); +} + +template<> +inline +long long +as_integer( const string& func, const wstring& s, size_t* idx, int base ) +{ + return as_integer_helper<long long>( func, s, idx, base, wcstoll ); +} + +template<> +inline +unsigned long long +as_integer( const string& func, const wstring& s, size_t* idx, int base ) +{ + return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull ); +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +// as_float + +template<typename V, typename S, typename F> +inline +V +as_float_helper(const string& func, const S& str, size_t* idx, F f ) +{ + typename S::value_type* ptr = nullptr; + const typename S::value_type* const p = str.c_str(); + typename remove_reference<decltype(errno)>::type errno_save = errno; + errno = 0; + V r = f(p, &ptr); + swap(errno, errno_save); + if (errno_save == ERANGE) + throw_from_string_out_of_range(func); + if (ptr == p) + throw_from_string_invalid_arg(func); + if (idx) + *idx = static_cast<size_t>(ptr - p); + return r; +} + +template<typename V, typename S> +inline +V as_float( const string& func, const S& s, size_t* idx = nullptr ); + +template<> +inline +float +as_float( const string& func, const string& s, size_t* idx ) +{ + return as_float_helper<float>( func, s, idx, strtof ); +} + +template<> +inline +double +as_float(const string& func, const string& s, size_t* idx ) +{ + return as_float_helper<double>( func, s, idx, strtod ); +} + +template<> +inline +long double +as_float( const string& func, const string& s, size_t* idx ) +{ + return as_float_helper<long double>( func, s, idx, strtold ); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template<> +inline +float +as_float( const string& func, const wstring& s, size_t* idx ) +{ + return as_float_helper<float>( func, s, idx, wcstof ); +} + +template<> +inline +double +as_float( const string& func, const wstring& s, size_t* idx ) +{ + return as_float_helper<double>( func, s, idx, wcstod ); +} + +template<> +inline +long double +as_float( const string& func, const wstring& s, size_t* idx ) +{ + return as_float_helper<long double>( func, s, idx, wcstold ); +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +} // unnamed namespace + +int +stoi(const string& str, size_t* idx, int base) +{ + return as_integer<int>( "stoi", str, idx, base ); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +int +stoi(const wstring& str, size_t* idx, int base) +{ + return as_integer<int>( "stoi", str, idx, base ); +} +#endif + +long +stol(const string& str, size_t* idx, int base) +{ + return as_integer<long>( "stol", str, idx, base ); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +long +stol(const wstring& str, size_t* idx, int base) +{ + return as_integer<long>( "stol", str, idx, base ); +} +#endif + +unsigned long +stoul(const string& str, size_t* idx, int base) +{ + return as_integer<unsigned long>( "stoul", str, idx, base ); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +unsigned long +stoul(const wstring& str, size_t* idx, int base) +{ + return as_integer<unsigned long>( "stoul", str, idx, base ); +} +#endif + +long long +stoll(const string& str, size_t* idx, int base) +{ + return as_integer<long long>( "stoll", str, idx, base ); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +long long +stoll(const wstring& str, size_t* idx, int base) +{ + return as_integer<long long>( "stoll", str, idx, base ); +} +#endif + +unsigned long long +stoull(const string& str, size_t* idx, int base) +{ + return as_integer<unsigned long long>( "stoull", str, idx, base ); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +unsigned long long +stoull(const wstring& str, size_t* idx, int base) +{ + return as_integer<unsigned long long>( "stoull", str, idx, base ); +} +#endif + +float +stof(const string& str, size_t* idx) +{ + return as_float<float>( "stof", str, idx ); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +float +stof(const wstring& str, size_t* idx) +{ + return as_float<float>( "stof", str, idx ); +} +#endif + +double +stod(const string& str, size_t* idx) +{ + return as_float<double>( "stod", str, idx ); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +double +stod(const wstring& str, size_t* idx) +{ + return as_float<double>( "stod", str, idx ); +} +#endif + +long double +stold(const string& str, size_t* idx) +{ + return as_float<long double>( "stold", str, idx ); +} + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +long double +stold(const wstring& str, size_t* idx) +{ + return as_float<long double>( "stold", str, idx ); +} +#endif + +// to_string + +namespace +{ + +// as_string + +template<typename S, typename P, typename V > +inline +S +as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) +{ + typedef typename S::size_type size_type; + size_type available = s.size(); + while (true) + { + int status = sprintf_like(&s[0], available + 1, fmt, a); + if ( status >= 0 ) + { + size_type used = static_cast<size_type>(status); + if ( used <= available ) + { + s.resize( used ); + break; + } + available = used; // Assume this is advice of how much space we need. + } + else + available = available * 2 + 1; + s.resize(available); + } + return s; +} + +template <class S> +struct initial_string; + +template <> +struct initial_string<string> +{ + string + operator()() const + { + string s; + s.resize(s.capacity()); + return s; + } +}; + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +template <> +struct initial_string<wstring> +{ + wstring + operator()() const + { + wstring s(20, wchar_t()); + s.resize(s.capacity()); + return s; + } +}; + +typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); + +inline +wide_printf +get_swprintf() +{ +#ifndef _LIBCPP_MSVCRT + return swprintf; +#else + return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf); +#endif +} +#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS + +template <typename S, typename V> +S i_to_string(V v) +{ +// numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. +// For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), +// so we need +1 here. + constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10 + char buf[bufsize]; + const auto res = to_chars(buf, buf + bufsize, v); + _LIBCPP_ASSERT(res.ec == errc(), "bufsize must be large enough to accomodate the value"); + return S(buf, res.ptr); +} + +} // unnamed namespace + +string to_string (int val) { return i_to_string< string>(val); } +string to_string (long val) { return i_to_string< string>(val); } +string to_string (long long val) { return i_to_string< string>(val); } +string to_string (unsigned val) { return i_to_string< string>(val); } +string to_string (unsigned long val) { return i_to_string< string>(val); } +string to_string (unsigned long long val) { return i_to_string< string>(val); } + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +wstring to_wstring(int val) { return i_to_string<wstring>(val); } +wstring to_wstring(long val) { return i_to_string<wstring>(val); } +wstring to_wstring(long long val) { return i_to_string<wstring>(val); } +wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); } +wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); } +wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); } +#endif + +string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } +string to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } +string to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); } + +#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS +wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } +wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } +wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); } +#endif + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/strstream.cpp b/contrib/libs/cxxsupp/libcxx/src/strstream.cpp index 6eafbf4bc2..ae66806833 100644 --- a/contrib/libs/cxxsupp/libcxx/src/strstream.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/strstream.cpp @@ -1,335 +1,335 @@ -//===------------------------ strstream.cpp -------------------------------===// -// +//===------------------------ strstream.cpp -------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "strstream" -#include "algorithm" -#include "climits" -#include "cstring" -#include "cstdlib" -#include "__debug" -#include "__undef_macros" - -_LIBCPP_BEGIN_NAMESPACE_STD - -strstreambuf::strstreambuf(streamsize __alsize) - : __strmode_(__dynamic), - __alsize_(__alsize), - __palloc_(nullptr), - __pfree_(nullptr) -{ -} - -strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*)) - : __strmode_(__dynamic), - __alsize_(__default_alsize), - __palloc_(__palloc), - __pfree_(__pfree) -{ -} - -void -strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg) -{ - if (__n == 0) - __n = static_cast<streamsize>(strlen(__gnext)); - else if (__n < 0) - __n = INT_MAX; - if (__pbeg == nullptr) - setg(__gnext, __gnext, __gnext + __n); - else - { - setg(__gnext, __gnext, __pbeg); - setp(__pbeg, __pbeg + __n); - } -} - -strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg) - : __strmode_(), - __alsize_(__default_alsize), - __palloc_(nullptr), - __pfree_(nullptr) -{ - __init(__gnext, __n, __pbeg); -} - -strstreambuf::strstreambuf(const char* __gnext, streamsize __n) - : __strmode_(__constant), - __alsize_(__default_alsize), - __palloc_(nullptr), - __pfree_(nullptr) -{ - __init(const_cast<char *>(__gnext), __n, nullptr); -} - -strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg) - : __strmode_(), - __alsize_(__default_alsize), - __palloc_(nullptr), - __pfree_(nullptr) -{ - __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg)); -} - -strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n) - : __strmode_(__constant), - __alsize_(__default_alsize), - __palloc_(nullptr), - __pfree_(nullptr) -{ - __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr); -} - -strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg) - : __strmode_(), - __alsize_(__default_alsize), - __palloc_(nullptr), - __pfree_(nullptr) -{ - __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg)); -} - -strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n) - : __strmode_(__constant), - __alsize_(__default_alsize), - __palloc_(nullptr), - __pfree_(nullptr) -{ - __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr); -} - -strstreambuf::~strstreambuf() -{ - if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0) - { - if (__pfree_) - __pfree_(eback()); - else - delete [] eback(); - } -} - -void -strstreambuf::swap(strstreambuf& __rhs) -{ - streambuf::swap(__rhs); - _VSTD::swap(__strmode_, __rhs.__strmode_); - _VSTD::swap(__alsize_, __rhs.__alsize_); - _VSTD::swap(__palloc_, __rhs.__palloc_); - _VSTD::swap(__pfree_, __rhs.__pfree_); -} - -void -strstreambuf::freeze(bool __freezefl) -{ - if (__strmode_ & __dynamic) - { - if (__freezefl) - __strmode_ |= __frozen; - else - __strmode_ &= ~__frozen; - } -} - -char* -strstreambuf::str() -{ - if (__strmode_ & __dynamic) - __strmode_ |= __frozen; - return eback(); -} - -int -strstreambuf::pcount() const -{ - return static_cast<int>(pptr() - pbase()); -} - -strstreambuf::int_type -strstreambuf::overflow(int_type __c) -{ - if (__c == EOF) - return int_type(0); - if (pptr() == epptr()) - { - if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0) - return int_type(EOF); - size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback()); - size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size); - if (new_size == 0) - new_size = __default_alsize; - char* buf = nullptr; - if (__palloc_) - buf = static_cast<char*>(__palloc_(new_size)); - else - buf = new char[new_size]; - if (buf == nullptr) - return int_type(EOF); - if (old_size != 0) { - _LIBCPP_ASSERT(eback(), "overflow copying from NULL"); - memcpy(buf, eback(), static_cast<size_t>(old_size)); - } - ptrdiff_t ninp = gptr() - eback(); - ptrdiff_t einp = egptr() - eback(); - ptrdiff_t nout = pptr() - pbase(); - if (__strmode_ & __allocated) - { - if (__pfree_) - __pfree_(eback()); - else - delete [] eback(); - } - setg(buf, buf + ninp, buf + einp); - setp(buf + einp, buf + new_size); - __pbump(nout); - __strmode_ |= __allocated; - } - *pptr() = static_cast<char>(__c); - pbump(1); - return int_type(static_cast<unsigned char>(__c)); -} - -strstreambuf::int_type -strstreambuf::pbackfail(int_type __c) -{ - if (eback() == gptr()) - return EOF; - if (__c == EOF) - { - gbump(-1); - return int_type(0); - } - if (__strmode_ & __constant) - { - if (gptr()[-1] == static_cast<char>(__c)) - { - gbump(-1); - return __c; - } - return EOF; - } - gbump(-1); - *gptr() = static_cast<char>(__c); - return __c; -} - -strstreambuf::int_type -strstreambuf::underflow() -{ - if (gptr() == egptr()) - { - if (egptr() >= pptr()) - return EOF; - setg(eback(), gptr(), pptr()); - } - return int_type(static_cast<unsigned char>(*gptr())); -} - -strstreambuf::pos_type -strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which) -{ - off_type __p(-1); - bool pos_in = (__which & ios::in) != 0; - bool pos_out = (__which & ios::out) != 0; - bool legal = false; - switch (__way) - { - case ios::beg: - case ios::end: - if (pos_in || pos_out) - legal = true; - break; - case ios::cur: - if (pos_in != pos_out) - legal = true; - break; - } - if (pos_in && gptr() == nullptr) - legal = false; - if (pos_out && pptr() == nullptr) - legal = false; - if (legal) - { - off_type newoff; - char* seekhigh = epptr() ? epptr() : egptr(); - switch (__way) - { - case ios::beg: - newoff = 0; - break; - case ios::cur: - newoff = (pos_in ? gptr() : pptr()) - eback(); - break; - case ios::end: - newoff = seekhigh - eback(); - break; - default: - _LIBCPP_UNREACHABLE(); - } - newoff += __off; - if (0 <= newoff && newoff <= seekhigh - eback()) - { - char* newpos = eback() + newoff; - if (pos_in) - setg(eback(), newpos, _VSTD::max(newpos, egptr())); - if (pos_out) - { - // min(pbase, newpos), newpos, epptr() - __off = epptr() - newpos; - setp(min(pbase(), newpos), epptr()); - __pbump((epptr() - pbase()) - __off); - } - __p = newoff; - } - } - return pos_type(__p); -} - -strstreambuf::pos_type -strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which) -{ - off_type __p(-1); - bool pos_in = (__which & ios::in) != 0; - bool pos_out = (__which & ios::out) != 0; - if (pos_in || pos_out) - { - if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr))) - { - off_type newoff = __sp; - char* seekhigh = epptr() ? epptr() : egptr(); - if (0 <= newoff && newoff <= seekhigh - eback()) - { - char* newpos = eback() + newoff; - if (pos_in) - setg(eback(), newpos, _VSTD::max(newpos, egptr())); - if (pos_out) - { - // min(pbase, newpos), newpos, epptr() - off_type temp = epptr() - newpos; - setp(min(pbase(), newpos), epptr()); - __pbump((epptr() - pbase()) - temp); - } - __p = newoff; - } - } - } - return pos_type(__p); -} - -istrstream::~istrstream() -{ -} - -ostrstream::~ostrstream() -{ -} - -strstream::~strstream() -{ -} - -_LIBCPP_END_NAMESPACE_STD +// +//===----------------------------------------------------------------------===// + +#include "strstream" +#include "algorithm" +#include "climits" +#include "cstring" +#include "cstdlib" +#include "__debug" +#include "__undef_macros" + +_LIBCPP_BEGIN_NAMESPACE_STD + +strstreambuf::strstreambuf(streamsize __alsize) + : __strmode_(__dynamic), + __alsize_(__alsize), + __palloc_(nullptr), + __pfree_(nullptr) +{ +} + +strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*)) + : __strmode_(__dynamic), + __alsize_(__default_alsize), + __palloc_(__palloc), + __pfree_(__pfree) +{ +} + +void +strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg) +{ + if (__n == 0) + __n = static_cast<streamsize>(strlen(__gnext)); + else if (__n < 0) + __n = INT_MAX; + if (__pbeg == nullptr) + setg(__gnext, __gnext, __gnext + __n); + else + { + setg(__gnext, __gnext, __pbeg); + setp(__pbeg, __pbeg + __n); + } +} + +strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg) + : __strmode_(), + __alsize_(__default_alsize), + __palloc_(nullptr), + __pfree_(nullptr) +{ + __init(__gnext, __n, __pbeg); +} + +strstreambuf::strstreambuf(const char* __gnext, streamsize __n) + : __strmode_(__constant), + __alsize_(__default_alsize), + __palloc_(nullptr), + __pfree_(nullptr) +{ + __init(const_cast<char *>(__gnext), __n, nullptr); +} + +strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg) + : __strmode_(), + __alsize_(__default_alsize), + __palloc_(nullptr), + __pfree_(nullptr) +{ + __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg)); +} + +strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n) + : __strmode_(__constant), + __alsize_(__default_alsize), + __palloc_(nullptr), + __pfree_(nullptr) +{ + __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr); +} + +strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg) + : __strmode_(), + __alsize_(__default_alsize), + __palloc_(nullptr), + __pfree_(nullptr) +{ + __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg)); +} + +strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n) + : __strmode_(__constant), + __alsize_(__default_alsize), + __palloc_(nullptr), + __pfree_(nullptr) +{ + __init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr); +} + +strstreambuf::~strstreambuf() +{ + if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0) + { + if (__pfree_) + __pfree_(eback()); + else + delete [] eback(); + } +} + +void +strstreambuf::swap(strstreambuf& __rhs) +{ + streambuf::swap(__rhs); + _VSTD::swap(__strmode_, __rhs.__strmode_); + _VSTD::swap(__alsize_, __rhs.__alsize_); + _VSTD::swap(__palloc_, __rhs.__palloc_); + _VSTD::swap(__pfree_, __rhs.__pfree_); +} + +void +strstreambuf::freeze(bool __freezefl) +{ + if (__strmode_ & __dynamic) + { + if (__freezefl) + __strmode_ |= __frozen; + else + __strmode_ &= ~__frozen; + } +} + +char* +strstreambuf::str() +{ + if (__strmode_ & __dynamic) + __strmode_ |= __frozen; + return eback(); +} + +int +strstreambuf::pcount() const +{ + return static_cast<int>(pptr() - pbase()); +} + +strstreambuf::int_type +strstreambuf::overflow(int_type __c) +{ + if (__c == EOF) + return int_type(0); + if (pptr() == epptr()) + { + if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0) + return int_type(EOF); + size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback()); + size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size); + if (new_size == 0) + new_size = __default_alsize; + char* buf = nullptr; + if (__palloc_) + buf = static_cast<char*>(__palloc_(new_size)); + else + buf = new char[new_size]; + if (buf == nullptr) + return int_type(EOF); + if (old_size != 0) { + _LIBCPP_ASSERT(eback(), "overflow copying from NULL"); + memcpy(buf, eback(), static_cast<size_t>(old_size)); + } + ptrdiff_t ninp = gptr() - eback(); + ptrdiff_t einp = egptr() - eback(); + ptrdiff_t nout = pptr() - pbase(); + if (__strmode_ & __allocated) + { + if (__pfree_) + __pfree_(eback()); + else + delete [] eback(); + } + setg(buf, buf + ninp, buf + einp); + setp(buf + einp, buf + new_size); + __pbump(nout); + __strmode_ |= __allocated; + } + *pptr() = static_cast<char>(__c); + pbump(1); + return int_type(static_cast<unsigned char>(__c)); +} + +strstreambuf::int_type +strstreambuf::pbackfail(int_type __c) +{ + if (eback() == gptr()) + return EOF; + if (__c == EOF) + { + gbump(-1); + return int_type(0); + } + if (__strmode_ & __constant) + { + if (gptr()[-1] == static_cast<char>(__c)) + { + gbump(-1); + return __c; + } + return EOF; + } + gbump(-1); + *gptr() = static_cast<char>(__c); + return __c; +} + +strstreambuf::int_type +strstreambuf::underflow() +{ + if (gptr() == egptr()) + { + if (egptr() >= pptr()) + return EOF; + setg(eback(), gptr(), pptr()); + } + return int_type(static_cast<unsigned char>(*gptr())); +} + +strstreambuf::pos_type +strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which) +{ + off_type __p(-1); + bool pos_in = (__which & ios::in) != 0; + bool pos_out = (__which & ios::out) != 0; + bool legal = false; + switch (__way) + { + case ios::beg: + case ios::end: + if (pos_in || pos_out) + legal = true; + break; + case ios::cur: + if (pos_in != pos_out) + legal = true; + break; + } + if (pos_in && gptr() == nullptr) + legal = false; + if (pos_out && pptr() == nullptr) + legal = false; + if (legal) + { + off_type newoff; + char* seekhigh = epptr() ? epptr() : egptr(); + switch (__way) + { + case ios::beg: + newoff = 0; + break; + case ios::cur: + newoff = (pos_in ? gptr() : pptr()) - eback(); + break; + case ios::end: + newoff = seekhigh - eback(); + break; + default: + _LIBCPP_UNREACHABLE(); + } + newoff += __off; + if (0 <= newoff && newoff <= seekhigh - eback()) + { + char* newpos = eback() + newoff; + if (pos_in) + setg(eback(), newpos, _VSTD::max(newpos, egptr())); + if (pos_out) + { + // min(pbase, newpos), newpos, epptr() + __off = epptr() - newpos; + setp(min(pbase(), newpos), epptr()); + __pbump((epptr() - pbase()) - __off); + } + __p = newoff; + } + } + return pos_type(__p); +} + +strstreambuf::pos_type +strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which) +{ + off_type __p(-1); + bool pos_in = (__which & ios::in) != 0; + bool pos_out = (__which & ios::out) != 0; + if (pos_in || pos_out) + { + if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr))) + { + off_type newoff = __sp; + char* seekhigh = epptr() ? epptr() : egptr(); + if (0 <= newoff && newoff <= seekhigh - eback()) + { + char* newpos = eback() + newoff; + if (pos_in) + setg(eback(), newpos, _VSTD::max(newpos, egptr())); + if (pos_out) + { + // min(pbase, newpos), newpos, epptr() + off_type temp = epptr() - newpos; + setp(min(pbase(), newpos), epptr()); + __pbump((epptr() - pbase()) - temp); + } + __p = newoff; + } + } + } + return pos_type(__p); +} + +istrstream::~istrstream() +{ +} + +ostrstream::~ostrstream() +{ +} + +strstream::~strstream() +{ +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/support/ibm/mbsnrtowcs.cpp b/contrib/libs/cxxsupp/libcxx/src/support/ibm/mbsnrtowcs.cpp index fc1bdead17..125bdbea1c 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/ibm/mbsnrtowcs.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/support/ibm/mbsnrtowcs.cpp @@ -1,95 +1,95 @@ -//===----------------------- mbsnrtowcs.cpp -------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include <cstddef> // size_t -#include <cwchar> // mbstate_t -#include <limits.h> // MB_LEN_MAX -#include <string.h> // wmemcpy - -// Returns the number of wide characters found in the multi byte sequence `src` -// (of `src_size_bytes`), that fit in the buffer `dst` (of `max_dest_chars` -// elements size). The count returned excludes the null terminator. -// When `dst` is NULL, no characters are copied to `dst`. -// Returns (size_t) -1 when an invalid sequence is encountered. -// Leaves *`src` pointing to the next character to convert or NULL -// if a null character was converted from *`src`. -_LIBCPP_FUNC_VIS -size_t mbsnrtowcs(wchar_t *__restrict dst, const char **__restrict src, - size_t src_size_bytes, size_t max_dest_chars, - mbstate_t *__restrict ps) { - const size_t terminated_sequence = static_cast<size_t>(0); - const size_t invalid_sequence = static_cast<size_t>(-1); - const size_t incomplete_sequence = static_cast<size_t>(-2); - - size_t source_converted; - size_t dest_converted; - size_t result = 0; - - // If `dst` is null then `max_dest_chars` should be ignored according to the - // standard. Setting `max_dest_chars` to a large value has this effect. - if (dst == nullptr) - max_dest_chars = static_cast<size_t>(-1); - - for (dest_converted = source_converted = 0; - source_converted < src_size_bytes && (!dst || dest_converted < max_dest_chars); - ++dest_converted, source_converted += result) { - // Converts one multi byte character. - // If result (char_size) is greater than 0, it's the size in bytes of that character. - // If result (char_size) is zero, it indicates that the null character has been found. - // Otherwise, it's an error and errno may be set. - size_t source_remaining = src_size_bytes - source_converted; - size_t dest_remaining = max_dest_chars - dest_converted; - - if (dst == nullptr) { - result = mbrtowc(NULL, *src + source_converted, source_remaining, ps); - } else if (dest_remaining >= source_remaining) { - // dst has enough space to translate in-place. - result = mbrtowc(dst + dest_converted, *src + source_converted, source_remaining, ps); - } else { - /* - * dst may not have enough space, so use a temporary buffer. - * - * We need to save a copy of the conversion state - * here so we can restore it if the multibyte - * character is too long for the buffer. - */ - wchar_t buff[MB_LEN_MAX]; - mbstate_t mbstate_tmp; - - if (ps != nullptr) - mbstate_tmp = *ps; - result = mbrtowc(buff, *src + source_converted, source_remaining, ps); - - if (result > dest_remaining) { - // Multi-byte sequence for character won't fit. - if (ps != nullptr) - *ps = mbstate_tmp; - break; - } else { - // The buffer was used, so we need copy the translation to dst. - wmemcpy(dst, buff, result); - } - } - - // Don't do anything to change errno from here on. - if (result == invalid_sequence || result == terminated_sequence || result == incomplete_sequence) { - break; - } - } - - if (dst) { - if (result == terminated_sequence) - *src = NULL; - else - *src += source_converted; - } - if (result == invalid_sequence) - return invalid_sequence; - - return dest_converted; -} +//===----------------------- mbsnrtowcs.cpp -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <cstddef> // size_t +#include <cwchar> // mbstate_t +#include <limits.h> // MB_LEN_MAX +#include <string.h> // wmemcpy + +// Returns the number of wide characters found in the multi byte sequence `src` +// (of `src_size_bytes`), that fit in the buffer `dst` (of `max_dest_chars` +// elements size). The count returned excludes the null terminator. +// When `dst` is NULL, no characters are copied to `dst`. +// Returns (size_t) -1 when an invalid sequence is encountered. +// Leaves *`src` pointing to the next character to convert or NULL +// if a null character was converted from *`src`. +_LIBCPP_FUNC_VIS +size_t mbsnrtowcs(wchar_t *__restrict dst, const char **__restrict src, + size_t src_size_bytes, size_t max_dest_chars, + mbstate_t *__restrict ps) { + const size_t terminated_sequence = static_cast<size_t>(0); + const size_t invalid_sequence = static_cast<size_t>(-1); + const size_t incomplete_sequence = static_cast<size_t>(-2); + + size_t source_converted; + size_t dest_converted; + size_t result = 0; + + // If `dst` is null then `max_dest_chars` should be ignored according to the + // standard. Setting `max_dest_chars` to a large value has this effect. + if (dst == nullptr) + max_dest_chars = static_cast<size_t>(-1); + + for (dest_converted = source_converted = 0; + source_converted < src_size_bytes && (!dst || dest_converted < max_dest_chars); + ++dest_converted, source_converted += result) { + // Converts one multi byte character. + // If result (char_size) is greater than 0, it's the size in bytes of that character. + // If result (char_size) is zero, it indicates that the null character has been found. + // Otherwise, it's an error and errno may be set. + size_t source_remaining = src_size_bytes - source_converted; + size_t dest_remaining = max_dest_chars - dest_converted; + + if (dst == nullptr) { + result = mbrtowc(NULL, *src + source_converted, source_remaining, ps); + } else if (dest_remaining >= source_remaining) { + // dst has enough space to translate in-place. + result = mbrtowc(dst + dest_converted, *src + source_converted, source_remaining, ps); + } else { + /* + * dst may not have enough space, so use a temporary buffer. + * + * We need to save a copy of the conversion state + * here so we can restore it if the multibyte + * character is too long for the buffer. + */ + wchar_t buff[MB_LEN_MAX]; + mbstate_t mbstate_tmp; + + if (ps != nullptr) + mbstate_tmp = *ps; + result = mbrtowc(buff, *src + source_converted, source_remaining, ps); + + if (result > dest_remaining) { + // Multi-byte sequence for character won't fit. + if (ps != nullptr) + *ps = mbstate_tmp; + break; + } else { + // The buffer was used, so we need copy the translation to dst. + wmemcpy(dst, buff, result); + } + } + + // Don't do anything to change errno from here on. + if (result == invalid_sequence || result == terminated_sequence || result == incomplete_sequence) { + break; + } + } + + if (dst) { + if (result == terminated_sequence) + *src = NULL; + else + *src += source_converted; + } + if (result == invalid_sequence) + return invalid_sequence; + + return dest_converted; +} diff --git a/contrib/libs/cxxsupp/libcxx/src/support/ibm/wcsnrtombs.cpp b/contrib/libs/cxxsupp/libcxx/src/support/ibm/wcsnrtombs.cpp index 6497fb7b98..01c6241dc5 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/ibm/wcsnrtombs.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/support/ibm/wcsnrtombs.cpp @@ -1,93 +1,93 @@ -//===----------------------- wcsnrtombs.cpp -------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include <cwchar> // mbstate_t -#include <limits.h> // MB_LEN_MAX -#include <stdlib.h> // MB_CUR_MAX, size_t -#include <string.h> // memcpy - -// Converts `max_source_chars` from the wide character buffer pointer to by *`src`, -// into the multi byte character sequence buffer stored at `dst`, which must be -// `dst_size_bytes` bytes in size. Returns the number of bytes in the sequence -// converted from *src, excluding the null terminator. -// Returns (size_t) -1 if an error occurs and sets errno. -// If `dst` is NULL, `dst_size_bytes` is ignored and no bytes are copied to `dst`. -_LIBCPP_FUNC_VIS -size_t wcsnrtombs(char *__restrict dst, const wchar_t **__restrict src, - size_t max_source_chars, size_t dst_size_bytes, - mbstate_t *__restrict ps) { - - const size_t invalid_wchar = static_cast<size_t>(-1); - - size_t source_converted; - size_t dest_converted; - size_t result = 0; - - // If `dst` is null then `dst_size_bytes` should be ignored according to the - // standard. Setting dst_size_bytes to a large value has this effect. - if (dst == nullptr) - dst_size_bytes = static_cast<size_t>(-1); - - for (dest_converted = source_converted = 0; - source_converted < max_source_chars && (!dst || dest_converted < dst_size_bytes); - ++source_converted, dest_converted += result) { - wchar_t c = (*src)[source_converted]; - size_t dest_remaining = dst_size_bytes - dest_converted; - - if (dst == nullptr) { - result = wcrtomb(NULL, c, ps); - } else if (dest_remaining >= static_cast<size_t>(MB_CUR_MAX)) { - // dst has enough space to translate in-place. - result = wcrtomb(dst + dest_converted, c, ps); - } else { - /* - * dst may not have enough space, so use a temporary buffer. - * - * We need to save a copy of the conversion state - * here so we can restore it if the multibyte - * character is too long for the buffer. - */ - char buff[MB_LEN_MAX]; - mbstate_t mbstate_tmp; - - if (ps != nullptr) - mbstate_tmp = *ps; - result = wcrtomb(buff, c, ps); - - if (result > dest_remaining) { - // Multi-byte sequence for character won't fit. - if (ps != nullptr) - *ps = mbstate_tmp; - if (result != invalid_wchar) - break; - } else { - // The buffer was used, so we need copy the translation to dst. - memcpy(dst, buff, result); - } - } - - // result (char_size) contains the size of the multi-byte-sequence converted. - // Otherwise, result (char_size) is (size_t) -1 and wcrtomb() sets the errno. - if (result == invalid_wchar) { - if (dst) - *src = *src + source_converted; - return invalid_wchar; - } - - if (c == L'\0') { - if (dst) - *src = NULL; - return dest_converted; - } - } - - if (dst) - *src = *src + source_converted; - - return dest_converted; -} +//===----------------------- wcsnrtombs.cpp -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <cwchar> // mbstate_t +#include <limits.h> // MB_LEN_MAX +#include <stdlib.h> // MB_CUR_MAX, size_t +#include <string.h> // memcpy + +// Converts `max_source_chars` from the wide character buffer pointer to by *`src`, +// into the multi byte character sequence buffer stored at `dst`, which must be +// `dst_size_bytes` bytes in size. Returns the number of bytes in the sequence +// converted from *src, excluding the null terminator. +// Returns (size_t) -1 if an error occurs and sets errno. +// If `dst` is NULL, `dst_size_bytes` is ignored and no bytes are copied to `dst`. +_LIBCPP_FUNC_VIS +size_t wcsnrtombs(char *__restrict dst, const wchar_t **__restrict src, + size_t max_source_chars, size_t dst_size_bytes, + mbstate_t *__restrict ps) { + + const size_t invalid_wchar = static_cast<size_t>(-1); + + size_t source_converted; + size_t dest_converted; + size_t result = 0; + + // If `dst` is null then `dst_size_bytes` should be ignored according to the + // standard. Setting dst_size_bytes to a large value has this effect. + if (dst == nullptr) + dst_size_bytes = static_cast<size_t>(-1); + + for (dest_converted = source_converted = 0; + source_converted < max_source_chars && (!dst || dest_converted < dst_size_bytes); + ++source_converted, dest_converted += result) { + wchar_t c = (*src)[source_converted]; + size_t dest_remaining = dst_size_bytes - dest_converted; + + if (dst == nullptr) { + result = wcrtomb(NULL, c, ps); + } else if (dest_remaining >= static_cast<size_t>(MB_CUR_MAX)) { + // dst has enough space to translate in-place. + result = wcrtomb(dst + dest_converted, c, ps); + } else { + /* + * dst may not have enough space, so use a temporary buffer. + * + * We need to save a copy of the conversion state + * here so we can restore it if the multibyte + * character is too long for the buffer. + */ + char buff[MB_LEN_MAX]; + mbstate_t mbstate_tmp; + + if (ps != nullptr) + mbstate_tmp = *ps; + result = wcrtomb(buff, c, ps); + + if (result > dest_remaining) { + // Multi-byte sequence for character won't fit. + if (ps != nullptr) + *ps = mbstate_tmp; + if (result != invalid_wchar) + break; + } else { + // The buffer was used, so we need copy the translation to dst. + memcpy(dst, buff, result); + } + } + + // result (char_size) contains the size of the multi-byte-sequence converted. + // Otherwise, result (char_size) is (size_t) -1 and wcrtomb() sets the errno. + if (result == invalid_wchar) { + if (dst) + *src = *src + source_converted; + return invalid_wchar; + } + + if (c == L'\0') { + if (dst) + *src = NULL; + return dest_converted; + } + } + + if (dst) + *src = *src + source_converted; + + return dest_converted; +} diff --git a/contrib/libs/cxxsupp/libcxx/src/support/ibm/xlocale_zos.cpp b/contrib/libs/cxxsupp/libcxx/src/support/ibm/xlocale_zos.cpp index 7649ab0c9f..90c1ba95a3 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/ibm/xlocale_zos.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/support/ibm/xlocale_zos.cpp @@ -1,137 +1,137 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include <__support/ibm/xlocale.h> -#include <sstream> -#include <vector> - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -locale_t newlocale(int category_mask, const char* locale, locale_t base) { - // Maintain current locale name(s) to restore later. - std::string current_loc_name(setlocale(LC_ALL, 0)); - - // Check for errors. - if (category_mask == LC_ALL_MASK && setlocale(LC_ALL, locale) == NULL) { - errno = EINVAL; - return (locale_t)0; - } else { - for (int _Cat = 0; _Cat <= _LC_MAX; ++_Cat) { - if ((_CATMASK(_Cat) & category_mask) != 0 && setlocale(_Cat, locale) == NULL) { - setlocale(LC_ALL, current_loc_name.c_str()); - errno = EINVAL; - return (locale_t)0; - } - } - } - - // Create new locale. - locale_t newloc = new locale_struct(); - - if (base) { - if (category_mask != LC_ALL_MASK) { - // Copy base when it will not be overwritten. - memcpy(newloc, base, sizeof (locale_struct)); - newloc->category_mask = category_mask | base->category_mask; - } - delete base; - } else { - newloc->category_mask = category_mask; - } - - if (category_mask & LC_COLLATE_MASK) - newloc->lc_collate = locale; - if (category_mask & LC_CTYPE_MASK) - newloc->lc_ctype = locale; - if (category_mask & LC_MONETARY_MASK) - newloc->lc_monetary = locale; - if (category_mask & LC_NUMERIC_MASK) - newloc->lc_numeric = locale; - if (category_mask & LC_TIME_MASK) - newloc->lc_time = locale; - if (category_mask & LC_MESSAGES_MASK) - newloc->lc_messages = locale; - - // Restore current locale. - setlocale(LC_ALL, current_loc_name.c_str()); - return (locale_t)newloc; -} - -void freelocale(locale_t locobj) { - delete locobj; -} - -locale_t uselocale(locale_t newloc) { - // Maintain current locale name(s). - std::string current_loc_name(setlocale(LC_ALL, 0)); - - if (newloc) { - // Set locales and check for errors. - bool is_error = - (newloc->category_mask & LC_COLLATE_MASK && - setlocale(LC_COLLATE, newloc->lc_collate.c_str()) == NULL) || - (newloc->category_mask & LC_CTYPE_MASK && - setlocale(LC_CTYPE, newloc->lc_ctype.c_str()) == NULL) || - (newloc->category_mask & LC_MONETARY_MASK && - setlocale(LC_MONETARY, newloc->lc_monetary.c_str()) == NULL) || - (newloc->category_mask & LC_NUMERIC_MASK && - setlocale(LC_NUMERIC, newloc->lc_numeric.c_str()) == NULL) || - (newloc->category_mask & LC_TIME_MASK && - setlocale(LC_TIME, newloc->lc_time.c_str()) == NULL) || - (newloc->category_mask & LC_MESSAGES_MASK && - setlocale(LC_MESSAGES, newloc->lc_messages.c_str()) == NULL); - - if (is_error) { - setlocale(LC_ALL, current_loc_name.c_str()); - errno = EINVAL; - return (locale_t)0; - } - } - - // Construct and return previous locale. - locale_t previous_loc = new locale_struct(); - - // current_loc_name might be a comma-separated locale name list. - if (current_loc_name.find(',') != std::string::npos) { - // Tokenize locale name list. - const char delimiter = ','; - std::vector<std::string> tokenized; - std::stringstream ss(current_loc_name); - std::string s; - - while (std::getline(ss, s, delimiter)) { - tokenized.push_back(s); - } - - _LIBCPP_ASSERT(tokenized.size() >= _NCAT, "locale-name list is too short"); - - previous_loc->lc_collate = tokenized[LC_COLLATE]; - previous_loc->lc_ctype = tokenized[LC_CTYPE]; - previous_loc->lc_monetary = tokenized[LC_MONETARY]; - previous_loc->lc_numeric = tokenized[LC_NUMERIC]; - previous_loc->lc_time = tokenized[LC_TIME]; - // Skip LC_TOD. - previous_loc->lc_messages = tokenized[LC_MESSAGES]; - } else { - previous_loc->lc_collate = current_loc_name; - previous_loc->lc_ctype = current_loc_name; - previous_loc->lc_monetary = current_loc_name; - previous_loc->lc_numeric = current_loc_name; - previous_loc->lc_time = current_loc_name; - previous_loc->lc_messages = current_loc_name; - } - - previous_loc->category_mask = LC_ALL_MASK; - return previous_loc; -} - -#ifdef __cplusplus -} -#endif // __cplusplus +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include <__support/ibm/xlocale.h> +#include <sstream> +#include <vector> + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +locale_t newlocale(int category_mask, const char* locale, locale_t base) { + // Maintain current locale name(s) to restore later. + std::string current_loc_name(setlocale(LC_ALL, 0)); + + // Check for errors. + if (category_mask == LC_ALL_MASK && setlocale(LC_ALL, locale) == NULL) { + errno = EINVAL; + return (locale_t)0; + } else { + for (int _Cat = 0; _Cat <= _LC_MAX; ++_Cat) { + if ((_CATMASK(_Cat) & category_mask) != 0 && setlocale(_Cat, locale) == NULL) { + setlocale(LC_ALL, current_loc_name.c_str()); + errno = EINVAL; + return (locale_t)0; + } + } + } + + // Create new locale. + locale_t newloc = new locale_struct(); + + if (base) { + if (category_mask != LC_ALL_MASK) { + // Copy base when it will not be overwritten. + memcpy(newloc, base, sizeof (locale_struct)); + newloc->category_mask = category_mask | base->category_mask; + } + delete base; + } else { + newloc->category_mask = category_mask; + } + + if (category_mask & LC_COLLATE_MASK) + newloc->lc_collate = locale; + if (category_mask & LC_CTYPE_MASK) + newloc->lc_ctype = locale; + if (category_mask & LC_MONETARY_MASK) + newloc->lc_monetary = locale; + if (category_mask & LC_NUMERIC_MASK) + newloc->lc_numeric = locale; + if (category_mask & LC_TIME_MASK) + newloc->lc_time = locale; + if (category_mask & LC_MESSAGES_MASK) + newloc->lc_messages = locale; + + // Restore current locale. + setlocale(LC_ALL, current_loc_name.c_str()); + return (locale_t)newloc; +} + +void freelocale(locale_t locobj) { + delete locobj; +} + +locale_t uselocale(locale_t newloc) { + // Maintain current locale name(s). + std::string current_loc_name(setlocale(LC_ALL, 0)); + + if (newloc) { + // Set locales and check for errors. + bool is_error = + (newloc->category_mask & LC_COLLATE_MASK && + setlocale(LC_COLLATE, newloc->lc_collate.c_str()) == NULL) || + (newloc->category_mask & LC_CTYPE_MASK && + setlocale(LC_CTYPE, newloc->lc_ctype.c_str()) == NULL) || + (newloc->category_mask & LC_MONETARY_MASK && + setlocale(LC_MONETARY, newloc->lc_monetary.c_str()) == NULL) || + (newloc->category_mask & LC_NUMERIC_MASK && + setlocale(LC_NUMERIC, newloc->lc_numeric.c_str()) == NULL) || + (newloc->category_mask & LC_TIME_MASK && + setlocale(LC_TIME, newloc->lc_time.c_str()) == NULL) || + (newloc->category_mask & LC_MESSAGES_MASK && + setlocale(LC_MESSAGES, newloc->lc_messages.c_str()) == NULL); + + if (is_error) { + setlocale(LC_ALL, current_loc_name.c_str()); + errno = EINVAL; + return (locale_t)0; + } + } + + // Construct and return previous locale. + locale_t previous_loc = new locale_struct(); + + // current_loc_name might be a comma-separated locale name list. + if (current_loc_name.find(',') != std::string::npos) { + // Tokenize locale name list. + const char delimiter = ','; + std::vector<std::string> tokenized; + std::stringstream ss(current_loc_name); + std::string s; + + while (std::getline(ss, s, delimiter)) { + tokenized.push_back(s); + } + + _LIBCPP_ASSERT(tokenized.size() >= _NCAT, "locale-name list is too short"); + + previous_loc->lc_collate = tokenized[LC_COLLATE]; + previous_loc->lc_ctype = tokenized[LC_CTYPE]; + previous_loc->lc_monetary = tokenized[LC_MONETARY]; + previous_loc->lc_numeric = tokenized[LC_NUMERIC]; + previous_loc->lc_time = tokenized[LC_TIME]; + // Skip LC_TOD. + previous_loc->lc_messages = tokenized[LC_MESSAGES]; + } else { + previous_loc->lc_collate = current_loc_name; + previous_loc->lc_ctype = current_loc_name; + previous_loc->lc_monetary = current_loc_name; + previous_loc->lc_numeric = current_loc_name; + previous_loc->lc_time = current_loc_name; + previous_loc->lc_messages = current_loc_name; + } + + previous_loc->category_mask = LC_ALL_MASK; + return previous_loc; +} + +#ifdef __cplusplus +} +#endif // __cplusplus diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_fallback.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_fallback.ipp index f70445af55..6ebaeee2a5 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_fallback.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_fallback.ipp @@ -1,161 +1,161 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include <cstdio> -#include "../../include/atomic_support.h" - -namespace std { - -_LIBCPP_SAFE_STATIC static std::terminate_handler __terminate_handler; -_LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler; - - -// libcxxrt provides implementations of these functions itself. -unexpected_handler -set_unexpected(unexpected_handler func) noexcept -{ - return __libcpp_atomic_exchange(&__unexpected_handler, func); -} - -unexpected_handler -get_unexpected() noexcept -{ - return __libcpp_atomic_load(&__unexpected_handler); - -} - -_LIBCPP_NORETURN -void unexpected() -{ - (*get_unexpected())(); - // unexpected handler should not return - terminate(); -} - -terminate_handler -set_terminate(terminate_handler func) noexcept -{ - return __libcpp_atomic_exchange(&__terminate_handler, func); -} - -terminate_handler -get_terminate() noexcept -{ - return __libcpp_atomic_load(&__terminate_handler); -} - -_LIBCPP_NORETURN -void -terminate() noexcept -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - (*get_terminate())(); - // handler should not return - fprintf(stderr, "terminate_handler unexpectedly returned\n"); - ::abort(); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - // handler should not throw exception - fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); - ::abort(); - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } - -int uncaught_exceptions() noexcept -{ -#warning uncaught_exception not yet implemented - fprintf(stderr, "uncaught_exceptions not yet implemented\n"); - ::abort(); -} - - -exception::~exception() noexcept -{ -} - -const char* exception::what() const noexcept -{ - return "std::exception"; -} - -bad_exception::~bad_exception() noexcept -{ -} - -const char* bad_exception::what() const noexcept -{ - return "std::bad_exception"; -} - - -bad_alloc::bad_alloc() noexcept -{ -} - -bad_alloc::~bad_alloc() noexcept -{ -} - -const char* -bad_alloc::what() const noexcept -{ - return "std::bad_alloc"; -} - -bad_array_new_length::bad_array_new_length() noexcept -{ -} - -bad_array_new_length::~bad_array_new_length() noexcept -{ -} - -const char* -bad_array_new_length::what() const noexcept -{ - return "bad_array_new_length"; -} - -bad_cast::bad_cast() noexcept -{ -} - -bad_typeid::bad_typeid() noexcept -{ -} - -bad_cast::~bad_cast() noexcept -{ -} - -const char* -bad_cast::what() const noexcept -{ - return "std::bad_cast"; -} - -bad_typeid::~bad_typeid() noexcept -{ -} - -const char* -bad_typeid::what() const noexcept -{ - return "std::bad_typeid"; -} - -} // namespace std +// +//===----------------------------------------------------------------------===// + +#include <cstdio> +#include "../../include/atomic_support.h" + +namespace std { + +_LIBCPP_SAFE_STATIC static std::terminate_handler __terminate_handler; +_LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler; + + +// libcxxrt provides implementations of these functions itself. +unexpected_handler +set_unexpected(unexpected_handler func) noexcept +{ + return __libcpp_atomic_exchange(&__unexpected_handler, func); +} + +unexpected_handler +get_unexpected() noexcept +{ + return __libcpp_atomic_load(&__unexpected_handler); + +} + +_LIBCPP_NORETURN +void unexpected() +{ + (*get_unexpected())(); + // unexpected handler should not return + terminate(); +} + +terminate_handler +set_terminate(terminate_handler func) noexcept +{ + return __libcpp_atomic_exchange(&__terminate_handler, func); +} + +terminate_handler +get_terminate() noexcept +{ + return __libcpp_atomic_load(&__terminate_handler); +} + +_LIBCPP_NORETURN +void +terminate() noexcept +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + (*get_terminate())(); + // handler should not return + fprintf(stderr, "terminate_handler unexpectedly returned\n"); + ::abort(); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + // handler should not throw exception + fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); + ::abort(); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } + +int uncaught_exceptions() noexcept +{ +#warning uncaught_exception not yet implemented + fprintf(stderr, "uncaught_exceptions not yet implemented\n"); + ::abort(); +} + + +exception::~exception() noexcept +{ +} + +const char* exception::what() const noexcept +{ + return "std::exception"; +} + +bad_exception::~bad_exception() noexcept +{ +} + +const char* bad_exception::what() const noexcept +{ + return "std::bad_exception"; +} + + +bad_alloc::bad_alloc() noexcept +{ +} + +bad_alloc::~bad_alloc() noexcept +{ +} + +const char* +bad_alloc::what() const noexcept +{ + return "std::bad_alloc"; +} + +bad_array_new_length::bad_array_new_length() noexcept +{ +} + +bad_array_new_length::~bad_array_new_length() noexcept +{ +} + +const char* +bad_array_new_length::what() const noexcept +{ + return "bad_array_new_length"; +} + +bad_cast::bad_cast() noexcept +{ +} + +bad_typeid::bad_typeid() noexcept +{ +} + +bad_cast::~bad_cast() noexcept +{ +} + +const char* +bad_cast::what() const noexcept +{ + return "std::bad_cast"; +} + +bad_typeid::~bad_typeid() noexcept +{ +} + +const char* +bad_typeid::what() const noexcept +{ + return "std::bad_typeid"; +} + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_glibcxx.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_glibcxx.ipp index 7cc665a8bc..e478ccbb6e 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_glibcxx.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_glibcxx.ipp @@ -1,32 +1,32 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// // 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 __GLIBCXX__ -#error header can only be used when targeting libstdc++ or libsupc++ -#endif - -namespace std { - -bad_alloc::bad_alloc() noexcept -{ -} - -bad_array_new_length::bad_array_new_length() noexcept -{ -} - -bad_cast::bad_cast() noexcept -{ -} - -bad_typeid::bad_typeid() noexcept -{ -} - -} // namespace std +// +//===----------------------------------------------------------------------===// + +#ifndef __GLIBCXX__ +#error header can only be used when targeting libstdc++ or libsupc++ +#endif + +namespace std { + +bad_alloc::bad_alloc() noexcept +{ +} + +bad_array_new_length::bad_array_new_length() noexcept +{ +} + +bad_cast::bad_cast() noexcept +{ +} + +bad_typeid::bad_typeid() noexcept +{ +} + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_libcxxabi.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_libcxxabi.ipp index a85a59f0a5..ee15e437e6 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_libcxxabi.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_libcxxabi.ipp @@ -1,27 +1,27 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// // 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 _LIBCPPABI_VERSION -#error this header can only be used with libc++abi -#endif - -namespace std { - -bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } - -int uncaught_exceptions() noexcept -{ -# if _LIBCPPABI_VERSION > 1001 - return __cxa_uncaught_exceptions(); -# else - return __cxa_uncaught_exception() ? 1 : 0; -# endif -} - -} // namespace std +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPPABI_VERSION +#error this header can only be used with libc++abi +#endif + +namespace std { + +bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } + +int uncaught_exceptions() noexcept +{ +# if _LIBCPPABI_VERSION > 1001 + return __cxa_uncaught_exceptions(); +# else + return __cxa_uncaught_exception() ? 1 : 0; +# endif +} + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_libcxxrt.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_libcxxrt.ipp index bcca118c9c..4e428d216c 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_libcxxrt.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_libcxxrt.ipp @@ -1,25 +1,25 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// // 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 LIBCXX_BUILDING_LIBCXXRT -#error this header may only be used when targeting libcxxrt -#endif - -namespace std { - -bad_exception::~bad_exception() noexcept -{ -} - -const char* bad_exception::what() const noexcept -{ - return "std::bad_exception"; -} - -} // namespace std +#error this header may only be used when targeting libcxxrt +#endif + +namespace std { + +bad_exception::~bad_exception() noexcept +{ +} + +const char* bad_exception::what() const noexcept +{ + return "std::bad_exception"; +} + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_msvc.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_msvc.ipp index ebfbe86b40..4eb1803f0b 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_msvc.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_msvc.ipp @@ -1,173 +1,173 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// // 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_ABI_MICROSOFT -#error this header can only be used when targeting the MSVC ABI -#endif - -#include <stdio.h> -#include <stdlib.h> - +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_ABI_MICROSOFT +#error this header can only be used when targeting the MSVC ABI +#endif + +#include <stdio.h> +#include <stdlib.h> + #include <__config> #ifdef _LIBCPP_COMPILER_MSVC -// We don't want to depend on MSVC headers but -// we have conflicting definitions otherwise due to -// some other dependency on eh.h. -#include _LIBCPP_MSVC_INCLUDE(eh.h) - -#else -extern "C" { -typedef void (__cdecl* terminate_handler)(); -_LIBCPP_CRT_FUNC terminate_handler __cdecl set_terminate( - terminate_handler _NewTerminateHandler) throw(); -_LIBCPP_CRT_FUNC terminate_handler __cdecl _get_terminate(); - -typedef void (__cdecl* unexpected_handler)(); -unexpected_handler __cdecl set_unexpected( - unexpected_handler _NewUnexpectedHandler) throw(); -unexpected_handler __cdecl _get_unexpected(); - -int __cdecl __uncaught_exceptions(); -} -#endif - -namespace std { - -unexpected_handler -set_unexpected(unexpected_handler func) noexcept { - return ::set_unexpected(func); -} - -unexpected_handler get_unexpected() noexcept { - return ::_get_unexpected(); -} - -_LIBCPP_NORETURN -void unexpected() { - (*get_unexpected())(); - // unexpected handler should not return - terminate(); -} - -terminate_handler set_terminate(terminate_handler func) noexcept { - return ::set_terminate(func); -} - -terminate_handler get_terminate() noexcept { - return ::_get_terminate(); -} - -_LIBCPP_NORETURN -void terminate() noexcept -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - (*get_terminate())(); - // handler should not return - fprintf(stderr, "terminate_handler unexpectedly returned\n"); - ::abort(); -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - // handler should not throw exception - fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); - ::abort(); - } -#endif // _LIBCPP_NO_EXCEPTIONS -} - -bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } - -int uncaught_exceptions() noexcept { - return __uncaught_exceptions(); -} - -#if !defined(_LIBCPP_ABI_VCRUNTIME) -bad_cast::bad_cast() noexcept -{ -} - -bad_cast::~bad_cast() noexcept -{ -} - -const char * -bad_cast::what() const noexcept -{ - return "std::bad_cast"; -} - -bad_typeid::bad_typeid() noexcept -{ -} - -bad_typeid::~bad_typeid() noexcept -{ -} - -const char * -bad_typeid::what() const noexcept -{ - return "std::bad_typeid"; -} - -exception::~exception() noexcept -{ -} - -const char* exception::what() const noexcept -{ - return "std::exception"; -} - - -bad_exception::~bad_exception() noexcept -{ -} - -const char* bad_exception::what() const noexcept -{ - return "std::bad_exception"; -} - - -bad_alloc::bad_alloc() noexcept -{ -} - -bad_alloc::~bad_alloc() noexcept -{ -} - -const char* -bad_alloc::what() const noexcept -{ - return "std::bad_alloc"; -} - -bad_array_new_length::bad_array_new_length() noexcept -{ -} - -bad_array_new_length::~bad_array_new_length() noexcept -{ -} - -const char* -bad_array_new_length::what() const noexcept -{ - return "bad_array_new_length"; -} -#endif // !_LIBCPP_ABI_VCRUNTIME - -} // namespace std +// We don't want to depend on MSVC headers but +// we have conflicting definitions otherwise due to +// some other dependency on eh.h. +#include _LIBCPP_MSVC_INCLUDE(eh.h) + +#else +extern "C" { +typedef void (__cdecl* terminate_handler)(); +_LIBCPP_CRT_FUNC terminate_handler __cdecl set_terminate( + terminate_handler _NewTerminateHandler) throw(); +_LIBCPP_CRT_FUNC terminate_handler __cdecl _get_terminate(); + +typedef void (__cdecl* unexpected_handler)(); +unexpected_handler __cdecl set_unexpected( + unexpected_handler _NewUnexpectedHandler) throw(); +unexpected_handler __cdecl _get_unexpected(); + +int __cdecl __uncaught_exceptions(); +} +#endif + +namespace std { + +unexpected_handler +set_unexpected(unexpected_handler func) noexcept { + return ::set_unexpected(func); +} + +unexpected_handler get_unexpected() noexcept { + return ::_get_unexpected(); +} + +_LIBCPP_NORETURN +void unexpected() { + (*get_unexpected())(); + // unexpected handler should not return + terminate(); +} + +terminate_handler set_terminate(terminate_handler func) noexcept { + return ::set_terminate(func); +} + +terminate_handler get_terminate() noexcept { + return ::_get_terminate(); +} + +_LIBCPP_NORETURN +void terminate() noexcept +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + try + { +#endif // _LIBCPP_NO_EXCEPTIONS + (*get_terminate())(); + // handler should not return + fprintf(stderr, "terminate_handler unexpectedly returned\n"); + ::abort(); +#ifndef _LIBCPP_NO_EXCEPTIONS + } + catch (...) + { + // handler should not throw exception + fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); + ::abort(); + } +#endif // _LIBCPP_NO_EXCEPTIONS +} + +bool uncaught_exception() noexcept { return uncaught_exceptions() > 0; } + +int uncaught_exceptions() noexcept { + return __uncaught_exceptions(); +} + +#if !defined(_LIBCPP_ABI_VCRUNTIME) +bad_cast::bad_cast() noexcept +{ +} + +bad_cast::~bad_cast() noexcept +{ +} + +const char * +bad_cast::what() const noexcept +{ + return "std::bad_cast"; +} + +bad_typeid::bad_typeid() noexcept +{ +} + +bad_typeid::~bad_typeid() noexcept +{ +} + +const char * +bad_typeid::what() const noexcept +{ + return "std::bad_typeid"; +} + +exception::~exception() noexcept +{ +} + +const char* exception::what() const noexcept +{ + return "std::exception"; +} + + +bad_exception::~bad_exception() noexcept +{ +} + +const char* bad_exception::what() const noexcept +{ + return "std::bad_exception"; +} + + +bad_alloc::bad_alloc() noexcept +{ +} + +bad_alloc::~bad_alloc() noexcept +{ +} + +const char* +bad_alloc::what() const noexcept +{ + return "std::bad_alloc"; +} + +bad_array_new_length::bad_array_new_length() noexcept +{ +} + +bad_array_new_length::~bad_array_new_length() noexcept +{ +} + +const char* +bad_array_new_length::what() const noexcept +{ + return "bad_array_new_length"; +} +#endif // !_LIBCPP_ABI_VCRUNTIME + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp index 5ffc0cd127..33aa94502b 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp @@ -1,73 +1,73 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// // 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 HAVE_DEPENDENT_EH_ABI -#error this header may only be used with libc++abi or libcxxrt -#endif - -namespace std { - -exception_ptr::~exception_ptr() noexcept { - __cxa_decrement_exception_refcount(__ptr_); -} - -exception_ptr::exception_ptr(const exception_ptr& other) noexcept - : __ptr_(other.__ptr_) -{ - __cxa_increment_exception_refcount(__ptr_); -} - -exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept -{ - if (__ptr_ != other.__ptr_) - { - __cxa_increment_exception_refcount(other.__ptr_); - __cxa_decrement_exception_refcount(__ptr_); - __ptr_ = other.__ptr_; - } - return *this; -} - -nested_exception::nested_exception() noexcept - : __ptr_(current_exception()) -{ -} - -nested_exception::~nested_exception() noexcept -{ -} - -_LIBCPP_NORETURN -void -nested_exception::rethrow_nested() const -{ - if (__ptr_ == nullptr) - terminate(); - rethrow_exception(__ptr_); -} - -exception_ptr current_exception() noexcept -{ - // be nicer if there was a constructor that took a ptr, then - // this whole function would be just: - // return exception_ptr(__cxa_current_primary_exception()); - exception_ptr ptr; - ptr.__ptr_ = __cxa_current_primary_exception(); - return ptr; -} - -_LIBCPP_NORETURN -void rethrow_exception(exception_ptr p) -{ - __cxa_rethrow_primary_exception(p.__ptr_); - // if p.__ptr_ is NULL, above returns so we terminate - terminate(); -} - -} // namespace std +// +//===----------------------------------------------------------------------===// + +#ifndef HAVE_DEPENDENT_EH_ABI +#error this header may only be used with libc++abi or libcxxrt +#endif + +namespace std { + +exception_ptr::~exception_ptr() noexcept { + __cxa_decrement_exception_refcount(__ptr_); +} + +exception_ptr::exception_ptr(const exception_ptr& other) noexcept + : __ptr_(other.__ptr_) +{ + __cxa_increment_exception_refcount(__ptr_); +} + +exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept +{ + if (__ptr_ != other.__ptr_) + { + __cxa_increment_exception_refcount(other.__ptr_); + __cxa_decrement_exception_refcount(__ptr_); + __ptr_ = other.__ptr_; + } + return *this; +} + +nested_exception::nested_exception() noexcept + : __ptr_(current_exception()) +{ +} + +nested_exception::~nested_exception() noexcept +{ +} + +_LIBCPP_NORETURN +void +nested_exception::rethrow_nested() const +{ + if (__ptr_ == nullptr) + terminate(); + rethrow_exception(__ptr_); +} + +exception_ptr current_exception() noexcept +{ + // be nicer if there was a constructor that took a ptr, then + // this whole function would be just: + // return exception_ptr(__cxa_current_primary_exception()); + exception_ptr ptr; + ptr.__ptr_ = __cxa_current_primary_exception(); + return ptr; +} + +_LIBCPP_NORETURN +void rethrow_exception(exception_ptr p) +{ + __cxa_rethrow_primary_exception(p.__ptr_); + // if p.__ptr_ is NULL, above returns so we terminate + terminate(); +} + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp index bd1d5e4752..983a08808d 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp @@ -1,77 +1,77 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -// libsupc++ does not implement the dependent EH ABI and the functionality -// it uses to implement std::exception_ptr (which it declares as an alias of -// std::__exception_ptr::exception_ptr) is not directly exported to clients. So -// we have little choice but to hijack std::__exception_ptr::exception_ptr's -// (which fortunately has the same layout as our std::exception_ptr) copy -// constructor, assignment operator and destructor (which are part of its -// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr) -// function. - -namespace std { - -namespace __exception_ptr -{ - -struct exception_ptr -{ - void* __ptr_; - - exception_ptr(const exception_ptr&) noexcept; - exception_ptr& operator=(const exception_ptr&) noexcept; - ~exception_ptr() noexcept; -}; - -} - -_LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr); - -exception_ptr::~exception_ptr() noexcept -{ - reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr(); -} - -exception_ptr::exception_ptr(const exception_ptr& other) noexcept - : __ptr_(other.__ptr_) -{ - new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr( - reinterpret_cast<const __exception_ptr::exception_ptr&>(other)); -} - -exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept -{ - *reinterpret_cast<__exception_ptr::exception_ptr*>(this) = - reinterpret_cast<const __exception_ptr::exception_ptr&>(other); - return *this; -} - -nested_exception::nested_exception() noexcept - : __ptr_(current_exception()) -{ -} - - -_LIBCPP_NORETURN -void -nested_exception::rethrow_nested() const -{ - if (__ptr_ == nullptr) - terminate(); - rethrow_exception(__ptr_); -} - -_LIBCPP_NORETURN -void rethrow_exception(exception_ptr p) -{ - rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p)); -} - -} // namespace std +// +//===----------------------------------------------------------------------===// + +// libsupc++ does not implement the dependent EH ABI and the functionality +// it uses to implement std::exception_ptr (which it declares as an alias of +// std::__exception_ptr::exception_ptr) is not directly exported to clients. So +// we have little choice but to hijack std::__exception_ptr::exception_ptr's +// (which fortunately has the same layout as our std::exception_ptr) copy +// constructor, assignment operator and destructor (which are part of its +// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr) +// function. + +namespace std { + +namespace __exception_ptr +{ + +struct exception_ptr +{ + void* __ptr_; + + exception_ptr(const exception_ptr&) noexcept; + exception_ptr& operator=(const exception_ptr&) noexcept; + ~exception_ptr() noexcept; +}; + +} + +_LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr); + +exception_ptr::~exception_ptr() noexcept +{ + reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr(); +} + +exception_ptr::exception_ptr(const exception_ptr& other) noexcept + : __ptr_(other.__ptr_) +{ + new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr( + reinterpret_cast<const __exception_ptr::exception_ptr&>(other)); +} + +exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept +{ + *reinterpret_cast<__exception_ptr::exception_ptr*>(this) = + reinterpret_cast<const __exception_ptr::exception_ptr&>(other); + return *this; +} + +nested_exception::nested_exception() noexcept + : __ptr_(current_exception()) +{ +} + + +_LIBCPP_NORETURN +void +nested_exception::rethrow_nested() const +{ + if (__ptr_ == nullptr) + terminate(); + rethrow_exception(__ptr_); +} + +_LIBCPP_NORETURN +void rethrow_exception(exception_ptr p) +{ + rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p)); +} + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_msvc.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_msvc.ipp index 0810acf1ed..300acbf759 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_msvc.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_msvc.ipp @@ -1,258 +1,258 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include <atomic> -#include <cstdint> -#include <cstring> -#include <malloc.h> -#include <windows.h> // For RtlPcToFileHeader function - -struct EHCatchableType { - uint32_t properties; - int32_t type_info; - uint32_t non_virtual_adjustment; - uint32_t offset_to_virtual_base_ptr; - uint32_t virtual_base_table_index; - uint32_t size; - int32_t copy_function; -}; - -struct EHCatchableTypeArray { - uint32_t catchable_types; - // It is variable size but we only need the first element of this array - int32_t array_of_catchable_types[1]; -}; - -struct EHThrowInfo { - uint32_t attributes; - int32_t unwind; - int32_t forward_compat; - int32_t catchable_type_array; -}; - -struct EHParameters { - uint32_t magic_number; - void* exception_object; - EHThrowInfo* throw_info; -#ifdef _M_AMD64 - uintptr_t throw_image_base; -#endif -}; - -struct EHExceptionRecord { - uint32_t exception_code; - uint32_t exception_flags; - void* exception_record; - void* exception_address; - uint32_t number_of_parameters; - EHParameters parameters; -}; - -// defined in vcruntime<ver>.dll -extern "C" EHExceptionRecord** __current_exception(); - -// This is internal compiler definition for MSVC but not for clang. -// We use our own EHThrowInfo because _ThrowInfo doesn't match actual -// compiler-generated structures in 64-bit mode. -#ifdef __clang__ -struct _ThrowInfo; -// defined in vcruntime<ver>.dll -_LIBCPP_NORETURN extern "C" void __stdcall _CxxThrowException( - void* __exc, _ThrowInfo* __throw_info); -#endif - -namespace { -struct ExceptionPtr { - void* exception_object; - const EHThrowInfo* throw_info; - std::atomic<size_t> counter; -#ifdef _M_AMD64 - PVOID image_base; -#endif - template <class T> - T convert(int32_t offset) { -#ifdef _M_AMD64 - uintptr_t value = reinterpret_cast<uintptr_t>(image_base) + - static_cast<uintptr_t>(offset); -#else - uintptr_t value = static_cast<uintptr_t>(offset); -#endif - T res; - static_assert( - sizeof(value) == sizeof(res), - "Can only convert to pointers or pointers to member functions"); - memcpy(&res, &value, sizeof(value)); - return res; - } - - void copy(void* dst, const void* src, const EHCatchableType* exc_type) { - struct Temp {}; - constexpr uint32_t virtual_base = 4; - if (exc_type->copy_function == 0) { - memcpy(dst, src, exc_type->size); - } else if (exc_type->properties & virtual_base) { - auto copy_constructor = - convert<void (Temp::*)(const void*, int)>(exc_type->copy_function); - ((Temp*)dst->*copy_constructor)(src, 1); - } else { - auto copy_constructor = - convert<void (Temp::*)(const void*)>(exc_type->copy_function); - ((Temp*)dst->*copy_constructor)(src); - } - } - - EHCatchableType* exception_type() { - return convert<EHCatchableType*>( - convert<EHCatchableTypeArray*>(throw_info->catchable_type_array) - ->array_of_catchable_types[0]); - } - - ExceptionPtr(const void* exception_object_, const EHThrowInfo* throw_info_) - : exception_object(nullptr), throw_info(throw_info_), counter(1) { -#ifdef _M_AMD64 - RtlPcToFileHeader( - reinterpret_cast<PVOID>(const_cast<EHThrowInfo*>(throw_info)), - &image_base); -#endif - EHCatchableType* exc_type = exception_type(); - this->exception_object = malloc(exc_type->size); - if (this->exception_object == nullptr) { - throw std::bad_alloc(); - } - copy(exception_object, exception_object_, exc_type); - } - - ~ExceptionPtr() { - if (throw_info->unwind && exception_object) { - struct Temp {}; - auto destructor = convert<void (Temp::*)()>(throw_info->unwind); - ((Temp*)exception_object->*destructor)(); - } - free(exception_object); - } - +// +//===----------------------------------------------------------------------===// + +#include <atomic> +#include <cstdint> +#include <cstring> +#include <malloc.h> +#include <windows.h> // For RtlPcToFileHeader function + +struct EHCatchableType { + uint32_t properties; + int32_t type_info; + uint32_t non_virtual_adjustment; + uint32_t offset_to_virtual_base_ptr; + uint32_t virtual_base_table_index; + uint32_t size; + int32_t copy_function; +}; + +struct EHCatchableTypeArray { + uint32_t catchable_types; + // It is variable size but we only need the first element of this array + int32_t array_of_catchable_types[1]; +}; + +struct EHThrowInfo { + uint32_t attributes; + int32_t unwind; + int32_t forward_compat; + int32_t catchable_type_array; +}; + +struct EHParameters { + uint32_t magic_number; + void* exception_object; + EHThrowInfo* throw_info; +#ifdef _M_AMD64 + uintptr_t throw_image_base; +#endif +}; + +struct EHExceptionRecord { + uint32_t exception_code; + uint32_t exception_flags; + void* exception_record; + void* exception_address; + uint32_t number_of_parameters; + EHParameters parameters; +}; + +// defined in vcruntime<ver>.dll +extern "C" EHExceptionRecord** __current_exception(); + +// This is internal compiler definition for MSVC but not for clang. +// We use our own EHThrowInfo because _ThrowInfo doesn't match actual +// compiler-generated structures in 64-bit mode. +#ifdef __clang__ +struct _ThrowInfo; +// defined in vcruntime<ver>.dll +_LIBCPP_NORETURN extern "C" void __stdcall _CxxThrowException( + void* __exc, _ThrowInfo* __throw_info); +#endif + +namespace { +struct ExceptionPtr { + void* exception_object; + const EHThrowInfo* throw_info; + std::atomic<size_t> counter; +#ifdef _M_AMD64 + PVOID image_base; +#endif + template <class T> + T convert(int32_t offset) { +#ifdef _M_AMD64 + uintptr_t value = reinterpret_cast<uintptr_t>(image_base) + + static_cast<uintptr_t>(offset); +#else + uintptr_t value = static_cast<uintptr_t>(offset); +#endif + T res; + static_assert( + sizeof(value) == sizeof(res), + "Can only convert to pointers or pointers to member functions"); + memcpy(&res, &value, sizeof(value)); + return res; + } + + void copy(void* dst, const void* src, const EHCatchableType* exc_type) { + struct Temp {}; + constexpr uint32_t virtual_base = 4; + if (exc_type->copy_function == 0) { + memcpy(dst, src, exc_type->size); + } else if (exc_type->properties & virtual_base) { + auto copy_constructor = + convert<void (Temp::*)(const void*, int)>(exc_type->copy_function); + ((Temp*)dst->*copy_constructor)(src, 1); + } else { + auto copy_constructor = + convert<void (Temp::*)(const void*)>(exc_type->copy_function); + ((Temp*)dst->*copy_constructor)(src); + } + } + + EHCatchableType* exception_type() { + return convert<EHCatchableType*>( + convert<EHCatchableTypeArray*>(throw_info->catchable_type_array) + ->array_of_catchable_types[0]); + } + + ExceptionPtr(const void* exception_object_, const EHThrowInfo* throw_info_) + : exception_object(nullptr), throw_info(throw_info_), counter(1) { +#ifdef _M_AMD64 + RtlPcToFileHeader( + reinterpret_cast<PVOID>(const_cast<EHThrowInfo*>(throw_info)), + &image_base); +#endif + EHCatchableType* exc_type = exception_type(); + this->exception_object = malloc(exc_type->size); + if (this->exception_object == nullptr) { + throw std::bad_alloc(); + } + copy(exception_object, exception_object_, exc_type); + } + + ~ExceptionPtr() { + if (throw_info->unwind && exception_object) { + struct Temp {}; + auto destructor = convert<void (Temp::*)()>(throw_info->unwind); + ((Temp*)exception_object->*destructor)(); + } + free(exception_object); + } + // _bad_alloc_storage must be initialized before bad_alloc, so we declare and define it first. static std::bad_alloc _bad_alloc_storage; - static ExceptionPtr bad_alloc; - //static ExceptionPtr bad_exception; -}; - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Waddress-of-temporary" -#endif - + static ExceptionPtr bad_alloc; + //static ExceptionPtr bad_exception; +}; + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Waddress-of-temporary" +#endif + std::bad_alloc ExceptionPtr::_bad_alloc_storage; -ExceptionPtr ExceptionPtr::bad_alloc( +ExceptionPtr ExceptionPtr::bad_alloc( &ExceptionPtr::_bad_alloc_storage, reinterpret_cast<const EHThrowInfo*>(__GetExceptionInfo(ExceptionPtr::_bad_alloc_storage))); - -/* ExceptionPtr -ExceptionPtr::bad_exception(&std::bad_exception(), - reinterpret_cast<const EHThrowInfo*>( - __GetExceptionInfo(std::bad_exception()))); */ - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - -} // namespace - -namespace std { - -exception_ptr::exception_ptr(const exception_ptr& __other) noexcept - : __ptr_(__other.__ptr_) { - if (__ptr_) { - reinterpret_cast<ExceptionPtr*>(__ptr_)->counter.fetch_add(1); - } -} - -exception_ptr& exception_ptr:: -operator=(const exception_ptr& __other) noexcept { - auto before = __ptr_; - __ptr_ = __other.__ptr_; - if (__ptr_) { - reinterpret_cast<ExceptionPtr*>(__ptr_)->counter.fetch_add(1); - } - if (before) { - if (reinterpret_cast<ExceptionPtr*>(before)->counter.fetch_sub(1) == 1) { - delete reinterpret_cast<ExceptionPtr*>(before); - } - } - return *this; -} - -exception_ptr::~exception_ptr() noexcept { - if (__ptr_) { - if (reinterpret_cast<ExceptionPtr*>(__ptr_)->counter.fetch_sub(1) == 1) { - delete reinterpret_cast<ExceptionPtr*>(__ptr_); - } - } -} - -exception_ptr __copy_exception_ptr(void* exception_object, - const void* throw_info) { - ExceptionPtr* ptr; - try { - ptr = new ExceptionPtr(exception_object, - reinterpret_cast<const EHThrowInfo*>(throw_info)); - } catch (const std::bad_alloc&) { - ptr = &ExceptionPtr::bad_alloc; - ptr->counter.fetch_add(1); - } catch (...) { - //ptr = &ExceptionPtr::bad_exception; - //ptr->counter.fetch_add(1); - std::terminate(); - } - exception_ptr res; - memcpy(&res, &ptr, sizeof(ptr)); - return res; -} - -exception_ptr current_exception() noexcept { - EHExceptionRecord** record = __current_exception(); - if (*record && !std::uncaught_exception()) { - return __copy_exception_ptr((*record)->parameters.exception_object, - (*record)->parameters.throw_info); - } - return exception_ptr(); -} - -_LIBCPP_NORETURN -void rethrow_exception(exception_ptr p) { - if (!p) { - throw std::bad_exception(); - } - ExceptionPtr* exc_ptr = reinterpret_cast<ExceptionPtr*>(p.__ptr_); - EHCatchableType* exc_type = exc_ptr->exception_type(); - // _CxxThrowException doesn't call free on exception object so we must - // allocate it on the stack. - void* dst = _alloca(exc_type->size); - exc_ptr->copy(dst, exc_ptr->exception_object, exc_type); - auto throw_info = reinterpret_cast<_ThrowInfo*>( - const_cast<EHThrowInfo*>(exc_ptr->throw_info)); - // For some reason clang doesn't call p destructor during unwinding. - // So we must clear it ourselves. - p = nullptr; - _CxxThrowException(dst, throw_info); -} - -nested_exception::nested_exception() noexcept : __ptr_(current_exception()) {} - -nested_exception::~nested_exception() noexcept {} - -_LIBCPP_NORETURN -void nested_exception::rethrow_nested() const { - if (__ptr_ == nullptr) - terminate(); - rethrow_exception(__ptr_); -} - -} // namespace std + +/* ExceptionPtr +ExceptionPtr::bad_exception(&std::bad_exception(), + reinterpret_cast<const EHThrowInfo*>( + __GetExceptionInfo(std::bad_exception()))); */ + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +} // namespace + +namespace std { + +exception_ptr::exception_ptr(const exception_ptr& __other) noexcept + : __ptr_(__other.__ptr_) { + if (__ptr_) { + reinterpret_cast<ExceptionPtr*>(__ptr_)->counter.fetch_add(1); + } +} + +exception_ptr& exception_ptr:: +operator=(const exception_ptr& __other) noexcept { + auto before = __ptr_; + __ptr_ = __other.__ptr_; + if (__ptr_) { + reinterpret_cast<ExceptionPtr*>(__ptr_)->counter.fetch_add(1); + } + if (before) { + if (reinterpret_cast<ExceptionPtr*>(before)->counter.fetch_sub(1) == 1) { + delete reinterpret_cast<ExceptionPtr*>(before); + } + } + return *this; +} + +exception_ptr::~exception_ptr() noexcept { + if (__ptr_) { + if (reinterpret_cast<ExceptionPtr*>(__ptr_)->counter.fetch_sub(1) == 1) { + delete reinterpret_cast<ExceptionPtr*>(__ptr_); + } + } +} + +exception_ptr __copy_exception_ptr(void* exception_object, + const void* throw_info) { + ExceptionPtr* ptr; + try { + ptr = new ExceptionPtr(exception_object, + reinterpret_cast<const EHThrowInfo*>(throw_info)); + } catch (const std::bad_alloc&) { + ptr = &ExceptionPtr::bad_alloc; + ptr->counter.fetch_add(1); + } catch (...) { + //ptr = &ExceptionPtr::bad_exception; + //ptr->counter.fetch_add(1); + std::terminate(); + } + exception_ptr res; + memcpy(&res, &ptr, sizeof(ptr)); + return res; +} + +exception_ptr current_exception() noexcept { + EHExceptionRecord** record = __current_exception(); + if (*record && !std::uncaught_exception()) { + return __copy_exception_ptr((*record)->parameters.exception_object, + (*record)->parameters.throw_info); + } + return exception_ptr(); +} + +_LIBCPP_NORETURN +void rethrow_exception(exception_ptr p) { + if (!p) { + throw std::bad_exception(); + } + ExceptionPtr* exc_ptr = reinterpret_cast<ExceptionPtr*>(p.__ptr_); + EHCatchableType* exc_type = exc_ptr->exception_type(); + // _CxxThrowException doesn't call free on exception object so we must + // allocate it on the stack. + void* dst = _alloca(exc_type->size); + exc_ptr->copy(dst, exc_ptr->exception_object, exc_type); + auto throw_info = reinterpret_cast<_ThrowInfo*>( + const_cast<EHThrowInfo*>(exc_ptr->throw_info)); + // For some reason clang doesn't call p destructor during unwinding. + // So we must clear it ourselves. + p = nullptr; + _CxxThrowException(dst, throw_info); +} + +nested_exception::nested_exception() noexcept : __ptr_(current_exception()) {} + +nested_exception::~nested_exception() noexcept {} + +_LIBCPP_NORETURN +void nested_exception::rethrow_nested() const { + if (__ptr_ == nullptr) + terminate(); + rethrow_exception(__ptr_); +} + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp index 191b9d4304..9e8ec04e11 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp @@ -1,79 +1,79 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include <stdio.h> -#include <stdlib.h> - -namespace std { - -exception_ptr::~exception_ptr() noexcept -{ -# warning exception_ptr not yet implemented - fprintf(stderr, "exception_ptr not yet implemented\n"); - ::abort(); -} - -exception_ptr::exception_ptr(const exception_ptr& other) noexcept - : __ptr_(other.__ptr_) -{ -# warning exception_ptr not yet implemented - fprintf(stderr, "exception_ptr not yet implemented\n"); - ::abort(); -} - -exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept -{ -# warning exception_ptr not yet implemented - fprintf(stderr, "exception_ptr not yet implemented\n"); - ::abort(); -} - -nested_exception::nested_exception() noexcept - : __ptr_(current_exception()) -{ -} - -#if !defined(__GLIBCXX__) - -nested_exception::~nested_exception() noexcept -{ -} - -#endif - -_LIBCPP_NORETURN -void -nested_exception::rethrow_nested() const -{ -# warning exception_ptr not yet implemented - fprintf(stderr, "exception_ptr not yet implemented\n"); - ::abort(); -#if 0 - if (__ptr_ == nullptr) - terminate(); - rethrow_exception(__ptr_); -#endif // FIXME -} - -exception_ptr current_exception() noexcept -{ -# warning exception_ptr not yet implemented - fprintf(stderr, "exception_ptr not yet implemented\n"); - ::abort(); -} - -_LIBCPP_NORETURN -void rethrow_exception(exception_ptr p) -{ -# warning exception_ptr not yet implemented - fprintf(stderr, "exception_ptr not yet implemented\n"); - ::abort(); -} - -} // namespace std +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#include <stdlib.h> + +namespace std { + +exception_ptr::~exception_ptr() noexcept +{ +# warning exception_ptr not yet implemented + fprintf(stderr, "exception_ptr not yet implemented\n"); + ::abort(); +} + +exception_ptr::exception_ptr(const exception_ptr& other) noexcept + : __ptr_(other.__ptr_) +{ +# warning exception_ptr not yet implemented + fprintf(stderr, "exception_ptr not yet implemented\n"); + ::abort(); +} + +exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept +{ +# warning exception_ptr not yet implemented + fprintf(stderr, "exception_ptr not yet implemented\n"); + ::abort(); +} + +nested_exception::nested_exception() noexcept + : __ptr_(current_exception()) +{ +} + +#if !defined(__GLIBCXX__) + +nested_exception::~nested_exception() noexcept +{ +} + +#endif + +_LIBCPP_NORETURN +void +nested_exception::rethrow_nested() const +{ +# warning exception_ptr not yet implemented + fprintf(stderr, "exception_ptr not yet implemented\n"); + ::abort(); +#if 0 + if (__ptr_ == nullptr) + terminate(); + rethrow_exception(__ptr_); +#endif // FIXME +} + +exception_ptr current_exception() noexcept +{ +# warning exception_ptr not yet implemented + fprintf(stderr, "exception_ptr not yet implemented\n"); + ::abort(); +} + +_LIBCPP_NORETURN +void rethrow_exception(exception_ptr p) +{ +# warning exception_ptr not yet implemented + fprintf(stderr, "exception_ptr not yet implemented\n"); + ::abort(); +} + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/new_handler_fallback.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/new_handler_fallback.ipp index 838a9a7910..3eaeb489a1 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/new_handler_fallback.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/new_handler_fallback.ipp @@ -1,28 +1,28 @@ -// -*- C++ -*- -//===----------------------------------------------------------------------===// -// +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "../../include/atomic_support.h" - -namespace std { - -_LIBCPP_SAFE_STATIC static std::new_handler __new_handler; - -new_handler -set_new_handler(new_handler handler) noexcept -{ - return __libcpp_atomic_exchange(&__new_handler, handler); -} - -new_handler -get_new_handler() noexcept -{ - return __libcpp_atomic_load(&__new_handler); -} - -} // namespace std +// +//===----------------------------------------------------------------------===// + +#include "../../include/atomic_support.h" + +namespace std { + +_LIBCPP_SAFE_STATIC static std::new_handler __new_handler; + +new_handler +set_new_handler(new_handler handler) noexcept +{ + return __libcpp_atomic_exchange(&__new_handler, handler); +} + +new_handler +get_new_handler() noexcept +{ + return __libcpp_atomic_load(&__new_handler); +} + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/stdexcept_default.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/stdexcept_default.ipp index 8f390a737d..5d22b7894c 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/stdexcept_default.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/stdexcept_default.ipp @@ -1,64 +1,64 @@ -//===--------------------- stdexcept_default.ipp --------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "../../include/refstring.h" - -/* For _LIBCPPABI_VERSION */ -#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \ +//===--------------------- stdexcept_default.ipp --------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "../../include/refstring.h" + +/* For _LIBCPPABI_VERSION */ +#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \ (defined(LIBCXX_BUILDING_LIBCXXABI) || defined(LIBCXX_BUILDING_LIBCXXRT)) -#include <cxxabi.h> -#endif - -static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char*), ""); - -namespace std // purposefully not using versioning namespace -{ - -logic_error::logic_error(const string& msg) : __imp_(msg.c_str()) {} - -logic_error::logic_error(const char* msg) : __imp_(msg) {} - -logic_error::logic_error(const logic_error& le) noexcept : __imp_(le.__imp_) {} - -logic_error& logic_error::operator=(const logic_error& le) noexcept { - __imp_ = le.__imp_; - return *this; -} - -runtime_error::runtime_error(const string& msg) : __imp_(msg.c_str()) {} - -runtime_error::runtime_error(const char* msg) : __imp_(msg) {} - -runtime_error::runtime_error(const runtime_error& re) noexcept - : __imp_(re.__imp_) {} - -runtime_error& runtime_error::operator=(const runtime_error& re) noexcept { - __imp_ = re.__imp_; - return *this; -} - -#if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX) - -const char* logic_error::what() const noexcept { return __imp_.c_str(); } - -const char* runtime_error::what() const noexcept { return __imp_.c_str(); } - -logic_error::~logic_error() noexcept {} -domain_error::~domain_error() noexcept {} -invalid_argument::~invalid_argument() noexcept {} -length_error::~length_error() noexcept {} -out_of_range::~out_of_range() noexcept {} - -runtime_error::~runtime_error() noexcept {} -range_error::~range_error() noexcept {} -overflow_error::~overflow_error() noexcept {} -underflow_error::~underflow_error() noexcept {} - -#endif - -} // namespace std +#include <cxxabi.h> +#endif + +static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char*), ""); + +namespace std // purposefully not using versioning namespace +{ + +logic_error::logic_error(const string& msg) : __imp_(msg.c_str()) {} + +logic_error::logic_error(const char* msg) : __imp_(msg) {} + +logic_error::logic_error(const logic_error& le) noexcept : __imp_(le.__imp_) {} + +logic_error& logic_error::operator=(const logic_error& le) noexcept { + __imp_ = le.__imp_; + return *this; +} + +runtime_error::runtime_error(const string& msg) : __imp_(msg.c_str()) {} + +runtime_error::runtime_error(const char* msg) : __imp_(msg) {} + +runtime_error::runtime_error(const runtime_error& re) noexcept + : __imp_(re.__imp_) {} + +runtime_error& runtime_error::operator=(const runtime_error& re) noexcept { + __imp_ = re.__imp_; + return *this; +} + +#if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX) + +const char* logic_error::what() const noexcept { return __imp_.c_str(); } + +const char* runtime_error::what() const noexcept { return __imp_.c_str(); } + +logic_error::~logic_error() noexcept {} +domain_error::~domain_error() noexcept {} +invalid_argument::~invalid_argument() noexcept {} +length_error::~length_error() noexcept {} +out_of_range::~out_of_range() noexcept {} + +runtime_error::~runtime_error() noexcept {} +range_error::~range_error() noexcept {} +overflow_error::~overflow_error() noexcept {} +underflow_error::~underflow_error() noexcept {} + +#endif + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/runtime/stdexcept_vcruntime.ipp b/contrib/libs/cxxsupp/libcxx/src/support/runtime/stdexcept_vcruntime.ipp index c62e702dc5..94eed465ae 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/runtime/stdexcept_vcruntime.ipp +++ b/contrib/libs/cxxsupp/libcxx/src/support/runtime/stdexcept_vcruntime.ipp @@ -1,16 +1,16 @@ -//===------------------- stdexcept_vcruntime.ipp --------------------------===// -// -// 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_ABI_VCRUNTIME -#error This file may only be used when defering to vcruntime -#endif - -namespace std { -logic_error::logic_error(std::string const& s) : exception(s.c_str()) {} -runtime_error::runtime_error(std::string const& s) : exception(s.c_str()) {} -} // namespace std +//===------------------- stdexcept_vcruntime.ipp --------------------------===// +// +// 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_ABI_VCRUNTIME +#error This file may only be used when defering to vcruntime +#endif + +namespace std { +logic_error::logic_error(std::string const& s) : exception(s.c_str()) {} +runtime_error::runtime_error(std::string const& s) : exception(s.c_str()) {} +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/support/solaris/README b/contrib/libs/cxxsupp/libcxx/src/support/solaris/README index 3f475a5d9c..89c887a3b4 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/solaris/README +++ b/contrib/libs/cxxsupp/libcxx/src/support/solaris/README @@ -1,4 +1,4 @@ -This directory contains a partial implementation of the xlocale APIs for -Solaris. Some portions are lifted from FreeBSD libc, and so are covered by a -2-clause BSD license instead of the MIT/UUIC license that the rest of libc++ is -distributed under. +This directory contains a partial implementation of the xlocale APIs for +Solaris. Some portions are lifted from FreeBSD libc, and so are covered by a +2-clause BSD license instead of the MIT/UUIC license that the rest of libc++ is +distributed under. diff --git a/contrib/libs/cxxsupp/libcxx/src/support/solaris/mbsnrtowcs.inc b/contrib/libs/cxxsupp/libcxx/src/support/solaris/mbsnrtowcs.inc index 2aa5fc1737..074045277c 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/solaris/mbsnrtowcs.inc +++ b/contrib/libs/cxxsupp/libcxx/src/support/solaris/mbsnrtowcs.inc @@ -1,76 +1,76 @@ - - -/*- - * As noted in the source, some portions of this implementation are copied from - * FreeBSD libc. These are covered by the following copyright: - * - * Copyright (c) 2002-2004 Tim J. Robbins. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -size_t -mbsnrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src, - size_t nms, size_t len, mbstate_t * __restrict ps, locale_t loc) -{ - const char *s; - size_t nchr; - wchar_t wc; - size_t nb; - FIX_LOCALE(loc); - - s = *src; - nchr = 0; - - if (dst == NULL) { - for (;;) { - if ((nb = mbrtowc_l(&wc, s, nms, ps, loc)) == (size_t)-1) - /* Invalid sequence - mbrtowc() sets errno. */ - return ((size_t)-1); - else if (nb == 0 || nb == (size_t)-2) - return (nchr); - s += nb; - nms -= nb; - nchr++; - } - /*NOTREACHED*/ - } - - while (len-- > 0) { - if ((nb = mbrtowc_l(dst, s, nms, ps, loc)) == (size_t)-1) { - *src = s; - return ((size_t)-1); - } else if (nb == (size_t)-2) { - *src = s + nms; - return (nchr); - } else if (nb == 0) { - *src = NULL; - return (nchr); - } - s += nb; - nms -= nb; - nchr++; - dst++; - } - *src = s; - return (nchr); -} + + +/*- + * As noted in the source, some portions of this implementation are copied from + * FreeBSD libc. These are covered by the following copyright: + * + * Copyright (c) 2002-2004 Tim J. Robbins. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +size_t +mbsnrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src, + size_t nms, size_t len, mbstate_t * __restrict ps, locale_t loc) +{ + const char *s; + size_t nchr; + wchar_t wc; + size_t nb; + FIX_LOCALE(loc); + + s = *src; + nchr = 0; + + if (dst == NULL) { + for (;;) { + if ((nb = mbrtowc_l(&wc, s, nms, ps, loc)) == (size_t)-1) + /* Invalid sequence - mbrtowc() sets errno. */ + return ((size_t)-1); + else if (nb == 0 || nb == (size_t)-2) + return (nchr); + s += nb; + nms -= nb; + nchr++; + } + /*NOTREACHED*/ + } + + while (len-- > 0) { + if ((nb = mbrtowc_l(dst, s, nms, ps, loc)) == (size_t)-1) { + *src = s; + return ((size_t)-1); + } else if (nb == (size_t)-2) { + *src = s + nms; + return (nchr); + } else if (nb == 0) { + *src = NULL; + return (nchr); + } + s += nb; + nms -= nb; + nchr++; + dst++; + } + *src = s; + return (nchr); +} diff --git a/contrib/libs/cxxsupp/libcxx/src/support/solaris/wcsnrtombs.inc b/contrib/libs/cxxsupp/libcxx/src/support/solaris/wcsnrtombs.inc index 7c241c310b..239079e471 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/solaris/wcsnrtombs.inc +++ b/contrib/libs/cxxsupp/libcxx/src/support/solaris/wcsnrtombs.inc @@ -1,92 +1,92 @@ -/*- - * Copyright (c) 2002-2004 Tim J. Robbins. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - -size_t -wcsnrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, - size_t nwc, size_t len, mbstate_t * __restrict ps, locale_t loc) -{ - FIX_LOCALE(loc); - mbstate_t mbsbak; - char buf[MB_CUR_MAX_L(loc)]; - const wchar_t *s; - size_t nbytes; - size_t nb; - - s = *src; - nbytes = 0; - - if (dst == NULL) { - while (nwc-- > 0) { - if ((nb = wcrtomb_l(buf, *s, ps, loc)) == (size_t)-1) - /* Invalid character - wcrtomb() sets errno. */ - return ((size_t)-1); - else if (*s == L'\0') - return (nbytes + nb - 1); - s++; - nbytes += nb; - } - return (nbytes); - } - - while (len > 0 && nwc-- > 0) { - if (len > (size_t)MB_CUR_MAX_L(loc)) { - /* Enough space to translate in-place. */ - if ((nb = wcrtomb_l(dst, *s, ps, loc)) == (size_t)-1) { - *src = s; - return ((size_t)-1); - } - } else { - /* - * May not be enough space; use temp. buffer. - * - * We need to save a copy of the conversion state - * here so we can restore it if the multibyte - * character is too long for the buffer. - */ - mbsbak = *ps; - if ((nb = wcrtomb_l(buf, *s, ps, loc)) == (size_t)-1) { - *src = s; - return ((size_t)-1); - } - if (nb > (int)len) { - /* MB sequence for character won't fit. */ - *ps = mbsbak; - break; - } - memcpy(dst, buf, nb); - } - if (*s == L'\0') { - *src = NULL; - return (nbytes + nb - 1); - } - s++; - dst += nb; - len -= nb; - nbytes += nb; - } - *src = s; - return (nbytes); -} +/*- + * Copyright (c) 2002-2004 Tim J. Robbins. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +size_t +wcsnrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, + size_t nwc, size_t len, mbstate_t * __restrict ps, locale_t loc) +{ + FIX_LOCALE(loc); + mbstate_t mbsbak; + char buf[MB_CUR_MAX_L(loc)]; + const wchar_t *s; + size_t nbytes; + size_t nb; + + s = *src; + nbytes = 0; + + if (dst == NULL) { + while (nwc-- > 0) { + if ((nb = wcrtomb_l(buf, *s, ps, loc)) == (size_t)-1) + /* Invalid character - wcrtomb() sets errno. */ + return ((size_t)-1); + else if (*s == L'\0') + return (nbytes + nb - 1); + s++; + nbytes += nb; + } + return (nbytes); + } + + while (len > 0 && nwc-- > 0) { + if (len > (size_t)MB_CUR_MAX_L(loc)) { + /* Enough space to translate in-place. */ + if ((nb = wcrtomb_l(dst, *s, ps, loc)) == (size_t)-1) { + *src = s; + return ((size_t)-1); + } + } else { + /* + * May not be enough space; use temp. buffer. + * + * We need to save a copy of the conversion state + * here so we can restore it if the multibyte + * character is too long for the buffer. + */ + mbsbak = *ps; + if ((nb = wcrtomb_l(buf, *s, ps, loc)) == (size_t)-1) { + *src = s; + return ((size_t)-1); + } + if (nb > (int)len) { + /* MB sequence for character won't fit. */ + *ps = mbsbak; + break; + } + memcpy(dst, buf, nb); + } + if (*s == L'\0') { + *src = NULL; + return (nbytes + nb - 1); + } + s++; + dst += nb; + len -= nb; + nbytes += nb; + } + *src = s; + return (nbytes); +} diff --git a/contrib/libs/cxxsupp/libcxx/src/support/solaris/xlocale.cpp b/contrib/libs/cxxsupp/libcxx/src/support/solaris/xlocale.cpp index 6b6ce2065a..d25adcd21d 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/solaris/xlocale.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/support/solaris/xlocale.cpp @@ -1,68 +1,68 @@ -//===----------------------------------------------------------------------===// -// +//===----------------------------------------------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#ifdef __sun__ - -#include "__support/solaris/xlocale.h" -#include <stdarg.h> -#include <stdio.h> -#include <sys/localedef.h> - -extern "C" { - -int isxdigit_l(int __c, locale_t __l) { - return isxdigit(__c); -} - -int iswxdigit_l(wint_t __c, locale_t __l) { - return isxdigit(__c); -} - -// FIXME: This disregards the locale, which is Very Wrong -#define vsnprintf_l(__s, __n, __l, __format, __va) \ +// +//===----------------------------------------------------------------------===// + +#ifdef __sun__ + +#include "__support/solaris/xlocale.h" +#include <stdarg.h> +#include <stdio.h> +#include <sys/localedef.h> + +extern "C" { + +int isxdigit_l(int __c, locale_t __l) { + return isxdigit(__c); +} + +int iswxdigit_l(wint_t __c, locale_t __l) { + return isxdigit(__c); +} + +// FIXME: This disregards the locale, which is Very Wrong +#define vsnprintf_l(__s, __n, __l, __format, __va) \ vsnprintf(__s, __n, __format, __va) - -int snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) -{ - va_list __va; - va_start(__va, __format); - int __res = vsnprintf_l(__s, __n , __l, __format, __va); - va_end(__va); - return __res; -} - -int asprintf_l(char **__s, locale_t __l, const char *__format, ...) { - va_list __va; - va_start(__va, __format); - // FIXME: - int __res = vasprintf(__s, __format, __va); - va_end(__va); - return __res; -} - -int sscanf_l(const char *__s, locale_t __l, const char *__format, ...) { - va_list __va; - va_start(__va, __format); - // FIXME: - int __res = vsscanf(__s, __format, __va); - va_end(__va); - return __res; -} - -size_t mbrtowc_l(wchar_t *__pwc, const char *__pmb, - size_t __max, mbstate_t *__ps, locale_t __loc) { - return mbrtowc(__pwc, __pmb, __max, __ps); -} - -struct lconv *localeconv_l(locale_t __l) { - return localeconv(); -} - -}; - -#endif // __sun__ + +int snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) +{ + va_list __va; + va_start(__va, __format); + int __res = vsnprintf_l(__s, __n , __l, __format, __va); + va_end(__va); + return __res; +} + +int asprintf_l(char **__s, locale_t __l, const char *__format, ...) { + va_list __va; + va_start(__va, __format); + // FIXME: + int __res = vasprintf(__s, __format, __va); + va_end(__va); + return __res; +} + +int sscanf_l(const char *__s, locale_t __l, const char *__format, ...) { + va_list __va; + va_start(__va, __format); + // FIXME: + int __res = vsscanf(__s, __format, __va); + va_end(__va); + return __res; +} + +size_t mbrtowc_l(wchar_t *__pwc, const char *__pmb, + size_t __max, mbstate_t *__ps, locale_t __loc) { + return mbrtowc(__pwc, __pmb, __max, __ps); +} + +struct lconv *localeconv_l(locale_t __l) { + return localeconv(); +} + +}; + +#endif // __sun__ diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/atomic_win32.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/atomic_win32.cpp index 04717c8c87..28cb0722ce 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/win32/atomic_win32.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/atomic_win32.cpp @@ -1,31 +1,31 @@ -#include <intrin.h> -#include <cstdint> - - -_LIBCPP_BEGIN_NAMESPACE_STD - -namespace { -static const int __msvc_locks_size = 1024; -volatile long __msvc_locks[__msvc_locks_size]; - -size_t __msvc_lock_hash(void* __p) { - uintptr_t __num = reinterpret_cast<uintptr_t>(__p); - return (__num ^ (__num >> 10)) & (__msvc_locks_size - 1); -} -} - -void __msvc_lock(void* __p) { - volatile long& __lock = __msvc_locks[__msvc_lock_hash(__p)]; - while (_InterlockedExchange(&__lock, 1) == 0) { -#if defined(_M_ARM) || defined(_M_ARM64) - __yield(); -#endif - } -} - -void __msvc_unlock(void* __p) { - volatile long& __lock = __msvc_locks[__msvc_lock_hash(__p)]; - _InterlockedExchange(&__lock, 0); -} - -_LIBCPP_END_NAMESPACE_STD
\ No newline at end of file +#include <intrin.h> +#include <cstdint> + + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace { +static const int __msvc_locks_size = 1024; +volatile long __msvc_locks[__msvc_locks_size]; + +size_t __msvc_lock_hash(void* __p) { + uintptr_t __num = reinterpret_cast<uintptr_t>(__p); + return (__num ^ (__num >> 10)) & (__msvc_locks_size - 1); +} +} + +void __msvc_lock(void* __p) { + volatile long& __lock = __msvc_locks[__msvc_lock_hash(__p)]; + while (_InterlockedExchange(&__lock, 1) == 0) { +#if defined(_M_ARM) || defined(_M_ARM64) + __yield(); +#endif + } +} + +void __msvc_unlock(void* __p) { + volatile long& __lock = __msvc_locks[__msvc_lock_hash(__p)]; + _InterlockedExchange(&__lock, 0); +} + +_LIBCPP_END_NAMESPACE_STD
\ No newline at end of file diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp index 67a8391e0f..f10916875d 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/locale_win32.cpp @@ -1,138 +1,138 @@ -//===----------------------------------------------------------------------===// -// +//===----------------------------------------------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include <locale> -#include <cstdarg> // va_start, va_end -#include <memory> -#include <type_traits> - -int __libcpp_vasprintf(char **sptr, const char *__restrict fmt, va_list ap); - -using std::__libcpp_locale_guard; - -// FIXME: base currently unused. Needs manual work to construct the new locale -locale_t newlocale( int mask, const char * locale, locale_t /*base*/ ) -{ - return {_create_locale( LC_ALL, locale ), locale}; -} - -decltype(MB_CUR_MAX) MB_CUR_MAX_L( locale_t __l ) -{ -#if defined(_LIBCPP_MSVCRT) - return ___mb_cur_max_l_func(__l); -#else - __libcpp_locale_guard __current(__l); - return MB_CUR_MAX; -#endif -} - -lconv *localeconv_l( locale_t &loc ) -{ - __libcpp_locale_guard __current(loc); - lconv *lc = localeconv(); - if (!lc) - return lc; - return loc.__store_lconv(lc); -} -size_t mbrlen_l( const char *__restrict s, size_t n, - mbstate_t *__restrict ps, locale_t loc ) -{ - __libcpp_locale_guard __current(loc); - return mbrlen( s, n, ps ); -} -size_t mbsrtowcs_l( wchar_t *__restrict dst, const char **__restrict src, - size_t len, mbstate_t *__restrict ps, locale_t loc ) -{ - __libcpp_locale_guard __current(loc); - return mbsrtowcs( dst, src, len, ps ); -} -size_t wcrtomb_l( char *__restrict s, wchar_t wc, mbstate_t *__restrict ps, - locale_t loc ) -{ - __libcpp_locale_guard __current(loc); - return wcrtomb( s, wc, ps ); -} -size_t mbrtowc_l( wchar_t *__restrict pwc, const char *__restrict s, - size_t n, mbstate_t *__restrict ps, locale_t loc ) -{ - __libcpp_locale_guard __current(loc); - return mbrtowc( pwc, s, n, ps ); -} -size_t mbsnrtowcs_l( wchar_t *__restrict dst, const char **__restrict src, - size_t nms, size_t len, mbstate_t *__restrict ps, locale_t loc ) -{ - __libcpp_locale_guard __current(loc); - return mbsnrtowcs( dst, src, nms, len, ps ); -} -size_t wcsnrtombs_l( char *__restrict dst, const wchar_t **__restrict src, - size_t nwc, size_t len, mbstate_t *__restrict ps, locale_t loc ) -{ - __libcpp_locale_guard __current(loc); - return wcsnrtombs( dst, src, nwc, len, ps ); -} -wint_t btowc_l( int c, locale_t loc ) -{ - __libcpp_locale_guard __current(loc); - return btowc( c ); -} -int wctob_l( wint_t c, locale_t loc ) -{ - __libcpp_locale_guard __current(loc); - return wctob( c ); -} - -int snprintf_l(char *ret, size_t n, locale_t loc, const char *format, ...) -{ - va_list ap; - va_start( ap, format ); -#if defined(_LIBCPP_MSVCRT) - // FIXME: Remove usage of internal CRT function and globals. - int result = __stdio_common_vsprintf( - _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, - ret, n, format, loc, ap); -#else - __libcpp_locale_guard __current(loc); - int result = vsnprintf( ret, n, format, ap ); -#endif - va_end(ap); - return result; -} - -int asprintf_l( char **ret, locale_t loc, const char *format, ... ) -{ - va_list ap; - va_start( ap, format ); - int result = vasprintf_l( ret, loc, format, ap ); - va_end(ap); - return result; -} -int vasprintf_l( char **ret, locale_t loc, const char *format, va_list ap ) -{ - __libcpp_locale_guard __current(loc); - return __libcpp_vasprintf( ret, format, ap ); -} - -#if !defined(_LIBCPP_MSVCRT) -float strtof_l(const char* nptr, char** endptr, locale_t loc) { - __libcpp_locale_guard __current(loc); - return strtof(nptr, endptr); -} - -long double strtold_l(const char* nptr, char** endptr, locale_t loc) { - __libcpp_locale_guard __current(loc); - return strtold(nptr, endptr); -} -#endif - -#if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800 -size_t strftime_l(char *ret, size_t n, const char *format, const struct tm *tm, - locale_t loc) { - __libcpp_locale_guard __current(loc); - return strftime(ret, n, format, tm); -} -#endif +// +//===----------------------------------------------------------------------===// + +#include <locale> +#include <cstdarg> // va_start, va_end +#include <memory> +#include <type_traits> + +int __libcpp_vasprintf(char **sptr, const char *__restrict fmt, va_list ap); + +using std::__libcpp_locale_guard; + +// FIXME: base currently unused. Needs manual work to construct the new locale +locale_t newlocale( int mask, const char * locale, locale_t /*base*/ ) +{ + return {_create_locale( LC_ALL, locale ), locale}; +} + +decltype(MB_CUR_MAX) MB_CUR_MAX_L( locale_t __l ) +{ +#if defined(_LIBCPP_MSVCRT) + return ___mb_cur_max_l_func(__l); +#else + __libcpp_locale_guard __current(__l); + return MB_CUR_MAX; +#endif +} + +lconv *localeconv_l( locale_t &loc ) +{ + __libcpp_locale_guard __current(loc); + lconv *lc = localeconv(); + if (!lc) + return lc; + return loc.__store_lconv(lc); +} +size_t mbrlen_l( const char *__restrict s, size_t n, + mbstate_t *__restrict ps, locale_t loc ) +{ + __libcpp_locale_guard __current(loc); + return mbrlen( s, n, ps ); +} +size_t mbsrtowcs_l( wchar_t *__restrict dst, const char **__restrict src, + size_t len, mbstate_t *__restrict ps, locale_t loc ) +{ + __libcpp_locale_guard __current(loc); + return mbsrtowcs( dst, src, len, ps ); +} +size_t wcrtomb_l( char *__restrict s, wchar_t wc, mbstate_t *__restrict ps, + locale_t loc ) +{ + __libcpp_locale_guard __current(loc); + return wcrtomb( s, wc, ps ); +} +size_t mbrtowc_l( wchar_t *__restrict pwc, const char *__restrict s, + size_t n, mbstate_t *__restrict ps, locale_t loc ) +{ + __libcpp_locale_guard __current(loc); + return mbrtowc( pwc, s, n, ps ); +} +size_t mbsnrtowcs_l( wchar_t *__restrict dst, const char **__restrict src, + size_t nms, size_t len, mbstate_t *__restrict ps, locale_t loc ) +{ + __libcpp_locale_guard __current(loc); + return mbsnrtowcs( dst, src, nms, len, ps ); +} +size_t wcsnrtombs_l( char *__restrict dst, const wchar_t **__restrict src, + size_t nwc, size_t len, mbstate_t *__restrict ps, locale_t loc ) +{ + __libcpp_locale_guard __current(loc); + return wcsnrtombs( dst, src, nwc, len, ps ); +} +wint_t btowc_l( int c, locale_t loc ) +{ + __libcpp_locale_guard __current(loc); + return btowc( c ); +} +int wctob_l( wint_t c, locale_t loc ) +{ + __libcpp_locale_guard __current(loc); + return wctob( c ); +} + +int snprintf_l(char *ret, size_t n, locale_t loc, const char *format, ...) +{ + va_list ap; + va_start( ap, format ); +#if defined(_LIBCPP_MSVCRT) + // FIXME: Remove usage of internal CRT function and globals. + int result = __stdio_common_vsprintf( + _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, + ret, n, format, loc, ap); +#else + __libcpp_locale_guard __current(loc); + int result = vsnprintf( ret, n, format, ap ); +#endif + va_end(ap); + return result; +} + +int asprintf_l( char **ret, locale_t loc, const char *format, ... ) +{ + va_list ap; + va_start( ap, format ); + int result = vasprintf_l( ret, loc, format, ap ); + va_end(ap); + return result; +} +int vasprintf_l( char **ret, locale_t loc, const char *format, va_list ap ) +{ + __libcpp_locale_guard __current(loc); + return __libcpp_vasprintf( ret, format, ap ); +} + +#if !defined(_LIBCPP_MSVCRT) +float strtof_l(const char* nptr, char** endptr, locale_t loc) { + __libcpp_locale_guard __current(loc); + return strtof(nptr, endptr); +} + +long double strtold_l(const char* nptr, char** endptr, locale_t loc) { + __libcpp_locale_guard __current(loc); + return strtold(nptr, endptr); +} +#endif + +#if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800 +size_t strftime_l(char *ret, size_t n, const char *format, const struct tm *tm, + locale_t loc) { + __libcpp_locale_guard __current(loc); + return strftime(ret, n, format, tm); +} +#endif diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/new_win32.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/new_win32.cpp index 600c802a96..00eff4abf9 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/win32/new_win32.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/new_win32.cpp @@ -1,28 +1,28 @@ -#include <atomic> -#include <new> - -namespace std { - -void -__throw_bad_alloc() -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - throw bad_alloc(); -#endif -} - -static std::atomic<std::new_handler> __new_handler; - -new_handler -set_new_handler(new_handler handler) _NOEXCEPT -{ - return __new_handler.exchange(handler); -} - -new_handler -get_new_handler() _NOEXCEPT -{ - return __new_handler.load(); -} - -}
\ No newline at end of file +#include <atomic> +#include <new> + +namespace std { + +void +__throw_bad_alloc() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw bad_alloc(); +#endif +} + +static std::atomic<std::new_handler> __new_handler; + +new_handler +set_new_handler(new_handler handler) _NOEXCEPT +{ + return __new_handler.exchange(handler); +} + +new_handler +get_new_handler() _NOEXCEPT +{ + return __new_handler.load(); +} + +}
\ No newline at end of file diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/support.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/support.cpp index 8532d623ca..11702a788b 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/win32/support.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/support.cpp @@ -1,166 +1,166 @@ -//===----------------------------------------------------------------------===// -// +//===----------------------------------------------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include <cstdarg> // va_start, va_end -#include <cstddef> // size_t -#include <cstdlib> // malloc -#include <cstdio> // vsprintf, vsnprintf -#include <cstring> // strcpy, wcsncpy -#include <cwchar> // mbstate_t - - -// Like sprintf, but when return value >= 0 it returns -// a pointer to a malloc'd string in *sptr. -// If return >= 0, use free to delete *sptr. -int __libcpp_vasprintf( char **sptr, const char *__restrict format, va_list ap ) -{ - *sptr = NULL; - // Query the count required. - va_list ap_copy; - va_copy(ap_copy, ap); - int count = _vsnprintf( NULL, 0, format, ap_copy ); - va_end(ap_copy); - if (count < 0) - return count; - size_t buffer_size = static_cast<size_t>(count) + 1; - char* p = static_cast<char*>(malloc(buffer_size)); - if ( ! p ) - return -1; - // If we haven't used exactly what was required, something is wrong. - // Maybe bug in vsnprintf. Report the error and return. - if (_vsnprintf(p, buffer_size, format, ap) != count) { - free(p); - return -1; - } - // All good. This is returning memory to the caller not freeing it. - *sptr = p; - return count; -} - +// +//===----------------------------------------------------------------------===// + +#include <cstdarg> // va_start, va_end +#include <cstddef> // size_t +#include <cstdlib> // malloc +#include <cstdio> // vsprintf, vsnprintf +#include <cstring> // strcpy, wcsncpy +#include <cwchar> // mbstate_t + + +// Like sprintf, but when return value >= 0 it returns +// a pointer to a malloc'd string in *sptr. +// If return >= 0, use free to delete *sptr. +int __libcpp_vasprintf( char **sptr, const char *__restrict format, va_list ap ) +{ + *sptr = NULL; + // Query the count required. + va_list ap_copy; + va_copy(ap_copy, ap); + int count = _vsnprintf( NULL, 0, format, ap_copy ); + va_end(ap_copy); + if (count < 0) + return count; + size_t buffer_size = static_cast<size_t>(count) + 1; + char* p = static_cast<char*>(malloc(buffer_size)); + if ( ! p ) + return -1; + // If we haven't used exactly what was required, something is wrong. + // Maybe bug in vsnprintf. Report the error and return. + if (_vsnprintf(p, buffer_size, format, ap) != count) { + free(p); + return -1; + } + // All good. This is returning memory to the caller not freeing it. + *sptr = p; + return count; +} + // Returns >= 0: the number of wide characters found in the // multi byte sequence src (of src_size_bytes), that fit in the buffer dst -// (of max_dest_chars elements size). The count returned excludes the +// (of max_dest_chars elements size). The count returned excludes the // null terminator. When dst is NULL, no characters are copied -// and no "out" parameters are updated. -// Returns (size_t) -1: an incomplete sequence encountered. +// and no "out" parameters are updated. +// Returns (size_t) -1: an incomplete sequence encountered. // Leaves *src pointing the next character to convert or NULL -// if a null character was converted from *src. -size_t mbsnrtowcs( wchar_t *__restrict dst, const char **__restrict src, - size_t src_size_bytes, size_t max_dest_chars, mbstate_t *__restrict ps ) -{ - const size_t terminated_sequence = static_cast<size_t>(0); - //const size_t invalid_sequence = static_cast<size_t>(-1); - const size_t incomplete_sequence = static_cast< size_t>(-2); - - size_t dest_converted = 0; - size_t source_converted = 0; - size_t source_remaining = src_size_bytes; - size_t result = 0; - bool have_result = false; - +// if a null character was converted from *src. +size_t mbsnrtowcs( wchar_t *__restrict dst, const char **__restrict src, + size_t src_size_bytes, size_t max_dest_chars, mbstate_t *__restrict ps ) +{ + const size_t terminated_sequence = static_cast<size_t>(0); + //const size_t invalid_sequence = static_cast<size_t>(-1); + const size_t incomplete_sequence = static_cast< size_t>(-2); + + size_t dest_converted = 0; + size_t source_converted = 0; + size_t source_remaining = src_size_bytes; + size_t result = 0; + bool have_result = false; + // If dst is null then max_dest_chars should be ignored according to the // standard. Setting max_dest_chars to a large value has this effect. if (!dst) max_dest_chars = static_cast<size_t>(-1); - while ( source_remaining ) { - if ( dst && dest_converted >= max_dest_chars ) - break; - // Converts one multi byte character. - // if result > 0, it's the size in bytes of that character. - // othewise if result is zero it indicates the null character has been found. - // otherwise it's an error and errno may be set. - size_t char_size = mbrtowc( dst ? dst + dest_converted : NULL, *src + source_converted, source_remaining, ps ); - // Don't do anything to change errno from here on. - if ( char_size > 0 ) { - source_remaining -= char_size; - source_converted += char_size; - ++dest_converted; - continue; - } - result = char_size; - have_result = true; - break; - } - if ( dst ) { - if ( have_result && result == terminated_sequence ) - *src = NULL; - else - *src += source_converted; - } - if ( have_result && result != terminated_sequence && result != incomplete_sequence ) - return static_cast<size_t>(-1); - - return dest_converted; -} - -// Converts max_source_chars from the wide character buffer pointer to by *src, -// into the multi byte character sequence buffer stored at dst which must be -// dst_size_bytes bytes in size. -// Returns >= 0: the number of bytes in the sequence -// converted from *src, excluding the null terminator. -// Returns size_t(-1) if an error occurs, also sets errno. + while ( source_remaining ) { + if ( dst && dest_converted >= max_dest_chars ) + break; + // Converts one multi byte character. + // if result > 0, it's the size in bytes of that character. + // othewise if result is zero it indicates the null character has been found. + // otherwise it's an error and errno may be set. + size_t char_size = mbrtowc( dst ? dst + dest_converted : NULL, *src + source_converted, source_remaining, ps ); + // Don't do anything to change errno from here on. + if ( char_size > 0 ) { + source_remaining -= char_size; + source_converted += char_size; + ++dest_converted; + continue; + } + result = char_size; + have_result = true; + break; + } + if ( dst ) { + if ( have_result && result == terminated_sequence ) + *src = NULL; + else + *src += source_converted; + } + if ( have_result && result != terminated_sequence && result != incomplete_sequence ) + return static_cast<size_t>(-1); + + return dest_converted; +} + +// Converts max_source_chars from the wide character buffer pointer to by *src, +// into the multi byte character sequence buffer stored at dst which must be +// dst_size_bytes bytes in size. +// Returns >= 0: the number of bytes in the sequence +// converted from *src, excluding the null terminator. +// Returns size_t(-1) if an error occurs, also sets errno. // If dst is NULL dst_size_bytes is ignored and no bytes are copied to dst -// and no "out" parameters are updated. -size_t wcsnrtombs( char *__restrict dst, const wchar_t **__restrict src, - size_t max_source_chars, size_t dst_size_bytes, mbstate_t *__restrict ps ) -{ - //const size_t invalid_sequence = static_cast<size_t>(-1); - - size_t source_converted = 0; - size_t dest_converted = 0; - size_t dest_remaining = dst_size_bytes; - size_t char_size = 0; - const errno_t no_error = ( errno_t) 0; - errno_t result = ( errno_t ) 0; - bool have_result = false; - bool terminator_found = false; - +// and no "out" parameters are updated. +size_t wcsnrtombs( char *__restrict dst, const wchar_t **__restrict src, + size_t max_source_chars, size_t dst_size_bytes, mbstate_t *__restrict ps ) +{ + //const size_t invalid_sequence = static_cast<size_t>(-1); + + size_t source_converted = 0; + size_t dest_converted = 0; + size_t dest_remaining = dst_size_bytes; + size_t char_size = 0; + const errno_t no_error = ( errno_t) 0; + errno_t result = ( errno_t ) 0; + bool have_result = false; + bool terminator_found = false; + // If dst is null then dst_size_bytes should be ignored according to the // standard. Setting dest_remaining to a large value has this effect. if (!dst) dest_remaining = static_cast<size_t>(-1); - while ( source_converted != max_source_chars ) { - if ( ! dest_remaining ) - break; - wchar_t c = (*src)[source_converted]; - if ( dst ) - result = wcrtomb_s( &char_size, dst + dest_converted, dest_remaining, c, ps); - else - result = wcrtomb_s( &char_size, NULL, 0, c, ps); + while ( source_converted != max_source_chars ) { + if ( ! dest_remaining ) + break; + wchar_t c = (*src)[source_converted]; + if ( dst ) + result = wcrtomb_s( &char_size, dst + dest_converted, dest_remaining, c, ps); + else + result = wcrtomb_s( &char_size, NULL, 0, c, ps); // If result is zero there is no error and char_size contains the - // size of the multi-byte-sequence converted. - // Otherwise result indicates an errno type error. - if ( result == no_error ) { - if ( c == L'\0' ) { - terminator_found = true; - break; - } - ++source_converted; - if ( dst ) - dest_remaining -= char_size; - dest_converted += char_size; - continue; - } - have_result = true; - break; - } - if ( dst ) { - if ( terminator_found ) - *src = NULL; - else - *src = *src + source_converted; - } - if ( have_result && result != no_error ) { - errno = result; - return static_cast<size_t>(-1); - } - - return dest_converted; -} + // size of the multi-byte-sequence converted. + // Otherwise result indicates an errno type error. + if ( result == no_error ) { + if ( c == L'\0' ) { + terminator_found = true; + break; + } + ++source_converted; + if ( dst ) + dest_remaining -= char_size; + dest_converted += char_size; + continue; + } + have_result = true; + break; + } + if ( dst ) { + if ( terminator_found ) + *src = NULL; + else + *src = *src + source_converted; + } + if ( have_result && result != no_error ) { + errno = result; + return static_cast<size_t>(-1); + } + + return dest_converted; +} diff --git a/contrib/libs/cxxsupp/libcxx/src/support/win32/thread_win32.cpp b/contrib/libs/cxxsupp/libcxx/src/support/win32/thread_win32.cpp index 7d79153c88..9506822da8 100644 --- a/contrib/libs/cxxsupp/libcxx/src/support/win32/thread_win32.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/support/win32/thread_win32.cpp @@ -1,310 +1,310 @@ -//===----------------------------------------------------------------------===// -// +//===----------------------------------------------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include <__threading_support> -#define NOMINMAX -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <process.h> -#include <fibersapi.h> - -_LIBCPP_BEGIN_NAMESPACE_STD - -static_assert(sizeof(__libcpp_mutex_t) == sizeof(SRWLOCK), ""); -static_assert(alignof(__libcpp_mutex_t) == alignof(SRWLOCK), ""); - -static_assert(sizeof(__libcpp_recursive_mutex_t) == sizeof(CRITICAL_SECTION), - ""); -static_assert(alignof(__libcpp_recursive_mutex_t) == alignof(CRITICAL_SECTION), - ""); - -static_assert(sizeof(__libcpp_condvar_t) == sizeof(CONDITION_VARIABLE), ""); -static_assert(alignof(__libcpp_condvar_t) == alignof(CONDITION_VARIABLE), ""); - -static_assert(sizeof(__libcpp_exec_once_flag) == sizeof(INIT_ONCE), ""); -static_assert(alignof(__libcpp_exec_once_flag) == alignof(INIT_ONCE), ""); - -static_assert(sizeof(__libcpp_thread_id) == sizeof(DWORD), ""); -static_assert(alignof(__libcpp_thread_id) == alignof(DWORD), ""); - -static_assert(sizeof(__libcpp_thread_t) == sizeof(HANDLE), ""); -static_assert(alignof(__libcpp_thread_t) == alignof(HANDLE), ""); - -static_assert(sizeof(__libcpp_tls_key) == sizeof(DWORD), ""); -static_assert(alignof(__libcpp_tls_key) == alignof(DWORD), ""); - -static_assert(sizeof(__libcpp_semaphore_t) == sizeof(HANDLE), ""); -static_assert(alignof(__libcpp_semaphore_t) == alignof(HANDLE), ""); - -// Mutex -int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) -{ - InitializeCriticalSection((LPCRITICAL_SECTION)__m); - return 0; -} - -int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) -{ - EnterCriticalSection((LPCRITICAL_SECTION)__m); - return 0; -} - -bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) -{ - return TryEnterCriticalSection((LPCRITICAL_SECTION)__m) != 0; -} - -int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) -{ - LeaveCriticalSection((LPCRITICAL_SECTION)__m); - return 0; -} - -int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) -{ - DeleteCriticalSection((LPCRITICAL_SECTION)__m); - return 0; -} - -int __libcpp_mutex_lock(__libcpp_mutex_t *__m) -{ - AcquireSRWLockExclusive((PSRWLOCK)__m); - return 0; -} - -bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) -{ - return TryAcquireSRWLockExclusive((PSRWLOCK)__m) != 0; -} - -int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) -{ - ReleaseSRWLockExclusive((PSRWLOCK)__m); - return 0; -} - -int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) -{ - static_cast<void>(__m); - return 0; -} - -// Condition Variable -int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) -{ - WakeConditionVariable((PCONDITION_VARIABLE)__cv); - return 0; -} - -int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) -{ - WakeAllConditionVariable((PCONDITION_VARIABLE)__cv); - return 0; -} - -int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) -{ - SleepConditionVariableSRW((PCONDITION_VARIABLE)__cv, (PSRWLOCK)__m, INFINITE, 0); - return 0; -} - -int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, - __libcpp_timespec_t *__ts) -{ - using namespace _VSTD::chrono; - - auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec); - auto abstime = - system_clock::time_point(duration_cast<system_clock::duration>(duration)); - auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now()); - - if (!SleepConditionVariableSRW((PCONDITION_VARIABLE)__cv, (PSRWLOCK)__m, - timeout_ms.count() > 0 ? timeout_ms.count() - : 0, - 0)) - { - auto __ec = GetLastError(); - return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec; - } - return 0; -} - -int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) -{ - static_cast<void>(__cv); - return 0; -} - -// Execute Once -static inline _LIBCPP_INLINE_VISIBILITY BOOL CALLBACK -__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter, - PVOID *__context) -{ - static_cast<void>(__init_once); - static_cast<void>(__context); - - void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter); - init_routine(); - return TRUE; -} - -int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, - void (*__init_routine)(void)) -{ - if (!InitOnceExecuteOnce((PINIT_ONCE)__flag, __libcpp_init_once_execute_once_thunk, - reinterpret_cast<void *>(__init_routine), NULL)) - return GetLastError(); - return 0; -} - -// Thread ID -bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, - __libcpp_thread_id __rhs) -{ - return __lhs == __rhs; -} - -bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) -{ - return __lhs < __rhs; -} - -// Thread -struct __libcpp_beginthreadex_thunk_data -{ - void *(*__func)(void *); - void *__arg; -}; - -static inline _LIBCPP_INLINE_VISIBILITY unsigned WINAPI -__libcpp_beginthreadex_thunk(void *__raw_data) -{ - auto *__data = - static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data); - auto *__func = __data->__func; - void *__arg = __data->__arg; - delete __data; - return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg))); -} - -bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { - return *__t == 0; -} - -int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), - void *__arg) -{ - auto *__data = new __libcpp_beginthreadex_thunk_data; - __data->__func = __func; - __data->__arg = __arg; - - *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, - __libcpp_beginthreadex_thunk, - __data, 0, nullptr)); - - if (*__t) - return 0; - return GetLastError(); -} - -__libcpp_thread_id __libcpp_thread_get_current_id() -{ - return GetCurrentThreadId(); -} - -__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) -{ - return GetThreadId(*__t); -} - -int __libcpp_thread_join(__libcpp_thread_t *__t) -{ - if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED) - return GetLastError(); - if (!CloseHandle(*__t)) - return GetLastError(); - return 0; -} - -int __libcpp_thread_detach(__libcpp_thread_t *__t) -{ - if (!CloseHandle(*__t)) - return GetLastError(); - return 0; -} - -void __libcpp_thread_yield() -{ - SwitchToThread(); -} - -void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) -{ - // round-up to the nearest millisecond - chrono::milliseconds __ms = chrono::ceil<chrono::milliseconds>(__ns); - // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx) - Sleep(__ms.count()); -} - -// Thread Local Storage -int __libcpp_tls_create(__libcpp_tls_key* __key, - void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)) -{ - DWORD index = FlsAlloc(__at_exit); - if (index == FLS_OUT_OF_INDEXES) - return GetLastError(); - *__key = index; - return 0; -} - -void *__libcpp_tls_get(__libcpp_tls_key __key) -{ - return FlsGetValue(__key); -} - -int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) -{ - if (!FlsSetValue(__key, __p)) - return GetLastError(); - return 0; -} - -// Semaphores -bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init) -{ - *(PHANDLE)__sem = CreateSemaphoreEx(nullptr, __init, _LIBCPP_SEMAPHORE_MAX, - nullptr, 0, SEMAPHORE_ALL_ACCESS); - return *__sem != nullptr; -} - -bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem) -{ - CloseHandle(*(PHANDLE)__sem); - return true; -} - -bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem) -{ - return ReleaseSemaphore(*(PHANDLE)__sem, 1, nullptr); -} - -bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem) -{ - return WaitForSingleObjectEx(*(PHANDLE)__sem, INFINITE, false) == - WAIT_OBJECT_0; -} - -bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, - chrono::nanoseconds const& __ns) -{ - chrono::milliseconds __ms = chrono::ceil<chrono::milliseconds>(__ns); - return WaitForSingleObjectEx(*(PHANDLE)__sem, __ms.count(), false) == - WAIT_OBJECT_0; -} - -_LIBCPP_END_NAMESPACE_STD +// +//===----------------------------------------------------------------------===// + +#include <__threading_support> +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <process.h> +#include <fibersapi.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +static_assert(sizeof(__libcpp_mutex_t) == sizeof(SRWLOCK), ""); +static_assert(alignof(__libcpp_mutex_t) == alignof(SRWLOCK), ""); + +static_assert(sizeof(__libcpp_recursive_mutex_t) == sizeof(CRITICAL_SECTION), + ""); +static_assert(alignof(__libcpp_recursive_mutex_t) == alignof(CRITICAL_SECTION), + ""); + +static_assert(sizeof(__libcpp_condvar_t) == sizeof(CONDITION_VARIABLE), ""); +static_assert(alignof(__libcpp_condvar_t) == alignof(CONDITION_VARIABLE), ""); + +static_assert(sizeof(__libcpp_exec_once_flag) == sizeof(INIT_ONCE), ""); +static_assert(alignof(__libcpp_exec_once_flag) == alignof(INIT_ONCE), ""); + +static_assert(sizeof(__libcpp_thread_id) == sizeof(DWORD), ""); +static_assert(alignof(__libcpp_thread_id) == alignof(DWORD), ""); + +static_assert(sizeof(__libcpp_thread_t) == sizeof(HANDLE), ""); +static_assert(alignof(__libcpp_thread_t) == alignof(HANDLE), ""); + +static_assert(sizeof(__libcpp_tls_key) == sizeof(DWORD), ""); +static_assert(alignof(__libcpp_tls_key) == alignof(DWORD), ""); + +static_assert(sizeof(__libcpp_semaphore_t) == sizeof(HANDLE), ""); +static_assert(alignof(__libcpp_semaphore_t) == alignof(HANDLE), ""); + +// Mutex +int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m) +{ + InitializeCriticalSection((LPCRITICAL_SECTION)__m); + return 0; +} + +int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m) +{ + EnterCriticalSection((LPCRITICAL_SECTION)__m); + return 0; +} + +bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m) +{ + return TryEnterCriticalSection((LPCRITICAL_SECTION)__m) != 0; +} + +int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m) +{ + LeaveCriticalSection((LPCRITICAL_SECTION)__m); + return 0; +} + +int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m) +{ + DeleteCriticalSection((LPCRITICAL_SECTION)__m); + return 0; +} + +int __libcpp_mutex_lock(__libcpp_mutex_t *__m) +{ + AcquireSRWLockExclusive((PSRWLOCK)__m); + return 0; +} + +bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m) +{ + return TryAcquireSRWLockExclusive((PSRWLOCK)__m) != 0; +} + +int __libcpp_mutex_unlock(__libcpp_mutex_t *__m) +{ + ReleaseSRWLockExclusive((PSRWLOCK)__m); + return 0; +} + +int __libcpp_mutex_destroy(__libcpp_mutex_t *__m) +{ + static_cast<void>(__m); + return 0; +} + +// Condition Variable +int __libcpp_condvar_signal(__libcpp_condvar_t *__cv) +{ + WakeConditionVariable((PCONDITION_VARIABLE)__cv); + return 0; +} + +int __libcpp_condvar_broadcast(__libcpp_condvar_t *__cv) +{ + WakeAllConditionVariable((PCONDITION_VARIABLE)__cv); + return 0; +} + +int __libcpp_condvar_wait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m) +{ + SleepConditionVariableSRW((PCONDITION_VARIABLE)__cv, (PSRWLOCK)__m, INFINITE, 0); + return 0; +} + +int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m, + __libcpp_timespec_t *__ts) +{ + using namespace _VSTD::chrono; + + auto duration = seconds(__ts->tv_sec) + nanoseconds(__ts->tv_nsec); + auto abstime = + system_clock::time_point(duration_cast<system_clock::duration>(duration)); + auto timeout_ms = duration_cast<milliseconds>(abstime - system_clock::now()); + + if (!SleepConditionVariableSRW((PCONDITION_VARIABLE)__cv, (PSRWLOCK)__m, + timeout_ms.count() > 0 ? timeout_ms.count() + : 0, + 0)) + { + auto __ec = GetLastError(); + return __ec == ERROR_TIMEOUT ? ETIMEDOUT : __ec; + } + return 0; +} + +int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) +{ + static_cast<void>(__cv); + return 0; +} + +// Execute Once +static inline _LIBCPP_INLINE_VISIBILITY BOOL CALLBACK +__libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter, + PVOID *__context) +{ + static_cast<void>(__init_once); + static_cast<void>(__context); + + void (*init_routine)(void) = reinterpret_cast<void (*)(void)>(__parameter); + init_routine(); + return TRUE; +} + +int __libcpp_execute_once(__libcpp_exec_once_flag *__flag, + void (*__init_routine)(void)) +{ + if (!InitOnceExecuteOnce((PINIT_ONCE)__flag, __libcpp_init_once_execute_once_thunk, + reinterpret_cast<void *>(__init_routine), NULL)) + return GetLastError(); + return 0; +} + +// Thread ID +bool __libcpp_thread_id_equal(__libcpp_thread_id __lhs, + __libcpp_thread_id __rhs) +{ + return __lhs == __rhs; +} + +bool __libcpp_thread_id_less(__libcpp_thread_id __lhs, __libcpp_thread_id __rhs) +{ + return __lhs < __rhs; +} + +// Thread +struct __libcpp_beginthreadex_thunk_data +{ + void *(*__func)(void *); + void *__arg; +}; + +static inline _LIBCPP_INLINE_VISIBILITY unsigned WINAPI +__libcpp_beginthreadex_thunk(void *__raw_data) +{ + auto *__data = + static_cast<__libcpp_beginthreadex_thunk_data *>(__raw_data); + auto *__func = __data->__func; + void *__arg = __data->__arg; + delete __data; + return static_cast<unsigned>(reinterpret_cast<uintptr_t>(__func(__arg))); +} + +bool __libcpp_thread_isnull(const __libcpp_thread_t *__t) { + return *__t == 0; +} + +int __libcpp_thread_create(__libcpp_thread_t *__t, void *(*__func)(void *), + void *__arg) +{ + auto *__data = new __libcpp_beginthreadex_thunk_data; + __data->__func = __func; + __data->__arg = __arg; + + *__t = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, + __libcpp_beginthreadex_thunk, + __data, 0, nullptr)); + + if (*__t) + return 0; + return GetLastError(); +} + +__libcpp_thread_id __libcpp_thread_get_current_id() +{ + return GetCurrentThreadId(); +} + +__libcpp_thread_id __libcpp_thread_get_id(const __libcpp_thread_t *__t) +{ + return GetThreadId(*__t); +} + +int __libcpp_thread_join(__libcpp_thread_t *__t) +{ + if (WaitForSingleObjectEx(*__t, INFINITE, FALSE) == WAIT_FAILED) + return GetLastError(); + if (!CloseHandle(*__t)) + return GetLastError(); + return 0; +} + +int __libcpp_thread_detach(__libcpp_thread_t *__t) +{ + if (!CloseHandle(*__t)) + return GetLastError(); + return 0; +} + +void __libcpp_thread_yield() +{ + SwitchToThread(); +} + +void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) +{ + // round-up to the nearest millisecond + chrono::milliseconds __ms = chrono::ceil<chrono::milliseconds>(__ns); + // FIXME(compnerd) this should be an alertable sleep (WFSO or SleepEx) + Sleep(__ms.count()); +} + +// Thread Local Storage +int __libcpp_tls_create(__libcpp_tls_key* __key, + void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)) +{ + DWORD index = FlsAlloc(__at_exit); + if (index == FLS_OUT_OF_INDEXES) + return GetLastError(); + *__key = index; + return 0; +} + +void *__libcpp_tls_get(__libcpp_tls_key __key) +{ + return FlsGetValue(__key); +} + +int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) +{ + if (!FlsSetValue(__key, __p)) + return GetLastError(); + return 0; +} + +// Semaphores +bool __libcpp_semaphore_init(__libcpp_semaphore_t* __sem, int __init) +{ + *(PHANDLE)__sem = CreateSemaphoreEx(nullptr, __init, _LIBCPP_SEMAPHORE_MAX, + nullptr, 0, SEMAPHORE_ALL_ACCESS); + return *__sem != nullptr; +} + +bool __libcpp_semaphore_destroy(__libcpp_semaphore_t* __sem) +{ + CloseHandle(*(PHANDLE)__sem); + return true; +} + +bool __libcpp_semaphore_post(__libcpp_semaphore_t* __sem) +{ + return ReleaseSemaphore(*(PHANDLE)__sem, 1, nullptr); +} + +bool __libcpp_semaphore_wait(__libcpp_semaphore_t* __sem) +{ + return WaitForSingleObjectEx(*(PHANDLE)__sem, INFINITE, false) == + WAIT_OBJECT_0; +} + +bool __libcpp_semaphore_wait_timed(__libcpp_semaphore_t* __sem, + chrono::nanoseconds const& __ns) +{ + chrono::milliseconds __ms = chrono::ceil<chrono::milliseconds>(__ns); + return WaitForSingleObjectEx(*(PHANDLE)__sem, __ms.count(), false) == + WAIT_OBJECT_0; +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/system_error.cpp b/contrib/libs/cxxsupp/libcxx/src/system_error.cpp index 2c0fc97734..a1ea6c4754 100644 --- a/contrib/libs/cxxsupp/libcxx/src/system_error.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/system_error.cpp @@ -1,295 +1,295 @@ -//===---------------------- system_error.cpp ------------------------------===// -// +//===---------------------- system_error.cpp ------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "__config" - -#include "system_error" - -#include "include/config_elast.h" -#include "cerrno" -#include "cstring" -#include "cstdio" -#include "cstdlib" -#include "string" -#include "string.h" -#include "__debug" - -#if defined(__ANDROID__) -#include <android/api-level.h> -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -// class error_category - -#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) -error_category::error_category() noexcept -{ -} -#endif - -error_category::~error_category() noexcept -{ -} - -error_condition -error_category::default_error_condition(int ev) const noexcept -{ - return error_condition(ev, *this); -} - -bool -error_category::equivalent(int code, const error_condition& condition) const noexcept -{ - return default_error_condition(code) == condition; -} - -bool -error_category::equivalent(const error_code& code, int condition) const noexcept -{ - return *this == code.category() && code.value() == condition; -} - -#if !defined(_LIBCPP_HAS_NO_THREADS) -namespace { - -// GLIBC also uses 1024 as the maximum buffer size internally. -constexpr size_t strerror_buff_size = 1024; - -string do_strerror_r(int ev); - -#if defined(_LIBCPP_MSVCRT_LIKE) -string do_strerror_r(int ev) { - char buffer[strerror_buff_size]; - if (::strerror_s(buffer, strerror_buff_size, ev) == 0) - return string(buffer); - std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev); - return string(buffer); -} -#else - -// Only one of the two following functions will be used, depending on -// the return type of strerror_r: - -// For the GNU variant, a char* return value: -__attribute__((unused)) const char * -handle_strerror_r_return(char *strerror_return, char *buffer) { - // GNU always returns a string pointer in its return value. The - // string might point to either the input buffer, or a static - // buffer, but we don't care which. - return strerror_return; -} - -// For the POSIX variant: an int return value. -__attribute__((unused)) const char * -handle_strerror_r_return(int strerror_return, char *buffer) { - // The POSIX variant either: - // - fills in the provided buffer and returns 0 - // - returns a positive error value, or +// +//===----------------------------------------------------------------------===// + +#include "__config" + +#include "system_error" + +#include "include/config_elast.h" +#include "cerrno" +#include "cstring" +#include "cstdio" +#include "cstdlib" +#include "string" +#include "string.h" +#include "__debug" + +#if defined(__ANDROID__) +#include <android/api-level.h> +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// class error_category + +#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) +error_category::error_category() noexcept +{ +} +#endif + +error_category::~error_category() noexcept +{ +} + +error_condition +error_category::default_error_condition(int ev) const noexcept +{ + return error_condition(ev, *this); +} + +bool +error_category::equivalent(int code, const error_condition& condition) const noexcept +{ + return default_error_condition(code) == condition; +} + +bool +error_category::equivalent(const error_code& code, int condition) const noexcept +{ + return *this == code.category() && code.value() == condition; +} + +#if !defined(_LIBCPP_HAS_NO_THREADS) +namespace { + +// GLIBC also uses 1024 as the maximum buffer size internally. +constexpr size_t strerror_buff_size = 1024; + +string do_strerror_r(int ev); + +#if defined(_LIBCPP_MSVCRT_LIKE) +string do_strerror_r(int ev) { + char buffer[strerror_buff_size]; + if (::strerror_s(buffer, strerror_buff_size, ev) == 0) + return string(buffer); + std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev); + return string(buffer); +} +#else + +// Only one of the two following functions will be used, depending on +// the return type of strerror_r: + +// For the GNU variant, a char* return value: +__attribute__((unused)) const char * +handle_strerror_r_return(char *strerror_return, char *buffer) { + // GNU always returns a string pointer in its return value. The + // string might point to either the input buffer, or a static + // buffer, but we don't care which. + return strerror_return; +} + +// For the POSIX variant: an int return value. +__attribute__((unused)) const char * +handle_strerror_r_return(int strerror_return, char *buffer) { + // The POSIX variant either: + // - fills in the provided buffer and returns 0 + // - returns a positive error value, or // - returns -1 and fills in errno with an error value. - if (strerror_return == 0) - return buffer; - - // Only handle EINVAL. Other errors abort. - int new_errno = strerror_return == -1 ? errno : strerror_return; - if (new_errno == EINVAL) - return ""; - - _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r"); - // FIXME maybe? 'strerror_buff_size' is likely to exceed the - // maximum error size so ERANGE shouldn't be returned. - std::abort(); -} - -// This function handles both GNU and POSIX variants, dispatching to -// one of the two above functions. -string do_strerror_r(int ev) { - char buffer[strerror_buff_size]; - // Preserve errno around the call. (The C++ standard requires that - // system_error functions not modify errno). - const int old_errno = errno; - const char *error_message = handle_strerror_r_return( - ::strerror_r(ev, buffer, strerror_buff_size), buffer); - // If we didn't get any message, print one now. - if (!error_message[0]) { + if (strerror_return == 0) + return buffer; + + // Only handle EINVAL. Other errors abort. + int new_errno = strerror_return == -1 ? errno : strerror_return; + if (new_errno == EINVAL) + return ""; + + _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r"); + // FIXME maybe? 'strerror_buff_size' is likely to exceed the + // maximum error size so ERANGE shouldn't be returned. + std::abort(); +} + +// This function handles both GNU and POSIX variants, dispatching to +// one of the two above functions. +string do_strerror_r(int ev) { + char buffer[strerror_buff_size]; + // Preserve errno around the call. (The C++ standard requires that + // system_error functions not modify errno). + const int old_errno = errno; + const char *error_message = handle_strerror_r_return( + ::strerror_r(ev, buffer, strerror_buff_size), buffer); + // If we didn't get any message, print one now. + if (!error_message[0]) { std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev); error_message = buffer; - } - errno = old_errno; - return string(error_message); -} -#endif -} // end namespace -#endif - -string -__do_message::message(int ev) const -{ -#if defined(_LIBCPP_HAS_NO_THREADS) - return string(::strerror(ev)); -#else - return do_strerror_r(ev); -#endif -} - -class _LIBCPP_HIDDEN __generic_error_category - : public __do_message -{ -public: - virtual const char* name() const noexcept; - virtual string message(int ev) const; -}; - -const char* -__generic_error_category::name() const noexcept -{ - return "generic"; -} - -string -__generic_error_category::message(int ev) const -{ -#ifdef _LIBCPP_ELAST - if (ev > _LIBCPP_ELAST) - return string("unspecified generic_category error"); -#endif // _LIBCPP_ELAST - return __do_message::message(ev); -} - -const error_category& -generic_category() noexcept -{ - static __generic_error_category s; - return s; -} - -class _LIBCPP_HIDDEN __system_error_category - : public __do_message -{ -public: - virtual const char* name() const noexcept; - virtual string message(int ev) const; - virtual error_condition default_error_condition(int ev) const noexcept; -}; - -const char* -__system_error_category::name() const noexcept -{ - return "system"; -} - -string -__system_error_category::message(int ev) const -{ -#ifdef _LIBCPP_ELAST - if (ev > _LIBCPP_ELAST) - return string("unspecified system_category error"); -#endif // _LIBCPP_ELAST - return __do_message::message(ev); -} - -error_condition -__system_error_category::default_error_condition(int ev) const noexcept -{ -#ifdef _LIBCPP_ELAST - if (ev > _LIBCPP_ELAST) - return error_condition(ev, system_category()); -#endif // _LIBCPP_ELAST - return error_condition(ev, generic_category()); -} - -const error_category& -system_category() noexcept -{ - static __system_error_category s; - return s; -} - -// error_condition - -string -error_condition::message() const -{ - return __cat_->message(__val_); -} - -// error_code - -string -error_code::message() const -{ - return __cat_->message(__val_); -} - -// system_error - -string -system_error::__init(const error_code& ec, string what_arg) -{ - if (ec) - { - if (!what_arg.empty()) - what_arg += ": "; - what_arg += ec.message(); - } - return what_arg; -} - -system_error::system_error(error_code ec, const string& what_arg) - : runtime_error(__init(ec, what_arg)), - __ec_(ec) -{ -} - -system_error::system_error(error_code ec, const char* what_arg) - : runtime_error(__init(ec, what_arg)), - __ec_(ec) -{ -} - -system_error::system_error(error_code ec) - : runtime_error(__init(ec, "")), - __ec_(ec) -{ -} - -system_error::system_error(int ev, const error_category& ecat, const string& what_arg) - : runtime_error(__init(error_code(ev, ecat), what_arg)), - __ec_(error_code(ev, ecat)) -{ -} - -system_error::system_error(int ev, const error_category& ecat, const char* what_arg) - : runtime_error(__init(error_code(ev, ecat), what_arg)), - __ec_(error_code(ev, ecat)) -{ -} - -system_error::system_error(int ev, const error_category& ecat) - : runtime_error(__init(error_code(ev, ecat), "")), - __ec_(error_code(ev, ecat)) -{ -} - -system_error::~system_error() noexcept -{ -} - -void -__throw_system_error(int ev, const char* what_arg) -{ -#ifndef _LIBCPP_NO_EXCEPTIONS - throw system_error(error_code(ev, system_category()), what_arg); -#else - (void)ev; - (void)what_arg; - _VSTD::abort(); -#endif -} - -_LIBCPP_END_NAMESPACE_STD + } + errno = old_errno; + return string(error_message); +} +#endif +} // end namespace +#endif + +string +__do_message::message(int ev) const +{ +#if defined(_LIBCPP_HAS_NO_THREADS) + return string(::strerror(ev)); +#else + return do_strerror_r(ev); +#endif +} + +class _LIBCPP_HIDDEN __generic_error_category + : public __do_message +{ +public: + virtual const char* name() const noexcept; + virtual string message(int ev) const; +}; + +const char* +__generic_error_category::name() const noexcept +{ + return "generic"; +} + +string +__generic_error_category::message(int ev) const +{ +#ifdef _LIBCPP_ELAST + if (ev > _LIBCPP_ELAST) + return string("unspecified generic_category error"); +#endif // _LIBCPP_ELAST + return __do_message::message(ev); +} + +const error_category& +generic_category() noexcept +{ + static __generic_error_category s; + return s; +} + +class _LIBCPP_HIDDEN __system_error_category + : public __do_message +{ +public: + virtual const char* name() const noexcept; + virtual string message(int ev) const; + virtual error_condition default_error_condition(int ev) const noexcept; +}; + +const char* +__system_error_category::name() const noexcept +{ + return "system"; +} + +string +__system_error_category::message(int ev) const +{ +#ifdef _LIBCPP_ELAST + if (ev > _LIBCPP_ELAST) + return string("unspecified system_category error"); +#endif // _LIBCPP_ELAST + return __do_message::message(ev); +} + +error_condition +__system_error_category::default_error_condition(int ev) const noexcept +{ +#ifdef _LIBCPP_ELAST + if (ev > _LIBCPP_ELAST) + return error_condition(ev, system_category()); +#endif // _LIBCPP_ELAST + return error_condition(ev, generic_category()); +} + +const error_category& +system_category() noexcept +{ + static __system_error_category s; + return s; +} + +// error_condition + +string +error_condition::message() const +{ + return __cat_->message(__val_); +} + +// error_code + +string +error_code::message() const +{ + return __cat_->message(__val_); +} + +// system_error + +string +system_error::__init(const error_code& ec, string what_arg) +{ + if (ec) + { + if (!what_arg.empty()) + what_arg += ": "; + what_arg += ec.message(); + } + return what_arg; +} + +system_error::system_error(error_code ec, const string& what_arg) + : runtime_error(__init(ec, what_arg)), + __ec_(ec) +{ +} + +system_error::system_error(error_code ec, const char* what_arg) + : runtime_error(__init(ec, what_arg)), + __ec_(ec) +{ +} + +system_error::system_error(error_code ec) + : runtime_error(__init(ec, "")), + __ec_(ec) +{ +} + +system_error::system_error(int ev, const error_category& ecat, const string& what_arg) + : runtime_error(__init(error_code(ev, ecat), what_arg)), + __ec_(error_code(ev, ecat)) +{ +} + +system_error::system_error(int ev, const error_category& ecat, const char* what_arg) + : runtime_error(__init(error_code(ev, ecat), what_arg)), + __ec_(error_code(ev, ecat)) +{ +} + +system_error::system_error(int ev, const error_category& ecat) + : runtime_error(__init(error_code(ev, ecat), "")), + __ec_(error_code(ev, ecat)) +{ +} + +system_error::~system_error() noexcept +{ +} + +void +__throw_system_error(int ev, const char* what_arg) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS + throw system_error(error_code(ev, system_category()), what_arg); +#else + (void)ev; + (void)what_arg; + _VSTD::abort(); +#endif +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/thread.cpp b/contrib/libs/cxxsupp/libcxx/src/thread.cpp index 268bae5829..8dddb240b5 100644 --- a/contrib/libs/cxxsupp/libcxx/src/thread.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/thread.cpp @@ -1,211 +1,211 @@ -//===------------------------- thread.cpp----------------------------------===// -// +//===------------------------- thread.cpp----------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "__config" -#ifndef _LIBCPP_HAS_NO_THREADS - -#include "thread" -#include "exception" -#include "vector" -#include "future" -#include "limits" - -#if __has_include(<unistd.h>) -# include <unistd.h> // for sysconf -#endif - -#if defined(__NetBSD__) -#pragma weak pthread_create // Do not create libpthread dependency -#endif - -#if defined(_LIBCPP_WIN32API) -#include <windows.h> -#endif - -#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) -#pragma comment(lib, "pthread") -#endif - -_LIBCPP_BEGIN_NAMESPACE_STD - -thread::~thread() -{ - if (!__libcpp_thread_isnull(&__t_)) - terminate(); -} - -void -thread::join() -{ - int ec = EINVAL; - if (!__libcpp_thread_isnull(&__t_)) - { - ec = __libcpp_thread_join(&__t_); - if (ec == 0) - __t_ = _LIBCPP_NULL_THREAD; - } - - if (ec) - __throw_system_error(ec, "thread::join failed"); -} - -void -thread::detach() -{ - int ec = EINVAL; - if (!__libcpp_thread_isnull(&__t_)) - { - ec = __libcpp_thread_detach(&__t_); - if (ec == 0) - __t_ = _LIBCPP_NULL_THREAD; - } - - if (ec) - __throw_system_error(ec, "thread::detach failed"); -} - -unsigned -thread::hardware_concurrency() noexcept -{ -#if defined(_SC_NPROCESSORS_ONLN) - long result = sysconf(_SC_NPROCESSORS_ONLN); - // sysconf returns -1 if the name is invalid, the option does not exist or - // does not have a definite limit. - // if sysconf returns some other negative number, we have no idea - // what is going on. Default to something safe. - if (result < 0) - return 0; - return static_cast<unsigned>(result); -#elif defined(_LIBCPP_WIN32API) - SYSTEM_INFO info; - GetSystemInfo(&info); - return info.dwNumberOfProcessors; -#else // defined(CTL_HW) && defined(HW_NCPU) - // TODO: grovel through /proc or check cpuid on x86 and similar - // instructions on other architectures. -# if defined(_LIBCPP_WARNING) - _LIBCPP_WARNING("hardware_concurrency not yet implemented") -# else -# warning hardware_concurrency not yet implemented -# endif - return 0; // Means not computable [thread.thread.static] -#endif // defined(CTL_HW) && defined(HW_NCPU) -} - -namespace this_thread -{ - -void -sleep_for(const chrono::nanoseconds& ns) -{ - if (ns > chrono::nanoseconds::zero()) - { - __libcpp_thread_sleep_for(ns); - } -} - -} // this_thread - -__thread_specific_ptr<__thread_struct>& -__thread_local_data() -{ - static __thread_specific_ptr<__thread_struct> __p; - return __p; -} - -// __thread_struct_imp - -template <class T> -class _LIBCPP_HIDDEN __hidden_allocator -{ -public: - typedef T value_type; - - T* allocate(size_t __n) - {return static_cast<T*>(::operator new(__n * sizeof(T)));} - void deallocate(T* __p, size_t) {::operator delete(static_cast<void*>(__p));} - - size_t max_size() const {return size_t(~0) / sizeof(T);} -}; - -class _LIBCPP_HIDDEN __thread_struct_imp -{ - typedef vector<__assoc_sub_state*, - __hidden_allocator<__assoc_sub_state*> > _AsyncStates; - typedef vector<pair<condition_variable*, mutex*>, - __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; - - _AsyncStates async_states_; - _Notify notify_; - - __thread_struct_imp(const __thread_struct_imp&); - __thread_struct_imp& operator=(const __thread_struct_imp&); -public: - __thread_struct_imp() {} - ~__thread_struct_imp(); - - void notify_all_at_thread_exit(condition_variable* cv, mutex* m); - void __make_ready_at_thread_exit(__assoc_sub_state* __s); -}; - -__thread_struct_imp::~__thread_struct_imp() -{ - for (_Notify::iterator i = notify_.begin(), e = notify_.end(); - i != e; ++i) - { - i->second->unlock(); - i->first->notify_all(); - } - for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); - i != e; ++i) - { - (*i)->__make_ready(); - (*i)->__release_shared(); - } -} - -void -__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) -{ - notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); -} - -void -__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) -{ - async_states_.push_back(__s); - __s->__add_shared(); -} - -// __thread_struct - -__thread_struct::__thread_struct() - : __p_(new __thread_struct_imp) -{ -} - -__thread_struct::~__thread_struct() -{ - delete __p_; -} - -void -__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) -{ - __p_->notify_all_at_thread_exit(cv, m); -} - -void -__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) -{ - __p_->__make_ready_at_thread_exit(__s); -} - -_LIBCPP_END_NAMESPACE_STD - -#endif // !_LIBCPP_HAS_NO_THREADS +// +//===----------------------------------------------------------------------===// + +#include "__config" +#ifndef _LIBCPP_HAS_NO_THREADS + +#include "thread" +#include "exception" +#include "vector" +#include "future" +#include "limits" + +#if __has_include(<unistd.h>) +# include <unistd.h> // for sysconf +#endif + +#if defined(__NetBSD__) +#pragma weak pthread_create // Do not create libpthread dependency +#endif + +#if defined(_LIBCPP_WIN32API) +#include <windows.h> +#endif + +#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB) +#pragma comment(lib, "pthread") +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +thread::~thread() +{ + if (!__libcpp_thread_isnull(&__t_)) + terminate(); +} + +void +thread::join() +{ + int ec = EINVAL; + if (!__libcpp_thread_isnull(&__t_)) + { + ec = __libcpp_thread_join(&__t_); + if (ec == 0) + __t_ = _LIBCPP_NULL_THREAD; + } + + if (ec) + __throw_system_error(ec, "thread::join failed"); +} + +void +thread::detach() +{ + int ec = EINVAL; + if (!__libcpp_thread_isnull(&__t_)) + { + ec = __libcpp_thread_detach(&__t_); + if (ec == 0) + __t_ = _LIBCPP_NULL_THREAD; + } + + if (ec) + __throw_system_error(ec, "thread::detach failed"); +} + +unsigned +thread::hardware_concurrency() noexcept +{ +#if defined(_SC_NPROCESSORS_ONLN) + long result = sysconf(_SC_NPROCESSORS_ONLN); + // sysconf returns -1 if the name is invalid, the option does not exist or + // does not have a definite limit. + // if sysconf returns some other negative number, we have no idea + // what is going on. Default to something safe. + if (result < 0) + return 0; + return static_cast<unsigned>(result); +#elif defined(_LIBCPP_WIN32API) + SYSTEM_INFO info; + GetSystemInfo(&info); + return info.dwNumberOfProcessors; +#else // defined(CTL_HW) && defined(HW_NCPU) + // TODO: grovel through /proc or check cpuid on x86 and similar + // instructions on other architectures. +# if defined(_LIBCPP_WARNING) + _LIBCPP_WARNING("hardware_concurrency not yet implemented") +# else +# warning hardware_concurrency not yet implemented +# endif + return 0; // Means not computable [thread.thread.static] +#endif // defined(CTL_HW) && defined(HW_NCPU) +} + +namespace this_thread +{ + +void +sleep_for(const chrono::nanoseconds& ns) +{ + if (ns > chrono::nanoseconds::zero()) + { + __libcpp_thread_sleep_for(ns); + } +} + +} // this_thread + +__thread_specific_ptr<__thread_struct>& +__thread_local_data() +{ + static __thread_specific_ptr<__thread_struct> __p; + return __p; +} + +// __thread_struct_imp + +template <class T> +class _LIBCPP_HIDDEN __hidden_allocator +{ +public: + typedef T value_type; + + T* allocate(size_t __n) + {return static_cast<T*>(::operator new(__n * sizeof(T)));} + void deallocate(T* __p, size_t) {::operator delete(static_cast<void*>(__p));} + + size_t max_size() const {return size_t(~0) / sizeof(T);} +}; + +class _LIBCPP_HIDDEN __thread_struct_imp +{ + typedef vector<__assoc_sub_state*, + __hidden_allocator<__assoc_sub_state*> > _AsyncStates; + typedef vector<pair<condition_variable*, mutex*>, + __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; + + _AsyncStates async_states_; + _Notify notify_; + + __thread_struct_imp(const __thread_struct_imp&); + __thread_struct_imp& operator=(const __thread_struct_imp&); +public: + __thread_struct_imp() {} + ~__thread_struct_imp(); + + void notify_all_at_thread_exit(condition_variable* cv, mutex* m); + void __make_ready_at_thread_exit(__assoc_sub_state* __s); +}; + +__thread_struct_imp::~__thread_struct_imp() +{ + for (_Notify::iterator i = notify_.begin(), e = notify_.end(); + i != e; ++i) + { + i->second->unlock(); + i->first->notify_all(); + } + for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); + i != e; ++i) + { + (*i)->__make_ready(); + (*i)->__release_shared(); + } +} + +void +__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) +{ + notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); +} + +void +__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) +{ + async_states_.push_back(__s); + __s->__add_shared(); +} + +// __thread_struct + +__thread_struct::__thread_struct() + : __p_(new __thread_struct_imp) +{ +} + +__thread_struct::~__thread_struct() +{ + delete __p_; +} + +void +__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) +{ + __p_->notify_all_at_thread_exit(cv, m); +} + +void +__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) +{ + __p_->__make_ready_at_thread_exit(__s); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // !_LIBCPP_HAS_NO_THREADS diff --git a/contrib/libs/cxxsupp/libcxx/src/typeinfo.cpp b/contrib/libs/cxxsupp/libcxx/src/typeinfo.cpp index b25bc4e58f..baace5643c 100644 --- a/contrib/libs/cxxsupp/libcxx/src/typeinfo.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/typeinfo.cpp @@ -1,57 +1,57 @@ -//===------------------------- typeinfo.cpp -------------------------------===// -// +//===------------------------- typeinfo.cpp -------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "typeinfo" - -#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_ABI_VCRUNTIME) -#include <string.h> - -int std::type_info::__compare(const type_info &__rhs) const noexcept { - if (&__data == &__rhs.__data) - return 0; - return strcmp(&__data.__decorated_name[1], &__rhs.__data.__decorated_name[1]); -} - -const char *std::type_info::name() const noexcept { - // TODO(compnerd) cache demangled &__data.__decorated_name[1] - return &__data.__decorated_name[1]; -} - -size_t std::type_info::hash_code() const noexcept { -#if defined(_WIN64) - constexpr size_t fnv_offset_basis = 14695981039346656037ull; - constexpr size_t fnv_prime = 10995116282110ull; -#else - constexpr size_t fnv_offset_basis = 2166136261ull; - constexpr size_t fnv_prime = 16777619ull; -#endif - - size_t value = fnv_offset_basis; - for (const char* c = &__data.__decorated_name[1]; *c; ++c) { - value ^= static_cast<size_t>(static_cast<unsigned char>(*c)); - value *= fnv_prime; - } - -#if defined(_WIN64) - value ^= value >> 32; -#endif - - return value; -} -#endif // _LIBCPP_ABI_MICROSOFT - -// FIXME: Remove the _LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY configuration. -#if (!defined(LIBCXX_BUILDING_LIBCXXABI) && \ +// +//===----------------------------------------------------------------------===// + +#include "typeinfo" + +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_ABI_VCRUNTIME) +#include <string.h> + +int std::type_info::__compare(const type_info &__rhs) const noexcept { + if (&__data == &__rhs.__data) + return 0; + return strcmp(&__data.__decorated_name[1], &__rhs.__data.__decorated_name[1]); +} + +const char *std::type_info::name() const noexcept { + // TODO(compnerd) cache demangled &__data.__decorated_name[1] + return &__data.__decorated_name[1]; +} + +size_t std::type_info::hash_code() const noexcept { +#if defined(_WIN64) + constexpr size_t fnv_offset_basis = 14695981039346656037ull; + constexpr size_t fnv_prime = 10995116282110ull; +#else + constexpr size_t fnv_offset_basis = 2166136261ull; + constexpr size_t fnv_prime = 16777619ull; +#endif + + size_t value = fnv_offset_basis; + for (const char* c = &__data.__decorated_name[1]; *c; ++c) { + value ^= static_cast<size_t>(static_cast<unsigned char>(*c)); + value *= fnv_prime; + } + +#if defined(_WIN64) + value ^= value >> 32; +#endif + + return value; +} +#endif // _LIBCPP_ABI_MICROSOFT + +// FIXME: Remove the _LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY configuration. +#if (!defined(LIBCXX_BUILDING_LIBCXXABI) && \ !defined(LIBCXX_BUILDING_LIBCXXRT) && \ - !defined(__GLIBCXX__) && \ + !defined(__GLIBCXX__) && \ !defined(_LIBCPP_ABI_VCRUNTIME)) || \ - defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) -std::type_info::~type_info() -{ -} -#endif + defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) +std::type_info::~type_info() +{ +} +#endif diff --git a/contrib/libs/cxxsupp/libcxx/src/utility.cpp b/contrib/libs/cxxsupp/libcxx/src/utility.cpp index a297ae0142..6a690dc287 100644 --- a/contrib/libs/cxxsupp/libcxx/src/utility.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/utility.cpp @@ -1,15 +1,15 @@ -//===------------------------ utility.cpp ---------------------------------===// -// +//===------------------------ utility.cpp ---------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "utility" - -_LIBCPP_BEGIN_NAMESPACE_STD - -const piecewise_construct_t piecewise_construct{}; - -_LIBCPP_END_NAMESPACE_STD +// +//===----------------------------------------------------------------------===// + +#include "utility" + +_LIBCPP_BEGIN_NAMESPACE_STD + +const piecewise_construct_t piecewise_construct{}; + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/valarray.cpp b/contrib/libs/cxxsupp/libcxx/src/valarray.cpp index 8b6124bffb..64d26583c7 100644 --- a/contrib/libs/cxxsupp/libcxx/src/valarray.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/valarray.cpp @@ -1,57 +1,57 @@ -//===------------------------ valarray.cpp --------------------------------===// -// +//===------------------------ valarray.cpp --------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "valarray" - -_LIBCPP_BEGIN_NAMESPACE_STD - -// These two symbols are part of the v1 ABI but not part of the >=v2 ABI. -#if _LIBCPP_ABI_VERSION == 1 -template _LIBCPP_FUNC_VIS valarray<size_t>::valarray(size_t); -template _LIBCPP_FUNC_VIS valarray<size_t>::~valarray(); -#endif - -template void valarray<size_t>::resize(size_t, size_t); - -void -gslice::__init(size_t __start) -{ - valarray<size_t> __indices(__size_.size()); - size_t __k = __size_.size() != 0; - for (size_t __i = 0; __i < __size_.size(); ++__i) - __k *= __size_[__i]; - __1d_.resize(__k); - if (__1d_.size()) - { - __k = 0; - __1d_[__k] = __start; - while (true) - { - size_t __i = __indices.size() - 1; - while (true) - { - if (++__indices[__i] < __size_[__i]) - { - ++__k; - __1d_[__k] = __1d_[__k-1] + __stride_[__i]; - for (size_t __j = __i + 1; __j != __indices.size(); ++__j) - __1d_[__k] -= __stride_[__j] * (__size_[__j] - 1); - break; - } - else - { - if (__i == 0) - return; - __indices[__i--] = 0; - } - } - } - } -} - -_LIBCPP_END_NAMESPACE_STD +// +//===----------------------------------------------------------------------===// + +#include "valarray" + +_LIBCPP_BEGIN_NAMESPACE_STD + +// These two symbols are part of the v1 ABI but not part of the >=v2 ABI. +#if _LIBCPP_ABI_VERSION == 1 +template _LIBCPP_FUNC_VIS valarray<size_t>::valarray(size_t); +template _LIBCPP_FUNC_VIS valarray<size_t>::~valarray(); +#endif + +template void valarray<size_t>::resize(size_t, size_t); + +void +gslice::__init(size_t __start) +{ + valarray<size_t> __indices(__size_.size()); + size_t __k = __size_.size() != 0; + for (size_t __i = 0; __i < __size_.size(); ++__i) + __k *= __size_[__i]; + __1d_.resize(__k); + if (__1d_.size()) + { + __k = 0; + __1d_[__k] = __start; + while (true) + { + size_t __i = __indices.size() - 1; + while (true) + { + if (++__indices[__i] < __size_[__i]) + { + ++__k; + __1d_[__k] = __1d_[__k-1] + __stride_[__i]; + for (size_t __j = __i + 1; __j != __indices.size(); ++__j) + __1d_[__k] -= __stride_[__j] * (__size_[__j] - 1); + break; + } + else + { + if (__i == 0) + return; + __indices[__i--] = 0; + } + } + } + } +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libs/cxxsupp/libcxx/src/variant.cpp b/contrib/libs/cxxsupp/libcxx/src/variant.cpp index b48c03fbd5..1fe70a1809 100644 --- a/contrib/libs/cxxsupp/libcxx/src/variant.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/variant.cpp @@ -1,17 +1,17 @@ -//===------------------------ variant.cpp ---------------------------------===// -// +//===------------------------ variant.cpp ---------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "variant" - -namespace std { - -const char* bad_variant_access::what() const noexcept { - return "bad_variant_access"; -} - -} // namespace std +// +//===----------------------------------------------------------------------===// + +#include "variant" + +namespace std { + +const char* bad_variant_access::what() const noexcept { + return "bad_variant_access"; +} + +} // namespace std diff --git a/contrib/libs/cxxsupp/libcxx/src/vector.cpp b/contrib/libs/cxxsupp/libcxx/src/vector.cpp index 75a4f3a4ab..0570ede733 100644 --- a/contrib/libs/cxxsupp/libcxx/src/vector.cpp +++ b/contrib/libs/cxxsupp/libcxx/src/vector.cpp @@ -1,21 +1,21 @@ -//===------------------------- vector.cpp ---------------------------------===// -// +//===------------------------- vector.cpp ---------------------------------===// +// // 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 -// -//===----------------------------------------------------------------------===// - -#include "vector" - -_LIBCPP_BEGIN_NAMESPACE_STD - -void __vector_base_common<true>::__throw_length_error() const { - _VSTD::__throw_length_error("vector"); -} - -void __vector_base_common<true>::__throw_out_of_range() const { - _VSTD::__throw_out_of_range("vector"); -} - -_LIBCPP_END_NAMESPACE_STD +// +//===----------------------------------------------------------------------===// + +#include "vector" + +_LIBCPP_BEGIN_NAMESPACE_STD + +void __vector_base_common<true>::__throw_length_error() const { + _VSTD::__throw_length_error("vector"); +} + +void __vector_base_common<true>::__throw_out_of_range() const { + _VSTD::__throw_out_of_range("vector"); +} + +_LIBCPP_END_NAMESPACE_STD |