mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-04 19:52:28 +00:00
Upgrade to 2022-era LLVM LIBCXX
This commit is contained in:
parent
2f4ca71f26
commit
8e68384e15
2078 changed files with 165657 additions and 65010 deletions
47
third_party/libcxx/src/algorithm.cpp
vendored
Normal file
47
third_party/libcxx/src/algorithm.cpp
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <bit>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class Comp, class RandomAccessIterator>
|
||||
void __sort(RandomAccessIterator first, RandomAccessIterator last, Comp comp) {
|
||||
auto depth_limit = 2 * std::__bit_log2(static_cast<size_t>(last - first));
|
||||
|
||||
// Only use bitset partitioning for arithmetic types. We should also check
|
||||
// that the default comparator is in use so that we are sure that there are no
|
||||
// branches in the comparator.
|
||||
std::__introsort<_ClassicAlgPolicy,
|
||||
Comp&,
|
||||
RandomAccessIterator,
|
||||
__use_branchless_sort<Comp, RandomAccessIterator>::value>(first, last, comp, depth_limit);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
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>&);
|
||||
// clang-format on
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
34
third_party/libcxx/src/any.cpp
vendored
Normal file
34
third_party/libcxx/src/any.cpp
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
220
third_party/libcxx/src/atomic.cpp
vendored
Normal file
220
third_party/libcxx/src/atomic.cpp
vendored
Normal file
|
@ -0,0 +1,220 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <atomic>
|
||||
#include <climits>
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
|
||||
#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
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/umtx.h>
|
||||
|
||||
#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);
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
#elif defined(__FreeBSD__) && __SIZEOF_LONG__ == 8
|
||||
/*
|
||||
* Since __cxx_contention_t is int64_t even on 32bit FreeBSD
|
||||
* platforms, we have to use umtx ops that work on the long type, and
|
||||
* limit its use to architectures where long and int64_t are synonyms.
|
||||
*/
|
||||
|
||||
static void __libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr,
|
||||
__cxx_contention_t __val)
|
||||
{
|
||||
_umtx_op(const_cast<__cxx_atomic_contention_t*>(__ptr),
|
||||
UMTX_OP_WAIT, __val, NULL, NULL);
|
||||
}
|
||||
|
||||
static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr,
|
||||
bool __notify_one)
|
||||
{
|
||||
_umtx_op(const_cast<__cxx_atomic_contention_t*>(__ptr),
|
||||
UMTX_OP_WAKE, __notify_one ? 1 : INT_MAX, NULL, NULL);
|
||||
}
|
||||
|
||||
#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
|
97
third_party/libcxx/src/barrier.cpp
vendored
Normal file
97
third_party/libcxx/src/barrier.cpp
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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)
|
||||
|
||||
class __barrier_algorithm_base {
|
||||
public:
|
||||
struct alignas(64) /* naturally-align the heap state */ __state_t
|
||||
{
|
||||
struct {
|
||||
__atomic_base<__barrier_phase_t> __phase{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_END_NAMESPACE_STD
|
||||
|
||||
#endif //_LIBCPP_HAS_NO_THREADS
|
29
third_party/libcxx/src/bind.cpp
vendored
Normal file
29
third_party/libcxx/src/bind.cpp
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
86
third_party/libcxx/src/charconv.cpp
vendored
Normal file
86
third_party/libcxx/src/charconv.cpp
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <charconv>
|
||||
#include <string.h>
|
||||
|
||||
#include "third_party/libcxx/src/include/to_chars_floating_point.h"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifndef _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
|
||||
|
||||
namespace __itoa
|
||||
{
|
||||
|
||||
_LIBCPP_FUNC_VIS char*
|
||||
__u32toa(uint32_t value, char* buffer) noexcept
|
||||
{
|
||||
return __base_10_u32(buffer, value);
|
||||
}
|
||||
|
||||
_LIBCPP_FUNC_VIS char*
|
||||
__u64toa(uint64_t value, char* buffer) noexcept
|
||||
{
|
||||
return __base_10_u64(buffer, value);
|
||||
}
|
||||
|
||||
} // namespace __itoa
|
||||
|
||||
#endif // _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
|
||||
|
||||
// The original version of floating-point to_chars was written by Microsoft and
|
||||
// contributed with the following license.
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// This implementation is dedicated to the memory of Mary and Thavatchai.
|
||||
|
||||
to_chars_result to_chars(char* __first, char* __last, float __value) {
|
||||
return _Floating_to_chars<_Floating_to_chars_overload::_Plain>(__first, __last, __value, chars_format{}, 0);
|
||||
}
|
||||
|
||||
to_chars_result to_chars(char* __first, char* __last, double __value) {
|
||||
return _Floating_to_chars<_Floating_to_chars_overload::_Plain>(__first, __last, __value, chars_format{}, 0);
|
||||
}
|
||||
|
||||
to_chars_result to_chars(char* __first, char* __last, long double __value) {
|
||||
return _Floating_to_chars<_Floating_to_chars_overload::_Plain>(__first, __last, static_cast<double>(__value),
|
||||
chars_format{}, 0);
|
||||
}
|
||||
|
||||
to_chars_result to_chars(char* __first, char* __last, float __value, chars_format __fmt) {
|
||||
return _Floating_to_chars<_Floating_to_chars_overload::_Format_only>(__first, __last, __value, __fmt, 0);
|
||||
}
|
||||
|
||||
to_chars_result to_chars(char* __first, char* __last, double __value, chars_format __fmt) {
|
||||
return _Floating_to_chars<_Floating_to_chars_overload::_Format_only>(__first, __last, __value, __fmt, 0);
|
||||
}
|
||||
|
||||
to_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt) {
|
||||
return _Floating_to_chars<_Floating_to_chars_overload::_Format_only>(__first, __last, static_cast<double>(__value),
|
||||
__fmt, 0);
|
||||
}
|
||||
|
||||
to_chars_result to_chars(char* __first, char* __last, float __value, chars_format __fmt, int __precision) {
|
||||
return _Floating_to_chars<_Floating_to_chars_overload::_Format_precision>(__first, __last, __value, __fmt,
|
||||
__precision);
|
||||
}
|
||||
|
||||
to_chars_result to_chars(char* __first, char* __last, double __value, chars_format __fmt, int __precision) {
|
||||
return _Floating_to_chars<_Floating_to_chars_overload::_Format_precision>(__first, __last, __value, __fmt,
|
||||
__precision);
|
||||
}
|
||||
|
||||
to_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision) {
|
||||
return _Floating_to_chars<_Floating_to_chars_overload::_Format_precision>(
|
||||
__first, __last, static_cast<double>(__value), __fmt, __precision);
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
254
third_party/libcxx/src/chrono.cpp
vendored
Normal file
254
third_party/libcxx/src/chrono.cpp
vendored
Normal file
|
@ -0,0 +1,254 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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 <__system_error/system_error.h>
|
||||
#include <cerrno> // errno
|
||||
#include <chrono>
|
||||
|
||||
#if defined(__MVS__)
|
||||
#include <__support/ibm/gettod_zos.h> // gettimeofdayMonotonic
|
||||
#endif
|
||||
|
||||
#include <time.h> // clock_gettime and CLOCK_{MONOTONIC,REALTIME,MONOTONIC_RAW}
|
||||
#include "third_party/libcxx/src/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 defined(__Fuchsia__)
|
||||
# include <zircon/syscalls.h>
|
||||
#endif
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
// Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority
|
||||
// attribute with a value that's reserved for the implementation (we're the implementation).
|
||||
#include "chrono_system_time_init.h"
|
||||
} // 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__)
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
#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(__Fuchsia__)
|
||||
|
||||
static steady_clock::time_point __libcpp_steady_clock_now() noexcept {
|
||||
// Implicitly link against the vDSO system call ABI without
|
||||
// requiring the final link to specify -lzircon explicitly when
|
||||
// statically linking libc++.
|
||||
# pragma comment(lib, "zircon")
|
||||
|
||||
return steady_clock::time_point(nanoseconds(_zx_clock_get_monotonic()));
|
||||
}
|
||||
|
||||
# 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
|
2
third_party/libcxx/src/chrono_system_time_init.h
vendored
Normal file
2
third_party/libcxx/src/chrono_system_time_init.h
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
#pragma GCC system_header
|
||||
GetSystemTimeInit GetSystemTimeAsFileTimeFunc _LIBCPP_INIT_PRIORITY_MAX;
|
96
third_party/libcxx/src/condition_variable.cpp
vendored
Normal file
96
third_party/libcxx/src/condition_variable.cpp
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>
|
||||
|
||||
#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
|
||||
# pragma comment(lib, "pthread")
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_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
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
46
third_party/libcxx/src/condition_variable_destructor.cpp
vendored
Normal file
46
third_party/libcxx/src/condition_variable_destructor.cpp
vendored
Normal file
|
@ -0,0 +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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// 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
|
559
third_party/libcxx/src/debug.cpp
vendored
Normal file
559
third_party/libcxx/src/debug.cpp
vendored
Normal file
|
@ -0,0 +1,559 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <__assert>
|
||||
#include <__config>
|
||||
#include <__debug>
|
||||
#include <__hash_table>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#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
|
||||
|
||||
_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
|
35
third_party/libcxx/src/exception.cpp
vendored
Normal file
35
third_party/libcxx/src/exception.cpp
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>
|
||||
|
||||
#if defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI)
|
||||
#include <cxxabi.h>
|
||||
using namespace __cxxabiv1;
|
||||
#define HAVE_DEPENDENT_EH_ABI 1
|
||||
#endif
|
||||
|
||||
#if defined(_LIBCPP_ABI_MICROSOFT)
|
||||
#include "third_party/libcxx/src/support/runtime/exception_msvc.ipp"
|
||||
#include "third_party/libcxx/src/support/runtime/exception_pointer_msvc.ipp"
|
||||
#elif defined(_LIBCPPABI_VERSION)
|
||||
#include "third_party/libcxx/src/support/runtime/exception_libcxxabi.ipp"
|
||||
#include "third_party/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp"
|
||||
#elif defined(LIBCXXRT)
|
||||
#include "third_party/libcxx/src/support/runtime/exception_libcxxrt.ipp"
|
||||
#include "third_party/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp"
|
||||
#elif defined(__GLIBCXX__)
|
||||
#include "third_party/libcxx/src/support/runtime/exception_glibcxx.ipp"
|
||||
#include "third_party/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp"
|
||||
#else
|
||||
#include "third_party/libcxx/src/include/atomic_support.h"
|
||||
#include "third_party/libcxx/src/support/runtime/exception_fallback.ipp"
|
||||
#include "third_party/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp"
|
||||
#endif
|
149
third_party/libcxx/src/experimental/memory_resource.cpp
vendored
Normal file
149
third_party/libcxx/src/experimental/memory_resource.cpp
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>
|
||||
|
||||
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
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_SINCE_CXX14 ResourceInitHelper() : resources() {}
|
||||
~ResourceInitHelper() {}
|
||||
};
|
||||
|
||||
// Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority
|
||||
// attribute with a value that's reserved for the implementation (we're the implementation).
|
||||
#include "memory_resource_init_helper.h"
|
||||
|
||||
} // 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
|
||||
static constinit atomic<memory_resource*> __res{&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)
|
||||
static constinit 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
|
||||
static constinit 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
|
2
third_party/libcxx/src/experimental/memory_resource_init_helper.h
vendored
Normal file
2
third_party/libcxx/src/experimental/memory_resource_init_helper.h
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
#pragma GCC system_header
|
||||
static constinit ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX;
|
332
third_party/libcxx/src/filesystem/directory_iterator.cpp
vendored
Normal file
332
third_party/libcxx/src/filesystem/directory_iterator.cpp
vendored
Normal file
|
@ -0,0 +1,332 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <__assert>
|
||||
#include <__config>
|
||||
#include <errno.h>
|
||||
#include <filesystem>
|
||||
#include <stack>
|
||||
|
||||
#include "filesystem_common.h"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
|
||||
|
||||
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_(std::move(__ds.__root_)),
|
||||
__entry_(std::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_);
|
||||
//cdata.__size_ = get_file_size(__data_);
|
||||
//cdata.__write_time_ = get_write_time(__data_);
|
||||
__entry_.__assign_iter_entry(
|
||||
__root_ / __data_.cFileName,
|
||||
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_(std::move(other.__root_)),
|
||||
__entry_(std::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_eacces =
|
||||
bool(opts & directory_options::skip_permission_denied);
|
||||
if (allow_eacces && 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 = std::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(std::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 = std::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(std::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 = std::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
|
611
third_party/libcxx/src/filesystem/filesystem_common.h
vendored
Normal file
611
third_party/libcxx/src/filesystem/filesystem_common.h
vendored
Normal file
|
@ -0,0 +1,611 @@
|
|||
//===----------------------------------------------------------------------===////
|
||||
//
|
||||
// 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 <__assert>
|
||||
#include <__config>
|
||||
#include <array>
|
||||
#include <cerrno>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#include <cstdarg>
|
||||
#include <ctime>
|
||||
#include <filesystem>
|
||||
#include <ratio>
|
||||
#include <utility>
|
||||
#include <system_error>
|
||||
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define NOMINMAX
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include <dirent.h> // for DIR & friends
|
||||
# include <fcntl.h> /* values for fchmodat */
|
||||
# include <sys/stat.h>
|
||||
# include <sys/statvfs.h>
|
||||
# include <sys/time.h> // for ::utimes as used in __last_write_time
|
||||
# include <unistd.h>
|
||||
#endif // defined(_LIBCPP_WIN32API)
|
||||
|
||||
// We can use the presence of UTIME_OMIT to detect platforms that provide utimensat.
|
||||
#if defined(UTIME_OMIT)
|
||||
# define _LIBCPP_USE_UTIMENSAT
|
||||
#endif
|
||||
|
||||
// TODO: Check whether these functions actually need internal linkage, or if they can be made normal header functions
|
||||
_LIBCPP_DIAGNOSTIC_PUSH
|
||||
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wunused-function")
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-function")
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-template")
|
||||
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
# define PATHSTR(x) (L##x)
|
||||
# define PATH_CSTR_FMT "\"%ls\""
|
||||
#else
|
||||
# define PATHSTR(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_ATTRIBUTE_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;
|
||||
result.__resize_default_init(size_with_null - 1);
|
||||
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_ATTRIBUTE_FORMAT(__printf__, 1, 2) string
|
||||
format_string(const char* msg, ...) {
|
||||
string ret;
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
ret = format_string_impl(msg, ap);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
} catch (...) {
|
||||
va_end(ap);
|
||||
throw;
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
error_code capture_errno() {
|
||||
_LIBCPP_ASSERT(errno != 0, "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_SINCE_CXX14 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_SINCE_CXX14 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_ATTRIBUTE_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_ATTRIBUTE_FORMAT(__printf__, 3, 4)
|
||||
T report(const error_code& ec, const char* msg, ...) const {
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
report_impl(ec, msg, ap);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
} catch (...) {
|
||||
va_end(ap);
|
||||
throw;
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
va_end(ap);
|
||||
return error_value<T>();
|
||||
}
|
||||
|
||||
T report(errc const& err) const {
|
||||
return report(make_error_code(err));
|
||||
}
|
||||
|
||||
_LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4)
|
||||
T report(errc const& err, const char* msg, ...) const {
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
report_impl(make_error_code(err), msg, ap);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
} catch (...) {
|
||||
va_end(ap);
|
||||
throw;
|
||||
}
|
||||
#endif // _LIBCPP_HAS_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_SINCE_CXX14 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_SINCE_CXX14 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_SINCE_CXX14 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_SINCE_CXX14 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_SINCE_CXX14 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_SINCE_CXX14 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_SINCE_CXX14 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_SINCE_CXX14 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
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
#endif // defined(DT_BLK)
|
||||
|
||||
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 // _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 // !_LIBCPP_WIN32API
|
||||
|
||||
} // namespace
|
||||
} // end namespace detail
|
||||
|
||||
_LIBCPP_END_NAMESPACE_FILESYSTEM
|
||||
|
||||
_LIBCPP_DIAGNOSTIC_POP
|
||||
|
||||
#endif // FILESYSTEM_COMMON_H
|
54
third_party/libcxx/src/filesystem/int128_builtins.cpp
vendored
Normal file
54
third_party/libcxx/src/filesystem/int128_builtins.cpp
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*===-- 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
|
2103
third_party/libcxx/src/filesystem/operations.cpp
vendored
Normal file
2103
third_party/libcxx/src/filesystem/operations.cpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
522
third_party/libcxx/src/filesystem/posix_compat.h
vendored
Normal file
522
third_party/libcxx/src/filesystem/posix_compat.h
vendored
Normal file
|
@ -0,0 +1,522 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <__assert>
|
||||
#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
|
27
third_party/libcxx/src/functional.cpp
vendored
Normal file
27
third_party/libcxx/src/functional.cpp
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE
|
||||
const char*
|
||||
bad_function_call::what() const noexcept
|
||||
{
|
||||
return "std::bad_function_call";
|
||||
}
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
269
third_party/libcxx/src/future.cpp
vendored
Normal file
269
third_party/libcxx/src/future.cpp
vendored
Normal file
|
@ -0,0 +1,269 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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";
|
||||
}
|
||||
|
||||
_LIBCPP_DIAGNOSTIC_PUSH
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wswitch")
|
||||
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wswitch")
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
_LIBCPP_DIAGNOSTIC_POP
|
||||
|
||||
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())
|
||||
__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())
|
||||
__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())
|
||||
__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()
|
||||
{
|
||||
__throw_future_error(future_errc::no_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_HAS_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_HAS_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)
|
||||
__throw_future_error(future_errc::no_state);
|
||||
__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)
|
||||
__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)
|
||||
__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
|
559
third_party/libcxx/src/hash.cpp
vendored
Normal file
559
third_party/libcxx/src/hash.cpp
vendored
Normal file
|
@ -0,0 +1,559 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>
|
||||
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wtautological-constant-out-of-range-compare")
|
||||
|
||||
_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
|
34
third_party/libcxx/src/include/apple_availability.h
vendored
Normal file
34
third_party/libcxx/src/include/apple_availability.h
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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__ >= 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
|
176
third_party/libcxx/src/include/atomic_support.h
vendored
Normal file
176
third_party/libcxx/src/include/atomic_support.h
vendored
Normal file
|
@ -0,0 +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
|
51
third_party/libcxx/src/include/config_elast.h
vendored
Normal file
51
third_party/libcxx/src/include/config_elast.h
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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(__EMSCRIPTEN__)
|
||||
// No _LIBCPP_ELAST needed on Emscripten
|
||||
#elif defined(__COSMOPOLITAN__)
|
||||
#define _LIBCPP_ELAST 65535
|
||||
#elif defined(__linux__) || defined(_LIBCPP_HAS_MUSL_LIBC)
|
||||
#define _LIBCPP_ELAST 4095
|
||||
#elif defined(__APPLE__)
|
||||
// No _LIBCPP_ELAST needed on Apple
|
||||
#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
|
140
third_party/libcxx/src/include/refstring.h
vendored
Normal file
140
third_party/libcxx/src/include/refstring.h
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>
|
||||
#include "atomic_support.h"
|
||||
|
||||
// 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;
|
||||
count_t count;
|
||||
};
|
||||
|
||||
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())
|
||||
__libcpp_atomic_add(&rep_from_data(__imp_)->count, 1);
|
||||
}
|
||||
|
||||
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())
|
||||
__libcpp_atomic_add(&rep_from_data(__imp_)->count, 1);
|
||||
if (adjust_old_count)
|
||||
{
|
||||
if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0)
|
||||
{
|
||||
::operator delete(old_rep);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
__libcpp_refstring::~__libcpp_refstring() {
|
||||
if (__uses_refcount()) {
|
||||
_Rep_base* rep = rep_from_data(__imp_);
|
||||
if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) {
|
||||
::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
|
109
third_party/libcxx/src/include/ryu/common.h
vendored
Normal file
109
third_party/libcxx/src/include/ryu/common.h
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Copyright 2018 Ulf Adams
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef _LIBCPP_SRC_INCLUDE_RYU_COMMON_H
|
||||
#define _LIBCPP_SRC_INCLUDE_RYU_COMMON_H
|
||||
|
||||
// Avoid formatting to keep the changes with the original code minimal.
|
||||
// clang-format off
|
||||
|
||||
#include <__assert>
|
||||
#include <__config>
|
||||
#include <cstring>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __decimalLength9(const uint32_t __v) {
|
||||
// Function precondition: __v is not a 10-digit number.
|
||||
// (f2s: 9 digits are sufficient for round-tripping.)
|
||||
// (d2fixed: We print 9-digit blocks.)
|
||||
_LIBCPP_ASSERT(__v < 1000000000, "");
|
||||
if (__v >= 100000000) { return 9; }
|
||||
if (__v >= 10000000) { return 8; }
|
||||
if (__v >= 1000000) { return 7; }
|
||||
if (__v >= 100000) { return 6; }
|
||||
if (__v >= 10000) { return 5; }
|
||||
if (__v >= 1000) { return 4; }
|
||||
if (__v >= 100) { return 3; }
|
||||
if (__v >= 10) { return 2; }
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Returns __e == 0 ? 1 : ceil(log_2(5^__e)).
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline int32_t __pow5bits(const int32_t __e) {
|
||||
// This approximation works up to the point that the multiplication overflows at __e = 3529.
|
||||
// If the multiplication were done in 64 bits, it would fail at 5^4004 which is just greater
|
||||
// than 2^9297.
|
||||
_LIBCPP_ASSERT(__e >= 0, "");
|
||||
_LIBCPP_ASSERT(__e <= 3528, "");
|
||||
return static_cast<int32_t>(((static_cast<uint32_t>(__e) * 1217359) >> 19) + 1);
|
||||
}
|
||||
|
||||
// Returns floor(log_10(2^__e)).
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __log10Pow2(const int32_t __e) {
|
||||
// The first value this approximation fails for is 2^1651 which is just greater than 10^297.
|
||||
_LIBCPP_ASSERT(__e >= 0, "");
|
||||
_LIBCPP_ASSERT(__e <= 1650, "");
|
||||
return (static_cast<uint32_t>(__e) * 78913) >> 18;
|
||||
}
|
||||
|
||||
// Returns floor(log_10(5^__e)).
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __log10Pow5(const int32_t __e) {
|
||||
// The first value this approximation fails for is 5^2621 which is just greater than 10^1832.
|
||||
_LIBCPP_ASSERT(__e >= 0, "");
|
||||
_LIBCPP_ASSERT(__e <= 2620, "");
|
||||
return (static_cast<uint32_t>(__e) * 732923) >> 20;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __float_to_bits(const float __f) {
|
||||
uint32_t __bits = 0;
|
||||
std::memcpy(&__bits, &__f, sizeof(float));
|
||||
return __bits;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __double_to_bits(const double __d) {
|
||||
uint64_t __bits = 0;
|
||||
std::memcpy(&__bits, &__d, sizeof(double));
|
||||
return __bits;
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // _LIBCPP_SRC_INCLUDE_RYU_COMMON_H
|
60
third_party/libcxx/src/include/ryu/d2fixed.h
vendored
Normal file
60
third_party/libcxx/src/include/ryu/d2fixed.h
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Copyright 2018 Ulf Adams
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef _LIBCPP_SRC_INCLUDE_RYU_D2FIXED_H
|
||||
#define _LIBCPP_SRC_INCLUDE_RYU_D2FIXED_H
|
||||
|
||||
// Avoid formatting to keep the changes with the original code minimal.
|
||||
// clang-format off
|
||||
|
||||
#include <__config>
|
||||
#include <cstdint>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
void __append_n_digits(const uint32_t __olength, uint32_t __digits, char* const __result);
|
||||
void __append_nine_digits(uint32_t __digits, char* const __result);
|
||||
|
||||
[[nodiscard]] to_chars_result __d2fixed_buffered_n(char* _First, char* const _Last, const double __d, const uint32_t __precision);
|
||||
[[nodiscard]] to_chars_result __d2exp_buffered_n(char* _First, char* const _Last, const double __d, uint32_t __precision);
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // _LIBCPP_SRC_INCLUDE_RYU_D2FIXED_H
|
4451
third_party/libcxx/src/include/ryu/d2fixed_full_table.h
vendored
Normal file
4451
third_party/libcxx/src/include/ryu/d2fixed_full_table.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
62
third_party/libcxx/src/include/ryu/d2s.h
vendored
Normal file
62
third_party/libcxx/src/include/ryu/d2s.h
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Copyright 2018 Ulf Adams
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef _LIBCPP_SRC_INCLUDE_RYU_DS2_H
|
||||
#define _LIBCPP_SRC_INCLUDE_RYU_DS2_H
|
||||
|
||||
// Avoid formatting to keep the changes with the original code minimal.
|
||||
// clang-format off
|
||||
|
||||
#include <__config>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
inline constexpr int __DOUBLE_MANTISSA_BITS = 52;
|
||||
inline constexpr int __DOUBLE_EXPONENT_BITS = 11;
|
||||
inline constexpr int __DOUBLE_BIAS = 1023;
|
||||
|
||||
inline constexpr int __DOUBLE_POW5_INV_BITCOUNT = 122;
|
||||
inline constexpr int __DOUBLE_POW5_BITCOUNT = 121;
|
||||
|
||||
[[nodiscard]] to_chars_result __d2s_buffered_n(char* const _First, char* const _Last, const double __f, const chars_format _Fmt);
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // _LIBCPP_SRC_INCLUDE_RYU_DS2_H
|
368
third_party/libcxx/src/include/ryu/d2s_full_table.h
vendored
Normal file
368
third_party/libcxx/src/include/ryu/d2s_full_table.h
vendored
Normal file
|
@ -0,0 +1,368 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Copyright 2018 Ulf Adams
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef _LIBCPP_SRC_INCLUDE_RYU_D2S_FULL_TABLE_H
|
||||
#define _LIBCPP_SRC_INCLUDE_RYU_D2S_FULL_TABLE_H
|
||||
|
||||
// Avoid formatting to keep the changes with the original code minimal.
|
||||
// clang-format off
|
||||
|
||||
#include <__config>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
inline constexpr uint64_t __DOUBLE_POW5_INV_SPLIT[292][2] = {
|
||||
{ 1u, 288230376151711744u }, { 3689348814741910324u, 230584300921369395u },
|
||||
{ 2951479051793528259u, 184467440737095516u }, { 17118578500402463900u, 147573952589676412u },
|
||||
{ 12632330341676300947u, 236118324143482260u }, { 10105864273341040758u, 188894659314785808u },
|
||||
{ 15463389048156653253u, 151115727451828646u }, { 17362724847566824558u, 241785163922925834u },
|
||||
{ 17579528692795369969u, 193428131138340667u }, { 6684925324752475329u, 154742504910672534u },
|
||||
{ 18074578149087781173u, 247588007857076054u }, { 18149011334012135262u, 198070406285660843u },
|
||||
{ 3451162622983977240u, 158456325028528675u }, { 5521860196774363583u, 253530120045645880u },
|
||||
{ 4417488157419490867u, 202824096036516704u }, { 7223339340677503017u, 162259276829213363u },
|
||||
{ 7867994130342094503u, 259614842926741381u }, { 2605046489531765280u, 207691874341393105u },
|
||||
{ 2084037191625412224u, 166153499473114484u }, { 10713157136084480204u, 265845599156983174u },
|
||||
{ 12259874523609494487u, 212676479325586539u }, { 13497248433629505913u, 170141183460469231u },
|
||||
{ 14216899864323388813u, 272225893536750770u }, { 11373519891458711051u, 217780714829400616u },
|
||||
{ 5409467098425058518u, 174224571863520493u }, { 4965798542738183305u, 278759314981632789u },
|
||||
{ 7661987648932456967u, 223007451985306231u }, { 2440241304404055250u, 178405961588244985u },
|
||||
{ 3904386087046488400u, 285449538541191976u }, { 17880904128604832013u, 228359630832953580u },
|
||||
{ 14304723302883865611u, 182687704666362864u }, { 15133127457049002812u, 146150163733090291u },
|
||||
{ 16834306301794583852u, 233840261972944466u }, { 9778096226693756759u, 187072209578355573u },
|
||||
{ 15201174610838826053u, 149657767662684458u }, { 2185786488890659746u, 239452428260295134u },
|
||||
{ 5437978005854438120u, 191561942608236107u }, { 15418428848909281466u, 153249554086588885u },
|
||||
{ 6222742084545298729u, 245199286538542217u }, { 16046240111861969953u, 196159429230833773u },
|
||||
{ 1768945645263844993u, 156927543384667019u }, { 10209010661905972635u, 251084069415467230u },
|
||||
{ 8167208529524778108u, 200867255532373784u }, { 10223115638361732810u, 160693804425899027u },
|
||||
{ 1599589762411131202u, 257110087081438444u }, { 4969020624670815285u, 205688069665150755u },
|
||||
{ 3975216499736652228u, 164550455732120604u }, { 13739044029062464211u, 263280729171392966u },
|
||||
{ 7301886408508061046u, 210624583337114373u }, { 13220206756290269483u, 168499666669691498u },
|
||||
{ 17462981995322520850u, 269599466671506397u }, { 6591687966774196033u, 215679573337205118u },
|
||||
{ 12652048002903177473u, 172543658669764094u }, { 9175230360419352987u, 276069853871622551u },
|
||||
{ 3650835473593572067u, 220855883097298041u }, { 17678063637842498946u, 176684706477838432u },
|
||||
{ 13527506561580357021u, 282695530364541492u }, { 3443307619780464970u, 226156424291633194u },
|
||||
{ 6443994910566282300u, 180925139433306555u }, { 5155195928453025840u, 144740111546645244u },
|
||||
{ 15627011115008661990u, 231584178474632390u }, { 12501608892006929592u, 185267342779705912u },
|
||||
{ 2622589484121723027u, 148213874223764730u }, { 4196143174594756843u, 237142198758023568u },
|
||||
{ 10735612169159626121u, 189713759006418854u }, { 12277838550069611220u, 151771007205135083u },
|
||||
{ 15955192865369467629u, 242833611528216133u }, { 1696107848069843133u, 194266889222572907u },
|
||||
{ 12424932722681605476u, 155413511378058325u }, { 1433148282581017146u, 248661618204893321u },
|
||||
{ 15903913885032455010u, 198929294563914656u }, { 9033782293284053685u, 159143435651131725u },
|
||||
{ 14454051669254485895u, 254629497041810760u }, { 11563241335403588716u, 203703597633448608u },
|
||||
{ 16629290697806691620u, 162962878106758886u }, { 781423413297334329u, 260740604970814219u },
|
||||
{ 4314487545379777786u, 208592483976651375u }, { 3451590036303822229u, 166873987181321100u },
|
||||
{ 5522544058086115566u, 266998379490113760u }, { 4418035246468892453u, 213598703592091008u },
|
||||
{ 10913125826658934609u, 170878962873672806u }, { 10082303693170474728u, 273406340597876490u },
|
||||
{ 8065842954536379782u, 218725072478301192u }, { 17520720807854834795u, 174980057982640953u },
|
||||
{ 5897060404116273733u, 279968092772225526u }, { 1028299508551108663u, 223974474217780421u },
|
||||
{ 15580034865808528224u, 179179579374224336u }, { 17549358155809824511u, 286687326998758938u },
|
||||
{ 2971440080422128639u, 229349861599007151u }, { 17134547323305344204u, 183479889279205720u },
|
||||
{ 13707637858644275364u, 146783911423364576u }, { 14553522944347019935u, 234854258277383322u },
|
||||
{ 4264120725993795302u, 187883406621906658u }, { 10789994210278856888u, 150306725297525326u },
|
||||
{ 9885293106962350374u, 240490760476040522u }, { 529536856086059653u, 192392608380832418u },
|
||||
{ 7802327114352668369u, 153914086704665934u }, { 1415676938738538420u, 246262538727465495u },
|
||||
{ 1132541550990830736u, 197010030981972396u }, { 15663428499760305882u, 157608024785577916u },
|
||||
{ 17682787970132668764u, 252172839656924666u }, { 10456881561364224688u, 201738271725539733u },
|
||||
{ 15744202878575200397u, 161390617380431786u }, { 17812026976236499989u, 258224987808690858u },
|
||||
{ 3181575136763469022u, 206579990246952687u }, { 13613306553636506187u, 165263992197562149u },
|
||||
{ 10713244041592678929u, 264422387516099439u }, { 12259944048016053467u, 211537910012879551u },
|
||||
{ 6118606423670932450u, 169230328010303641u }, { 2411072648389671274u, 270768524816485826u },
|
||||
{ 16686253377679378312u, 216614819853188660u }, { 13349002702143502650u, 173291855882550928u },
|
||||
{ 17669055508687693916u, 277266969412081485u }, { 14135244406950155133u, 221813575529665188u },
|
||||
{ 240149081334393137u, 177450860423732151u }, { 11452284974360759988u, 283921376677971441u },
|
||||
{ 5472479164746697667u, 227137101342377153u }, { 11756680961281178780u, 181709681073901722u },
|
||||
{ 2026647139541122378u, 145367744859121378u }, { 18000030682233437097u, 232588391774594204u },
|
||||
{ 18089373360528660001u, 186070713419675363u }, { 3403452244197197031u, 148856570735740291u },
|
||||
{ 16513570034941246220u, 238170513177184465u }, { 13210856027952996976u, 190536410541747572u },
|
||||
{ 3189987192878576934u, 152429128433398058u }, { 1414630693863812771u, 243886605493436893u },
|
||||
{ 8510402184574870864u, 195109284394749514u }, { 10497670562401807014u, 156087427515799611u },
|
||||
{ 9417575270359070576u, 249739884025279378u }, { 14912757845771077107u, 199791907220223502u },
|
||||
{ 4551508647133041040u, 159833525776178802u }, { 10971762650154775986u, 255733641241886083u },
|
||||
{ 16156107749607641435u, 204586912993508866u }, { 9235537384944202825u, 163669530394807093u },
|
||||
{ 11087511001168814197u, 261871248631691349u }, { 12559357615676961681u, 209496998905353079u },
|
||||
{ 13736834907283479668u, 167597599124282463u }, { 18289587036911657145u, 268156158598851941u },
|
||||
{ 10942320814787415393u, 214524926879081553u }, { 16132554281313752961u, 171619941503265242u },
|
||||
{ 11054691591134363444u, 274591906405224388u }, { 16222450902391311402u, 219673525124179510u },
|
||||
{ 12977960721913049122u, 175738820099343608u }, { 17075388340318968271u, 281182112158949773u },
|
||||
{ 2592264228029443648u, 224945689727159819u }, { 5763160197165465241u, 179956551781727855u },
|
||||
{ 9221056315464744386u, 287930482850764568u }, { 14755542681855616155u, 230344386280611654u },
|
||||
{ 15493782960226403247u, 184275509024489323u }, { 1326979923955391628u, 147420407219591459u },
|
||||
{ 9501865507812447252u, 235872651551346334u }, { 11290841220991868125u, 188698121241077067u },
|
||||
{ 1653975347309673853u, 150958496992861654u }, { 10025058185179298811u, 241533595188578646u },
|
||||
{ 4330697733401528726u, 193226876150862917u }, { 14532604630946953951u, 154581500920690333u },
|
||||
{ 1116074521063664381u, 247330401473104534u }, { 4582208431592841828u, 197864321178483627u },
|
||||
{ 14733813189500004432u, 158291456942786901u }, { 16195403473716186445u, 253266331108459042u },
|
||||
{ 5577625149489128510u, 202613064886767234u }, { 8151448934333213131u, 162090451909413787u },
|
||||
{ 16731667109675051333u, 259344723055062059u }, { 17074682502481951390u, 207475778444049647u },
|
||||
{ 6281048372501740465u, 165980622755239718u }, { 6360328581260874421u, 265568996408383549u },
|
||||
{ 8777611679750609860u, 212455197126706839u }, { 10711438158542398211u, 169964157701365471u },
|
||||
{ 9759603424184016492u, 271942652322184754u }, { 11497031554089123517u, 217554121857747803u },
|
||||
{ 16576322872755119460u, 174043297486198242u }, { 11764721337440549842u, 278469275977917188u },
|
||||
{ 16790474699436260520u, 222775420782333750u }, { 13432379759549008416u, 178220336625867000u },
|
||||
{ 3045063541568861850u, 285152538601387201u }, { 17193446092222730773u, 228122030881109760u },
|
||||
{ 13754756873778184618u, 182497624704887808u }, { 18382503128506368341u, 145998099763910246u },
|
||||
{ 3586563302416817083u, 233596959622256395u }, { 2869250641933453667u, 186877567697805116u },
|
||||
{ 17052795772514404226u, 149502054158244092u }, { 12527077977055405469u, 239203286653190548u },
|
||||
{ 17400360011128145022u, 191362629322552438u }, { 2852241564676785048u, 153090103458041951u },
|
||||
{ 15631632947708587046u, 244944165532867121u }, { 8815957543424959314u, 195955332426293697u },
|
||||
{ 18120812478965698421u, 156764265941034957u }, { 14235904707377476180u, 250822825505655932u },
|
||||
{ 4010026136418160298u, 200658260404524746u }, { 17965416168102169531u, 160526608323619796u },
|
||||
{ 2919224165770098987u, 256842573317791675u }, { 2335379332616079190u, 205474058654233340u },
|
||||
{ 1868303466092863352u, 164379246923386672u }, { 6678634360490491686u, 263006795077418675u },
|
||||
{ 5342907488392393349u, 210405436061934940u }, { 4274325990713914679u, 168324348849547952u },
|
||||
{ 10528270399884173809u, 269318958159276723u }, { 15801313949391159694u, 215455166527421378u },
|
||||
{ 1573004715287196786u, 172364133221937103u }, { 17274202803427156150u, 275782613155099364u },
|
||||
{ 17508711057483635243u, 220626090524079491u }, { 10317620031244997871u, 176500872419263593u },
|
||||
{ 12818843235250086271u, 282401395870821749u }, { 13944423402941979340u, 225921116696657399u },
|
||||
{ 14844887537095493795u, 180736893357325919u }, { 15565258844418305359u, 144589514685860735u },
|
||||
{ 6457670077359736959u, 231343223497377177u }, { 16234182506113520537u, 185074578797901741u },
|
||||
{ 9297997190148906106u, 148059663038321393u }, { 11187446689496339446u, 236895460861314229u },
|
||||
{ 12639306166338981880u, 189516368689051383u }, { 17490142562555006151u, 151613094951241106u },
|
||||
{ 2158786396894637579u, 242580951921985771u }, { 16484424376483351356u, 194064761537588616u },
|
||||
{ 9498190686444770762u, 155251809230070893u }, { 11507756283569722895u, 248402894768113429u },
|
||||
{ 12895553841597688639u, 198722315814490743u }, { 17695140702761971558u, 158977852651592594u },
|
||||
{ 17244178680193423523u, 254364564242548151u }, { 10105994129412828495u, 203491651394038521u },
|
||||
{ 4395446488788352473u, 162793321115230817u }, { 10722063196803274280u, 260469313784369307u },
|
||||
{ 1198952927958798777u, 208375451027495446u }, { 15716557601334680315u, 166700360821996356u },
|
||||
{ 17767794532651667857u, 266720577315194170u }, { 14214235626121334286u, 213376461852155336u },
|
||||
{ 7682039686155157106u, 170701169481724269u }, { 1223217053622520399u, 273121871170758831u },
|
||||
{ 15735968901865657612u, 218497496936607064u }, { 16278123936234436413u, 174797997549285651u },
|
||||
{ 219556594781725998u, 279676796078857043u }, { 7554342905309201445u, 223741436863085634u },
|
||||
{ 9732823138989271479u, 178993149490468507u }, { 815121763415193074u, 286389039184749612u },
|
||||
{ 11720143854957885429u, 229111231347799689u }, { 13065463898708218666u, 183288985078239751u },
|
||||
{ 6763022304224664610u, 146631188062591801u }, { 3442138057275642729u, 234609900900146882u },
|
||||
{ 13821756890046245153u, 187687920720117505u }, { 11057405512036996122u, 150150336576094004u },
|
||||
{ 6623802375033462826u, 240240538521750407u }, { 16367088344252501231u, 192192430817400325u },
|
||||
{ 13093670675402000985u, 153753944653920260u }, { 2503129006933649959u, 246006311446272417u },
|
||||
{ 13070549649772650937u, 196805049157017933u }, { 17835137349301941396u, 157444039325614346u },
|
||||
{ 2710778055689733971u, 251910462920982955u }, { 2168622444551787177u, 201528370336786364u },
|
||||
{ 5424246770383340065u, 161222696269429091u }, { 1300097203129523457u, 257956314031086546u },
|
||||
{ 15797473021471260058u, 206365051224869236u }, { 8948629602435097724u, 165092040979895389u },
|
||||
{ 3249760919670425388u, 264147265567832623u }, { 9978506365220160957u, 211317812454266098u },
|
||||
{ 15361502721659949412u, 169054249963412878u }, { 2442311466204457120u, 270486799941460606u },
|
||||
{ 16711244431931206989u, 216389439953168484u }, { 17058344360286875914u, 173111551962534787u },
|
||||
{ 12535955717491360170u, 276978483140055660u }, { 10028764573993088136u, 221582786512044528u },
|
||||
{ 15401709288678291155u, 177266229209635622u }, { 9885339602917624555u, 283625966735416996u },
|
||||
{ 4218922867592189321u, 226900773388333597u }, { 14443184738299482427u, 181520618710666877u },
|
||||
{ 4175850161155765295u, 145216494968533502u }, { 10370709072591134795u, 232346391949653603u },
|
||||
{ 15675264887556728482u, 185877113559722882u }, { 5161514280561562140u, 148701690847778306u },
|
||||
{ 879725219414678777u, 237922705356445290u }, { 703780175531743021u, 190338164285156232u },
|
||||
{ 11631070584651125387u, 152270531428124985u }, { 162968861732249003u, 243632850284999977u },
|
||||
{ 11198421533611530172u, 194906280227999981u }, { 5269388412147313814u, 155925024182399985u },
|
||||
{ 8431021459435702103u, 249480038691839976u }, { 3055468352806651359u, 199584030953471981u },
|
||||
{ 17201769941212962380u, 159667224762777584u }, { 16454785461715008838u, 255467559620444135u },
|
||||
{ 13163828369372007071u, 204374047696355308u }, { 17909760324981426303u, 163499238157084246u },
|
||||
{ 2830174816776909822u, 261598781051334795u }, { 2264139853421527858u, 209279024841067836u },
|
||||
{ 16568707141704863579u, 167423219872854268u }, { 4373838538276319787u, 267877151796566830u },
|
||||
{ 3499070830621055830u, 214301721437253464u }, { 6488605479238754987u, 171441377149802771u },
|
||||
{ 3003071137298187333u, 274306203439684434u }, { 6091805724580460189u, 219444962751747547u },
|
||||
{ 15941491023890099121u, 175555970201398037u }, { 10748990379256517301u, 280889552322236860u },
|
||||
{ 8599192303405213841u, 224711641857789488u }, { 14258051472207991719u, 179769313486231590u }
|
||||
};
|
||||
|
||||
inline constexpr uint64_t __DOUBLE_POW5_SPLIT[326][2] = {
|
||||
{ 0u, 72057594037927936u }, { 0u, 90071992547409920u },
|
||||
{ 0u, 112589990684262400u }, { 0u, 140737488355328000u },
|
||||
{ 0u, 87960930222080000u }, { 0u, 109951162777600000u },
|
||||
{ 0u, 137438953472000000u }, { 0u, 85899345920000000u },
|
||||
{ 0u, 107374182400000000u }, { 0u, 134217728000000000u },
|
||||
{ 0u, 83886080000000000u }, { 0u, 104857600000000000u },
|
||||
{ 0u, 131072000000000000u }, { 0u, 81920000000000000u },
|
||||
{ 0u, 102400000000000000u }, { 0u, 128000000000000000u },
|
||||
{ 0u, 80000000000000000u }, { 0u, 100000000000000000u },
|
||||
{ 0u, 125000000000000000u }, { 0u, 78125000000000000u },
|
||||
{ 0u, 97656250000000000u }, { 0u, 122070312500000000u },
|
||||
{ 0u, 76293945312500000u }, { 0u, 95367431640625000u },
|
||||
{ 0u, 119209289550781250u }, { 4611686018427387904u, 74505805969238281u },
|
||||
{ 10376293541461622784u, 93132257461547851u }, { 8358680908399640576u, 116415321826934814u },
|
||||
{ 612489549322387456u, 72759576141834259u }, { 14600669991935148032u, 90949470177292823u },
|
||||
{ 13639151471491547136u, 113686837721616029u }, { 3213881284082270208u, 142108547152020037u },
|
||||
{ 4314518811765112832u, 88817841970012523u }, { 781462496279003136u, 111022302462515654u },
|
||||
{ 10200200157203529728u, 138777878078144567u }, { 13292654125893287936u, 86736173798840354u },
|
||||
{ 7392445620511834112u, 108420217248550443u }, { 4628871007212404736u, 135525271560688054u },
|
||||
{ 16728102434789916672u, 84703294725430033u }, { 7075069988205232128u, 105879118406787542u },
|
||||
{ 18067209522111315968u, 132348898008484427u }, { 8986162942105878528u, 82718061255302767u },
|
||||
{ 6621017659204960256u, 103397576569128459u }, { 3664586055578812416u, 129246970711410574u },
|
||||
{ 16125424340018921472u, 80779356694631608u }, { 1710036351314100224u, 100974195868289511u },
|
||||
{ 15972603494424788992u, 126217744835361888u }, { 9982877184015493120u, 78886090522101180u },
|
||||
{ 12478596480019366400u, 98607613152626475u }, { 10986559581596820096u, 123259516440783094u },
|
||||
{ 2254913720070624656u, 77037197775489434u }, { 12042014186943056628u, 96296497219361792u },
|
||||
{ 15052517733678820785u, 120370621524202240u }, { 9407823583549262990u, 75231638452626400u },
|
||||
{ 11759779479436578738u, 94039548065783000u }, { 14699724349295723422u, 117549435082228750u },
|
||||
{ 4575641699882439235u, 73468396926392969u }, { 10331238143280436948u, 91835496157991211u },
|
||||
{ 8302361660673158281u, 114794370197489014u }, { 1154580038986672043u, 143492962746861268u },
|
||||
{ 9944984561221445835u, 89683101716788292u }, { 12431230701526807293u, 112103877145985365u },
|
||||
{ 1703980321626345405u, 140129846432481707u }, { 17205888765512323542u, 87581154020301066u },
|
||||
{ 12283988920035628619u, 109476442525376333u }, { 1519928094762372062u, 136845553156720417u },
|
||||
{ 12479170105294952299u, 85528470722950260u }, { 15598962631618690374u, 106910588403687825u },
|
||||
{ 5663645234241199255u, 133638235504609782u }, { 17374836326682913246u, 83523897190381113u },
|
||||
{ 7883487353071477846u, 104404871487976392u }, { 9854359191339347308u, 130506089359970490u },
|
||||
{ 10770660513014479971u, 81566305849981556u }, { 13463325641268099964u, 101957882312476945u },
|
||||
{ 2994098996302961243u, 127447352890596182u }, { 15706369927971514489u, 79654595556622613u },
|
||||
{ 5797904354682229399u, 99568244445778267u }, { 2635694424925398845u, 124460305557222834u },
|
||||
{ 6258995034005762182u, 77787690973264271u }, { 3212057774079814824u, 97234613716580339u },
|
||||
{ 17850130272881932242u, 121543267145725423u }, { 18073860448192289507u, 75964541966078389u },
|
||||
{ 8757267504958198172u, 94955677457597987u }, { 6334898362770359811u, 118694596821997484u },
|
||||
{ 13182683513586250689u, 74184123013748427u }, { 11866668373555425458u, 92730153767185534u },
|
||||
{ 5609963430089506015u, 115912692208981918u }, { 17341285199088104971u, 72445432630613698u },
|
||||
{ 12453234462005355406u, 90556790788267123u }, { 10954857059079306353u, 113195988485333904u },
|
||||
{ 13693571323849132942u, 141494985606667380u }, { 17781854114260483896u, 88434366004167112u },
|
||||
{ 3780573569116053255u, 110542957505208891u }, { 114030942967678664u, 138178696881511114u },
|
||||
{ 4682955357782187069u, 86361685550944446u }, { 15077066234082509644u, 107952106938680557u },
|
||||
{ 5011274737320973344u, 134940133673350697u }, { 14661261756894078100u, 84337583545844185u },
|
||||
{ 4491519140835433913u, 105421979432305232u }, { 5614398926044292391u, 131777474290381540u },
|
||||
{ 12732371365632458552u, 82360921431488462u }, { 6692092170185797382u, 102951151789360578u },
|
||||
{ 17588487249587022536u, 128688939736700722u }, { 15604490549419276989u, 80430587335437951u },
|
||||
{ 14893927168346708332u, 100538234169297439u }, { 14005722942005997511u, 125672792711621799u },
|
||||
{ 15671105866394830300u, 78545495444763624u }, { 1142138259283986260u, 98181869305954531u },
|
||||
{ 15262730879387146537u, 122727336632443163u }, { 7233363790403272633u, 76704585395276977u },
|
||||
{ 13653390756431478696u, 95880731744096221u }, { 3231680390257184658u, 119850914680120277u },
|
||||
{ 4325643253124434363u, 74906821675075173u }, { 10018740084832930858u, 93633527093843966u },
|
||||
{ 3300053069186387764u, 117041908867304958u }, { 15897591223523656064u, 73151193042065598u },
|
||||
{ 10648616992549794273u, 91438991302581998u }, { 4087399203832467033u, 114298739128227498u },
|
||||
{ 14332621041645359599u, 142873423910284372u }, { 18181260187883125557u, 89295889943927732u },
|
||||
{ 4279831161144355331u, 111619862429909666u }, { 14573160988285219972u, 139524828037387082u },
|
||||
{ 13719911636105650386u, 87203017523366926u }, { 7926517508277287175u, 109003771904208658u },
|
||||
{ 684774848491833161u, 136254714880260823u }, { 7345513307948477581u, 85159196800163014u },
|
||||
{ 18405263671790372785u, 106448996000203767u }, { 18394893571310578077u, 133061245000254709u },
|
||||
{ 13802651491282805250u, 83163278125159193u }, { 3418256308821342851u, 103954097656448992u },
|
||||
{ 4272820386026678563u, 129942622070561240u }, { 2670512741266674102u, 81214138794100775u },
|
||||
{ 17173198981865506339u, 101517673492625968u }, { 3019754653622331308u, 126897091865782461u },
|
||||
{ 4193189667727651020u, 79310682416114038u }, { 14464859121514339583u, 99138353020142547u },
|
||||
{ 13469387883465536574u, 123922941275178184u }, { 8418367427165960359u, 77451838296986365u },
|
||||
{ 15134645302384838353u, 96814797871232956u }, { 471562554271496325u, 121018497339041196u },
|
||||
{ 9518098633274461011u, 75636560836900747u }, { 7285937273165688360u, 94545701046125934u },
|
||||
{ 18330793628311886258u, 118182126307657417u }, { 4539216990053847055u, 73863828942285886u },
|
||||
{ 14897393274422084627u, 92329786177857357u }, { 4786683537745442072u, 115412232722321697u },
|
||||
{ 14520892257159371055u, 72132645451451060u }, { 18151115321449213818u, 90165806814313825u },
|
||||
{ 8853836096529353561u, 112707258517892282u }, { 1843923083806916143u, 140884073147365353u },
|
||||
{ 12681666973447792349u, 88052545717103345u }, { 2017025661527576725u, 110065682146379182u },
|
||||
{ 11744654113764246714u, 137582102682973977u }, { 422879793461572340u, 85988814176858736u },
|
||||
{ 528599741826965425u, 107486017721073420u }, { 660749677283706782u, 134357522151341775u },
|
||||
{ 7330497575943398595u, 83973451344588609u }, { 13774807988356636147u, 104966814180735761u },
|
||||
{ 3383451930163631472u, 131208517725919702u }, { 15949715511634433382u, 82005323578699813u },
|
||||
{ 6102086334260878016u, 102506654473374767u }, { 3015921899398709616u, 128133318091718459u },
|
||||
{ 18025852251620051174u, 80083323807324036u }, { 4085571240815512351u, 100104154759155046u },
|
||||
{ 14330336087874166247u, 125130193448943807u }, { 15873989082562435760u, 78206370905589879u },
|
||||
{ 15230800334775656796u, 97757963631987349u }, { 5203442363187407284u, 122197454539984187u },
|
||||
{ 946308467778435600u, 76373409087490117u }, { 5794571603150432404u, 95466761359362646u },
|
||||
{ 16466586540792816313u, 119333451699203307u }, { 7985773578781816244u, 74583407312002067u },
|
||||
{ 5370530955049882401u, 93229259140002584u }, { 6713163693812353001u, 116536573925003230u },
|
||||
{ 18030785363914884337u, 72835358703127018u }, { 13315109668038829614u, 91044198378908773u },
|
||||
{ 2808829029766373305u, 113805247973635967u }, { 17346094342490130344u, 142256559967044958u },
|
||||
{ 6229622945628943561u, 88910349979403099u }, { 3175342663608791547u, 111137937474253874u },
|
||||
{ 13192550366365765242u, 138922421842817342u }, { 3633657960551215372u, 86826513651760839u },
|
||||
{ 18377130505971182927u, 108533142064701048u }, { 4524669058754427043u, 135666427580876311u },
|
||||
{ 9745447189362598758u, 84791517238047694u }, { 2958436949848472639u, 105989396547559618u },
|
||||
{ 12921418224165366607u, 132486745684449522u }, { 12687572408530742033u, 82804216052780951u },
|
||||
{ 11247779492236039638u, 103505270065976189u }, { 224666310012885835u, 129381587582470237u },
|
||||
{ 2446259452971747599u, 80863492239043898u }, { 12281196353069460307u, 101079365298804872u },
|
||||
{ 15351495441336825384u, 126349206623506090u }, { 14206370669262903769u, 78968254139691306u },
|
||||
{ 8534591299723853903u, 98710317674614133u }, { 15279925143082205283u, 123387897093267666u },
|
||||
{ 14161639232853766206u, 77117435683292291u }, { 13090363022639819853u, 96396794604115364u },
|
||||
{ 16362953778299774816u, 120495993255144205u }, { 12532689120651053212u, 75309995784465128u },
|
||||
{ 15665861400813816515u, 94137494730581410u }, { 10358954714162494836u, 117671868413226763u },
|
||||
{ 4168503687137865320u, 73544917758266727u }, { 598943590494943747u, 91931147197833409u },
|
||||
{ 5360365506546067587u, 114913933997291761u }, { 11312142901609972388u, 143642417496614701u },
|
||||
{ 9375932322719926695u, 89776510935384188u }, { 11719915403399908368u, 112220638669230235u },
|
||||
{ 10038208235822497557u, 140275798336537794u }, { 10885566165816448877u, 87672373960336121u },
|
||||
{ 18218643725697949000u, 109590467450420151u }, { 18161618638695048346u, 136988084313025189u },
|
||||
{ 13656854658398099168u, 85617552695640743u }, { 12459382304570236056u, 107021940869550929u },
|
||||
{ 1739169825430631358u, 133777426086938662u }, { 14922039196176308311u, 83610891304336663u },
|
||||
{ 14040862976792997485u, 104513614130420829u }, { 3716020665709083144u, 130642017663026037u },
|
||||
{ 4628355925281870917u, 81651261039391273u }, { 10397130925029726550u, 102064076299239091u },
|
||||
{ 8384727637859770284u, 127580095374048864u }, { 5240454773662356427u, 79737559608780540u },
|
||||
{ 6550568467077945534u, 99671949510975675u }, { 3576524565420044014u, 124589936888719594u },
|
||||
{ 6847013871814915412u, 77868710555449746u }, { 17782139376623420074u, 97335888194312182u },
|
||||
{ 13004302183924499284u, 121669860242890228u }, { 17351060901807587860u, 76043662651806392u },
|
||||
{ 3242082053549933210u, 95054578314757991u }, { 17887660622219580224u, 118818222893447488u },
|
||||
{ 11179787888887237640u, 74261389308404680u }, { 13974734861109047050u, 92826736635505850u },
|
||||
{ 8245046539531533005u, 116033420794382313u }, { 16682369133275677888u, 72520887996488945u },
|
||||
{ 7017903361312433648u, 90651109995611182u }, { 17995751238495317868u, 113313887494513977u },
|
||||
{ 8659630992836983623u, 141642359368142472u }, { 5412269370523114764u, 88526474605089045u },
|
||||
{ 11377022731581281359u, 110658093256361306u }, { 4997906377621825891u, 138322616570451633u },
|
||||
{ 14652906532082110942u, 86451635356532270u }, { 9092761128247862869u, 108064544195665338u },
|
||||
{ 2142579373455052779u, 135080680244581673u }, { 12868327154477877747u, 84425425152863545u },
|
||||
{ 2250350887815183471u, 105531781441079432u }, { 2812938609768979339u, 131914726801349290u },
|
||||
{ 6369772649532999991u, 82446704250843306u }, { 17185587848771025797u, 103058380313554132u },
|
||||
{ 3035240737254230630u, 128822975391942666u }, { 6508711479211282048u, 80514359619964166u },
|
||||
{ 17359261385868878368u, 100642949524955207u }, { 17087390713908710056u, 125803686906194009u },
|
||||
{ 3762090168551861929u, 78627304316371256u }, { 4702612710689827411u, 98284130395464070u },
|
||||
{ 15101637925217060072u, 122855162994330087u }, { 16356052730901744401u, 76784476871456304u },
|
||||
{ 1998321839917628885u, 95980596089320381u }, { 7109588318324424010u, 119975745111650476u },
|
||||
{ 13666864735807540814u, 74984840694781547u }, { 12471894901332038114u, 93731050868476934u },
|
||||
{ 6366496589810271835u, 117163813585596168u }, { 3979060368631419896u, 73227383490997605u },
|
||||
{ 9585511479216662775u, 91534229363747006u }, { 2758517312166052660u, 114417786704683758u },
|
||||
{ 12671518677062341634u, 143022233380854697u }, { 1002170145522881665u, 89388895863034186u },
|
||||
{ 10476084718758377889u, 111736119828792732u }, { 13095105898447972362u, 139670149785990915u },
|
||||
{ 5878598177316288774u, 87293843616244322u }, { 16571619758500136775u, 109117304520305402u },
|
||||
{ 11491152661270395161u, 136396630650381753u }, { 264441385652915120u, 85247894156488596u },
|
||||
{ 330551732066143900u, 106559867695610745u }, { 5024875683510067779u, 133199834619513431u },
|
||||
{ 10058076329834874218u, 83249896637195894u }, { 3349223375438816964u, 104062370796494868u },
|
||||
{ 4186529219298521205u, 130077963495618585u }, { 14145795808130045513u, 81298727184761615u },
|
||||
{ 13070558741735168987u, 101623408980952019u }, { 11726512408741573330u, 127029261226190024u },
|
||||
{ 7329070255463483331u, 79393288266368765u }, { 13773023837756742068u, 99241610332960956u },
|
||||
{ 17216279797195927585u, 124052012916201195u }, { 8454331864033760789u, 77532508072625747u },
|
||||
{ 5956228811614813082u, 96915635090782184u }, { 7445286014518516353u, 121144543863477730u },
|
||||
{ 9264989777501460624u, 75715339914673581u }, { 16192923240304213684u, 94644174893341976u },
|
||||
{ 1794409976670715490u, 118305218616677471u }, { 8039035263060279037u, 73940761635423419u },
|
||||
{ 5437108060397960892u, 92425952044279274u }, { 16019757112352226923u, 115532440055349092u },
|
||||
{ 788976158365366019u, 72207775034593183u }, { 14821278253238871236u, 90259718793241478u },
|
||||
{ 9303225779693813237u, 112824648491551848u }, { 11629032224617266546u, 141030810614439810u },
|
||||
{ 11879831158813179495u, 88144256634024881u }, { 1014730893234310657u, 110180320792531102u },
|
||||
{ 10491785653397664129u, 137725400990663877u }, { 8863209042587234033u, 86078375619164923u },
|
||||
{ 6467325284806654637u, 107597969523956154u }, { 17307528642863094104u, 134497461904945192u },
|
||||
{ 10817205401789433815u, 84060913690590745u }, { 18133192770664180173u, 105076142113238431u },
|
||||
{ 18054804944902837312u, 131345177641548039u }, { 18201782118205355176u, 82090736025967524u },
|
||||
{ 4305483574047142354u, 102613420032459406u }, { 14605226504413703751u, 128266775040574257u },
|
||||
{ 2210737537617482988u, 80166734400358911u }, { 16598479977304017447u, 100208418000448638u },
|
||||
{ 11524727934775246001u, 125260522500560798u }, { 2591268940807140847u, 78287826562850499u },
|
||||
{ 17074144231291089770u, 97859783203563123u }, { 16730994270686474309u, 122324729004453904u },
|
||||
{ 10456871419179046443u, 76452955627783690u }, { 3847717237119032246u, 95566194534729613u },
|
||||
{ 9421332564826178211u, 119457743168412016u }, { 5888332853016361382u, 74661089480257510u },
|
||||
{ 16583788103125227536u, 93326361850321887u }, { 16118049110479146516u, 116657952312902359u },
|
||||
{ 16991309721690548428u, 72911220195563974u }, { 12015765115258409727u, 91139025244454968u },
|
||||
{ 15019706394073012159u, 113923781555568710u }, { 9551260955736489391u, 142404726944460888u },
|
||||
{ 5969538097335305869u, 89002954340288055u }, { 2850236603241744433u, 111253692925360069u }
|
||||
};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // _LIBCPP_SRC_INCLUDE_RYU_D2S_FULL_TABLE_H
|
260
third_party/libcxx/src/include/ryu/d2s_intrinsics.h
vendored
Normal file
260
third_party/libcxx/src/include/ryu/d2s_intrinsics.h
vendored
Normal file
|
@ -0,0 +1,260 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Copyright 2018 Ulf Adams
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef _LIBCPP_SRC_INCLUDE_RYU_DS2_INTRINSICS_H
|
||||
#define _LIBCPP_SRC_INCLUDE_RYU_DS2_INTRINSICS_H
|
||||
|
||||
// Avoid formatting to keep the changes with the original code minimal.
|
||||
// clang-format off
|
||||
|
||||
#include <__assert>
|
||||
#include <__config>
|
||||
|
||||
#include "third_party/libcxx/src/include/ryu/ryu.h"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if defined(_M_X64) && defined(_MSC_VER)
|
||||
#define _LIBCPP_INTRINSIC128 1
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __ryu_umul128(const uint64_t __a, const uint64_t __b, uint64_t* const __productHi) {
|
||||
return _umul128(__a, __b, __productHi);
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __ryu_shiftright128(const uint64_t __lo, const uint64_t __hi, const uint32_t __dist) {
|
||||
// For the __shiftright128 intrinsic, the shift value is always
|
||||
// modulo 64.
|
||||
// In the current implementation of the double-precision version
|
||||
// of Ryu, the shift value is always < 64.
|
||||
// (The shift value is in the range [49, 58].)
|
||||
// Check this here in case a future change requires larger shift
|
||||
// values. In this case this function needs to be adjusted.
|
||||
_LIBCPP_ASSERT(__dist < 64, "");
|
||||
return __shiftright128(__lo, __hi, static_cast<unsigned char>(__dist));
|
||||
}
|
||||
|
||||
// ^^^ intrinsics available ^^^ / vvv __int128 available vvv
|
||||
#elif defined(__SIZEOF_INT128__) && ( \
|
||||
(defined(__clang__) && !defined(_MSC_VER)) || \
|
||||
(defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__)))
|
||||
#define _LIBCPP_INTRINSIC128 1
|
||||
// We have __uint128 support in clang or gcc
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __ryu_umul128(const uint64_t __a, const uint64_t __b, uint64_t* const __productHi) {
|
||||
auto __temp = __a * (unsigned __int128)__b;
|
||||
*__productHi = __temp >> 64;
|
||||
return static_cast<uint64_t>(__temp);
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __ryu_shiftright128(const uint64_t __lo, const uint64_t __hi, const uint32_t __dist) {
|
||||
// In the current implementation of the double-precision version
|
||||
// of Ryu, the shift value is always < 64.
|
||||
// (The shift value is in the range [49, 58].)
|
||||
// Check this here in case a future change requires larger shift
|
||||
// values. In this case this function needs to be adjusted.
|
||||
_LIBCPP_ASSERT(__dist < 64, "");
|
||||
auto __temp = __lo | ((unsigned __int128)__hi << 64);
|
||||
// For x64 128-bit shfits using the `shrd` instruction and two 64-bit
|
||||
// registers, the shift value is modulo 64. Thus the `& 63` is free.
|
||||
return static_cast<uint64_t>(__temp >> (__dist & 63));
|
||||
}
|
||||
#else // ^^^ __int128 available ^^^ / vvv intrinsics unavailable vvv
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_ALWAYS_INLINE uint64_t __ryu_umul128(const uint64_t __a, const uint64_t __b, uint64_t* const __productHi) {
|
||||
// TRANSITION, VSO-634761
|
||||
// The casts here help MSVC to avoid calls to the __allmul library function.
|
||||
const uint32_t __aLo = static_cast<uint32_t>(__a);
|
||||
const uint32_t __aHi = static_cast<uint32_t>(__a >> 32);
|
||||
const uint32_t __bLo = static_cast<uint32_t>(__b);
|
||||
const uint32_t __bHi = static_cast<uint32_t>(__b >> 32);
|
||||
|
||||
const uint64_t __b00 = static_cast<uint64_t>(__aLo) * __bLo;
|
||||
const uint64_t __b01 = static_cast<uint64_t>(__aLo) * __bHi;
|
||||
const uint64_t __b10 = static_cast<uint64_t>(__aHi) * __bLo;
|
||||
const uint64_t __b11 = static_cast<uint64_t>(__aHi) * __bHi;
|
||||
|
||||
const uint32_t __b00Lo = static_cast<uint32_t>(__b00);
|
||||
const uint32_t __b00Hi = static_cast<uint32_t>(__b00 >> 32);
|
||||
|
||||
const uint64_t __mid1 = __b10 + __b00Hi;
|
||||
const uint32_t __mid1Lo = static_cast<uint32_t>(__mid1);
|
||||
const uint32_t __mid1Hi = static_cast<uint32_t>(__mid1 >> 32);
|
||||
|
||||
const uint64_t __mid2 = __b01 + __mid1Lo;
|
||||
const uint32_t __mid2Lo = static_cast<uint32_t>(__mid2);
|
||||
const uint32_t __mid2Hi = static_cast<uint32_t>(__mid2 >> 32);
|
||||
|
||||
const uint64_t __pHi = __b11 + __mid1Hi + __mid2Hi;
|
||||
const uint64_t __pLo = (static_cast<uint64_t>(__mid2Lo) << 32) | __b00Lo;
|
||||
|
||||
*__productHi = __pHi;
|
||||
return __pLo;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __ryu_shiftright128(const uint64_t __lo, const uint64_t __hi, const uint32_t __dist) {
|
||||
// We don't need to handle the case __dist >= 64 here (see above).
|
||||
_LIBCPP_ASSERT(__dist < 64, "");
|
||||
#ifdef _LIBCPP_64_BIT
|
||||
_LIBCPP_ASSERT(__dist > 0, "");
|
||||
return (__hi << (64 - __dist)) | (__lo >> __dist);
|
||||
#else // ^^^ 64-bit ^^^ / vvv 32-bit vvv
|
||||
// Avoid a 64-bit shift by taking advantage of the range of shift values.
|
||||
_LIBCPP_ASSERT(__dist >= 32, "");
|
||||
return (__hi << (64 - __dist)) | (static_cast<uint32_t>(__lo >> 32) >> (__dist - 32));
|
||||
#endif // ^^^ 32-bit ^^^
|
||||
}
|
||||
|
||||
#endif // ^^^ intrinsics unavailable ^^^
|
||||
|
||||
#ifndef _LIBCPP_64_BIT
|
||||
|
||||
// Returns the high 64 bits of the 128-bit product of __a and __b.
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __umulh(const uint64_t __a, const uint64_t __b) {
|
||||
// Reuse the __ryu_umul128 implementation.
|
||||
// Optimizers will likely eliminate the instructions used to compute the
|
||||
// low part of the product.
|
||||
uint64_t __hi;
|
||||
(void) __ryu_umul128(__a, __b, &__hi);
|
||||
return __hi;
|
||||
}
|
||||
|
||||
// On 32-bit platforms, compilers typically generate calls to library
|
||||
// functions for 64-bit divisions, even if the divisor is a constant.
|
||||
//
|
||||
// TRANSITION, LLVM-37932
|
||||
//
|
||||
// The functions here perform division-by-constant using multiplications
|
||||
// in the same way as 64-bit compilers would do.
|
||||
//
|
||||
// NB:
|
||||
// The multipliers and shift values are the ones generated by clang x64
|
||||
// for expressions like x/5, x/10, etc.
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __div5(const uint64_t __x) {
|
||||
return __umulh(__x, 0xCCCCCCCCCCCCCCCDu) >> 2;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __div10(const uint64_t __x) {
|
||||
return __umulh(__x, 0xCCCCCCCCCCCCCCCDu) >> 3;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __div100(const uint64_t __x) {
|
||||
return __umulh(__x >> 2, 0x28F5C28F5C28F5C3u) >> 2;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __div1e8(const uint64_t __x) {
|
||||
return __umulh(__x, 0xABCC77118461CEFDu) >> 26;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __div1e9(const uint64_t __x) {
|
||||
return __umulh(__x >> 9, 0x44B82FA09B5A53u) >> 11;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __mod1e9(const uint64_t __x) {
|
||||
// Avoid 64-bit math as much as possible.
|
||||
// Returning static_cast<uint32_t>(__x - 1000000000 * __div1e9(__x)) would
|
||||
// perform 32x64-bit multiplication and 64-bit subtraction.
|
||||
// __x and 1000000000 * __div1e9(__x) are guaranteed to differ by
|
||||
// less than 10^9, so their highest 32 bits must be identical,
|
||||
// so we can truncate both sides to uint32_t before subtracting.
|
||||
// We can also simplify static_cast<uint32_t>(1000000000 * __div1e9(__x)).
|
||||
// We can truncate before multiplying instead of after, as multiplying
|
||||
// the highest 32 bits of __div1e9(__x) can't affect the lowest 32 bits.
|
||||
return static_cast<uint32_t>(__x) - 1000000000 * static_cast<uint32_t>(__div1e9(__x));
|
||||
}
|
||||
|
||||
#else // ^^^ 32-bit ^^^ / vvv 64-bit vvv
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __div5(const uint64_t __x) {
|
||||
return __x / 5;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __div10(const uint64_t __x) {
|
||||
return __x / 10;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __div100(const uint64_t __x) {
|
||||
return __x / 100;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __div1e8(const uint64_t __x) {
|
||||
return __x / 100000000;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __div1e9(const uint64_t __x) {
|
||||
return __x / 1000000000;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __mod1e9(const uint64_t __x) {
|
||||
return static_cast<uint32_t>(__x - 1000000000 * __div1e9(__x));
|
||||
}
|
||||
|
||||
#endif // ^^^ 64-bit ^^^
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __pow5Factor(uint64_t __value) {
|
||||
uint32_t __count = 0;
|
||||
for (;;) {
|
||||
_LIBCPP_ASSERT(__value != 0, "");
|
||||
const uint64_t __q = __div5(__value);
|
||||
const uint32_t __r = static_cast<uint32_t>(__value) - 5 * static_cast<uint32_t>(__q);
|
||||
if (__r != 0) {
|
||||
break;
|
||||
}
|
||||
__value = __q;
|
||||
++__count;
|
||||
}
|
||||
return __count;
|
||||
}
|
||||
|
||||
// Returns true if __value is divisible by 5^__p.
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline bool __multipleOfPowerOf5(const uint64_t __value, const uint32_t __p) {
|
||||
// I tried a case distinction on __p, but there was no performance difference.
|
||||
return __pow5Factor(__value) >= __p;
|
||||
}
|
||||
|
||||
// Returns true if __value is divisible by 2^__p.
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline bool __multipleOfPowerOf2(const uint64_t __value, const uint32_t __p) {
|
||||
_LIBCPP_ASSERT(__value != 0, "");
|
||||
_LIBCPP_ASSERT(__p < 64, "");
|
||||
// __builtin_ctzll doesn't appear to be faster here.
|
||||
return (__value & ((1ull << __p) - 1)) == 0;
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // _LIBCPP_SRC_INCLUDE_RYU_DS2_INTRINSICS_H
|
57
third_party/libcxx/src/include/ryu/digit_table.h
vendored
Normal file
57
third_party/libcxx/src/include/ryu/digit_table.h
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Copyright 2018 Ulf Adams
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef _LIBCPP_SRC_INCLUDE_RYU_DIGIT_TABLE_H
|
||||
#define _LIBCPP_SRC_INCLUDE_RYU_DIGIT_TABLE_H
|
||||
|
||||
#include <__charconv/tables.h>
|
||||
#include <__config>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// A table of all two-digit numbers. This is used to speed up decimal digit
|
||||
// generation by copying pairs of digits into the final output.
|
||||
//
|
||||
// In order to minimize the diff in the Ryu code between MSVC STL and libc++
|
||||
// the code uses the name __DIGIT_TABLE. In order to avoid code duplication it
|
||||
// reuses the table already available in libc++.
|
||||
inline constexpr auto& __DIGIT_TABLE = __itoa::__digits_base_10;
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_SRC_INCLUDE_RYU_DIGIT_TABLE_H
|
55
third_party/libcxx/src/include/ryu/f2s.h
vendored
Normal file
55
third_party/libcxx/src/include/ryu/f2s.h
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Copyright 2018 Ulf Adams
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef _LIBCPP_SRC_INCLUDE_RYU_FS2_H
|
||||
#define _LIBCPP_SRC_INCLUDE_RYU_FS2_H
|
||||
|
||||
// Avoid formatting to keep the changes with the original code minimal.
|
||||
// clang-format off
|
||||
|
||||
#include <__config>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
[[nodiscard]] to_chars_result __f2s_buffered_n(char* const _First, char* const _Last, const float __f, const chars_format _Fmt);
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // _LIBCPP_SRC_INCLUDE_RYU_FS2_H
|
149
third_party/libcxx/src/include/ryu/ryu.h
vendored
Normal file
149
third_party/libcxx/src/include/ryu/ryu.h
vendored
Normal file
|
@ -0,0 +1,149 @@
|
|||
// -*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
|
||||
// Copyright 2018 Ulf Adams
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#ifndef _LIBCPP_SRC_INCLUDE_RYU_RYU_H
|
||||
#define _LIBCPP_SRC_INCLUDE_RYU_RYU_H
|
||||
|
||||
// Avoid formatting to keep the changes with the original code minimal.
|
||||
// clang-format off
|
||||
|
||||
#include <__charconv/chars_format.h>
|
||||
#include <__charconv/to_chars_result.h>
|
||||
#include <__config>
|
||||
#include <__debug>
|
||||
#include <__system_error/errc.h>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#include "third_party/libcxx/src/include/ryu/f2s.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2s.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2fixed.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h> // for _umul128(), __shiftright128(), _BitScanForward{,64}
|
||||
#endif // defined(_MSC_VER)
|
||||
|
||||
#if defined(_WIN64) || defined(_M_AMD64) || defined(__x86_64__) || defined(__aarch64__)
|
||||
#define _LIBCPP_64_BIT
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// https://github.com/ulfjack/ryu/tree/59661c3/ryu
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
_LIBCPP_HIDE_FROM_ABI inline unsigned char _BitScanForward64(unsigned long* __index, unsigned long long __mask) {
|
||||
if (__mask == 0) {
|
||||
return false;
|
||||
}
|
||||
*__index = __builtin_ctzll(__mask);
|
||||
return true;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI inline unsigned char _BitScanForward(unsigned long* __index, unsigned int __mask) {
|
||||
if (__mask == 0) {
|
||||
return false;
|
||||
}
|
||||
*__index = __builtin_ctz(__mask);
|
||||
return true;
|
||||
}
|
||||
#endif // !_MSC_VER
|
||||
|
||||
template <class _Floating>
|
||||
[[nodiscard]] to_chars_result _Floating_to_chars_ryu(
|
||||
char* const _First, char* const _Last, const _Floating _Value, const chars_format _Fmt) noexcept {
|
||||
if constexpr (_IsSame<_Floating, float>::value) {
|
||||
return __f2s_buffered_n(_First, _Last, _Value, _Fmt);
|
||||
} else {
|
||||
return __d2s_buffered_n(_First, _Last, _Value, _Fmt);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Floating>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI to_chars_result _Floating_to_chars_scientific_precision(
|
||||
char* const _First, char* const _Last, const _Floating _Value, int _Precision) noexcept {
|
||||
|
||||
// C11 7.21.6.1 "The fprintf function"/5:
|
||||
// "A negative precision argument is taken as if the precision were omitted."
|
||||
// /8: "e,E [...] if the precision is missing, it is taken as 6"
|
||||
|
||||
if (_Precision < 0) {
|
||||
_Precision = 6;
|
||||
} else if (_Precision < 1'000'000'000) { // Match ' to fix compilation with GCC in C++11 mode
|
||||
// _Precision is ok.
|
||||
} else {
|
||||
// Avoid integer overflow.
|
||||
// (This defensive check is slightly nonconformant; it can be carefully improved in the future.)
|
||||
return {_Last, errc::value_too_large};
|
||||
}
|
||||
|
||||
return __d2exp_buffered_n(_First, _Last, _Value, static_cast<uint32_t>(_Precision));
|
||||
}
|
||||
|
||||
template <class _Floating>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI to_chars_result _Floating_to_chars_fixed_precision(
|
||||
char* const _First, char* const _Last, const _Floating _Value, int _Precision) noexcept {
|
||||
|
||||
// C11 7.21.6.1 "The fprintf function"/5:
|
||||
// "A negative precision argument is taken as if the precision were omitted."
|
||||
// /8: "f,F [...] If the precision is missing, it is taken as 6"
|
||||
|
||||
if (_Precision < 0) {
|
||||
_Precision = 6;
|
||||
} else if (_Precision < 1'000'000'000) { // Match ' to fix compilation with GCC in C++11 mode
|
||||
// _Precision is ok.
|
||||
} else {
|
||||
// Avoid integer overflow.
|
||||
// (This defensive check is slightly nonconformant; it can be carefully improved in the future.)
|
||||
return {_Last, errc::value_too_large};
|
||||
}
|
||||
|
||||
return __d2fixed_buffered_n(_First, _Last, _Value, static_cast<uint32_t>(_Precision));
|
||||
}
|
||||
|
||||
#undef _LIBCPP_64_BIT
|
||||
#undef _LIBCPP_INTRINSIC128
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
// clang-format on
|
||||
|
||||
#endif // _LIBCPP_SRC_INCLUDE_RYU_RYU_H
|
82
third_party/libcxx/src/include/sso_allocator.h
vendored
Normal file
82
third_party/libcxx/src/include/sso_allocator.h
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
// -*- 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;
|
||||
|
||||
template <class U>
|
||||
struct rebind {
|
||||
using other = __sso_allocator<U, _Np>;
|
||||
};
|
||||
|
||||
_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
|
1085
third_party/libcxx/src/include/to_chars_floating_point.h
vendored
Normal file
1085
third_party/libcxx/src/include/to_chars_floating_point.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
443
third_party/libcxx/src/ios.cpp
vendored
Normal file
443
third_party/libcxx/src/ios.cpp
vendored
Normal file
|
@ -0,0 +1,443 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <__locale>
|
||||
#include <algorithm>
|
||||
#include <ios>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
|
||||
#include "third_party/libcxx/src/include/config_elast.h"
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#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_{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_HAS_NO_EXCEPTIONS
|
||||
if (__exceptions_ & badbit)
|
||||
throw;
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::__set_failbit_and_consider_rethrow()
|
||||
{
|
||||
__rdstate_ |= failbit;
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
if (__exceptions_ & failbit)
|
||||
throw;
|
||||
#endif // _LIBCPP_HAS_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
|
||||
|
||||
_LIBCPP_POP_MACROS
|
48
third_party/libcxx/src/ios.instantiations.cpp
vendored
Normal file
48
third_party/libcxx/src/ios.instantiations.cpp
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>;
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_FSTREAM
|
||||
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>;
|
||||
#endif
|
||||
|
||||
// Add more here if needed...
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
168
third_party/libcxx/src/iostream.cpp
vendored
Normal file
168
third_party/libcxx/src/iostream.cpp
vendored
Normal file
|
@ -0,0 +1,168 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 "std_stream.h"
|
||||
#include <new>
|
||||
#include <string>
|
||||
|
||||
#ifdef _LIBCPP_MSVCRT_LIKE
|
||||
# include <__locale_dir/locale_base_api/locale_guard.h>
|
||||
#endif
|
||||
|
||||
#define _str(s) #s
|
||||
#define str(s) _str(s)
|
||||
#define _LIBCPP_ABI_NAMESPACE_STR str(_LIBCPP_ABI_NAMESPACE)
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
_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
|
||||
;
|
||||
_ALIGNAS_TYPE (__stdinbuf<char> ) static char __cin[sizeof(__stdinbuf <char>)];
|
||||
static mbstate_t mb_cin;
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
_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
|
||||
;
|
||||
_ALIGNAS_TYPE (__stdinbuf<wchar_t> ) static char __wcin[sizeof(__stdinbuf <wchar_t>)];
|
||||
static mbstate_t mb_wcin;
|
||||
#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
|
||||
_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
|
||||
;
|
||||
_ALIGNAS_TYPE (__stdoutbuf<char>) static char __cout[sizeof(__stdoutbuf<char>)];
|
||||
static mbstate_t mb_cout;
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
_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
|
||||
;
|
||||
_ALIGNAS_TYPE (__stdoutbuf<wchar_t>) static char __wcout[sizeof(__stdoutbuf<wchar_t>)];
|
||||
static mbstate_t mb_wcout;
|
||||
#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
|
||||
_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
|
||||
;
|
||||
_ALIGNAS_TYPE (__stdoutbuf<char>) static char __cerr[sizeof(__stdoutbuf<char>)];
|
||||
static mbstate_t mb_cerr;
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
_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
|
||||
;
|
||||
_ALIGNAS_TYPE (__stdoutbuf<wchar_t>) static char __wcerr[sizeof(__stdoutbuf<wchar_t>)];
|
||||
static mbstate_t mb_wcerr;
|
||||
#endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
|
||||
_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
|
||||
;
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
_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 // _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
|
||||
// Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority
|
||||
// attribute with a value that's reserved for the implementation (we're the implementation).
|
||||
#include "iostream_init.h"
|
||||
|
||||
// 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
|
2
third_party/libcxx/src/iostream_init.h
vendored
Normal file
2
third_party/libcxx/src/iostream_init.h
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
#pragma GCC system_header
|
||||
_LIBCPP_HIDDEN ios_base::Init __start_std_streams _LIBCPP_INIT_PRIORITY_MAX;
|
54
third_party/libcxx/src/legacy_debug_handler.cpp
vendored
Normal file
54
third_party/libcxx/src/legacy_debug_handler.cpp
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
// This file defines the legacy default debug handler and related mechanisms
|
||||
// to set it. This is for backwards ABI compatibility with code that has been
|
||||
// using this debug handler previously.
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
struct _LIBCPP_TEMPLATE_VIS __libcpp_debug_info {
|
||||
_LIBCPP_EXPORTED_FROM_ABI string what() const;
|
||||
|
||||
const char* __file_;
|
||||
int __line_;
|
||||
const char* __pred_;
|
||||
const char* __msg_;
|
||||
};
|
||||
|
||||
std::string __libcpp_debug_info::what() const {
|
||||
string msg = __file_;
|
||||
msg += ":" + std::to_string(__line_) + ": _LIBCPP_ASSERT '";
|
||||
msg += __pred_;
|
||||
msg += "' failed. ";
|
||||
msg += __msg_;
|
||||
return msg;
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
|
||||
std::fprintf(stderr, "%s\n", info.what().c_str());
|
||||
std::abort();
|
||||
}
|
||||
|
||||
typedef void (*__libcpp_debug_function_type)(__libcpp_debug_info const&);
|
||||
|
||||
_LIBCPP_EXPORTED_FROM_ABI
|
||||
constinit __libcpp_debug_function_type __libcpp_debug_function = __libcpp_abort_debug_function;
|
||||
|
||||
_LIBCPP_EXPORTED_FROM_ABI
|
||||
bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) {
|
||||
__libcpp_debug_function = __func;
|
||||
return true;
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
23
third_party/libcxx/src/legacy_pointer_safety.cpp
vendored
Normal file
23
third_party/libcxx/src/legacy_pointer_safety.cpp
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <memory>
|
||||
|
||||
// Support for garbage collection was removed in C++23 by https://wg21.link/P2186R2. Libc++ implements
|
||||
// that removal as an extension in all Standard versions. However, we still define the functions that
|
||||
// were once part of the library's ABI for backwards compatibility.
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_FUNC_VIS void declare_reachable(void*) {}
|
||||
_LIBCPP_FUNC_VIS void declare_no_pointers(char*, size_t) {}
|
||||
_LIBCPP_FUNC_VIS void undeclare_no_pointers(char*, size_t) {}
|
||||
_LIBCPP_FUNC_VIS void* __undeclare_reachable(void* p) { return p; }
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
6596
third_party/libcxx/src/locale.cpp
vendored
Normal file
6596
third_party/libcxx/src/locale.cpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
207
third_party/libcxx/src/memory.cpp
vendored
Normal file
207
third_party/libcxx/src/memory.cpp
vendored
Normal file
|
@ -0,0 +1,207 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>
|
||||
#ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
|
||||
# define _LIBCPP_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
#include "third_party/libcxx/src/include/atomic_support.h"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
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_SHARED_PTR_DEFINE_LEGACY_INLINE_FUNCTIONS)
|
||||
void
|
||||
__shared_count::__add_shared() noexcept
|
||||
{
|
||||
__libcpp_atomic_refcount_increment(__shared_owners_);
|
||||
}
|
||||
|
||||
bool
|
||||
__shared_count::__release_shared() noexcept
|
||||
{
|
||||
if (__libcpp_atomic_refcount_decrement(__shared_owners_) == -1)
|
||||
{
|
||||
__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
|
||||
{
|
||||
__libcpp_atomic_refcount_increment(__shared_weak_owners_);
|
||||
}
|
||||
|
||||
void
|
||||
__shared_weak_count::__release_shared() noexcept
|
||||
{
|
||||
if (__shared_count::__release_shared())
|
||||
__release_weak();
|
||||
}
|
||||
#endif // _LIBCPP_SHARED_PTR_DEFINE_LEGACY_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.
|
||||
if (__libcpp_atomic_load(&__shared_weak_owners_, _AO_Acquire) == 0)
|
||||
{
|
||||
// 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();
|
||||
}
|
||||
else if (__libcpp_atomic_refcount_decrement(__shared_weak_owners_) == -1)
|
||||
__on_zero_shared_weak();
|
||||
}
|
||||
|
||||
__shared_weak_count*
|
||||
__shared_weak_count::lock() noexcept
|
||||
{
|
||||
long object_owners = __libcpp_atomic_load(&__shared_owners_);
|
||||
while (object_owners != -1)
|
||||
{
|
||||
if (__libcpp_atomic_compare_exchange(&__shared_owners_,
|
||||
&object_owners,
|
||||
object_owners+1))
|
||||
return this;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const void*
|
||||
__shared_weak_count::__get_deleter(const type_info&) const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
|
||||
static constexpr std::size_t __sp_mut_count = 32;
|
||||
static constinit __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_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_);
|
||||
__libcpp_mutex_lock(m);
|
||||
}
|
||||
|
||||
void
|
||||
__sp_mut::unlock() noexcept
|
||||
{
|
||||
__libcpp_mutex_unlock(static_cast<__libcpp_mutex_t*>(__lx_));
|
||||
}
|
||||
|
||||
__sp_mut&
|
||||
__get_sp_mut(const void* p)
|
||||
{
|
||||
static constinit __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],
|
||||
&mut_back[16], &mut_back[17], &mut_back[18], &mut_back[19],
|
||||
&mut_back[20], &mut_back[21], &mut_back[22], &mut_back[23],
|
||||
&mut_back[24], &mut_back[25], &mut_back[26], &mut_back[27],
|
||||
&mut_back[28], &mut_back[29], &mut_back[30], &mut_back[31]
|
||||
};
|
||||
return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
|
||||
}
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
|
||||
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<uintptr_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
|
496
third_party/libcxx/src/memory_resource.cpp
vendored
Normal file
496
third_party/libcxx/src/memory_resource.cpp
vendored
Normal file
|
@ -0,0 +1,496 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>
|
||||
#include <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_STD
|
||||
|
||||
namespace pmr {
|
||||
|
||||
// memory_resource
|
||||
|
||||
memory_resource::~memory_resource() = default;
|
||||
|
||||
// new_delete_resource()
|
||||
|
||||
#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
static bool is_aligned_to(void* ptr, size_t align) {
|
||||
void* p2 = ptr;
|
||||
size_t space = 1;
|
||||
void* result = std::align(align, 1, p2, space);
|
||||
return (result == ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp : public memory_resource {
|
||||
void* do_allocate(size_t bytes, size_t align) override {
|
||||
#ifndef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
return std::__libcpp_allocate(bytes, align);
|
||||
#else
|
||||
if (bytes == 0)
|
||||
bytes = 1;
|
||||
void* result = std::__libcpp_allocate(bytes, align);
|
||||
if (!is_aligned_to(result, align)) {
|
||||
std::__libcpp_deallocate(result, bytes, align);
|
||||
__throw_bad_alloc();
|
||||
}
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
void do_deallocate(void* p, size_t bytes, size_t align) override { std::__libcpp_deallocate(p, bytes, align); }
|
||||
|
||||
bool do_is_equal(const memory_resource& other) const noexcept override { return &other == this; }
|
||||
};
|
||||
|
||||
// null_memory_resource()
|
||||
|
||||
class _LIBCPP_TYPE_VIS __null_memory_resource_imp : public memory_resource {
|
||||
void* do_allocate(size_t, size_t) override { __throw_bad_alloc(); }
|
||||
void do_deallocate(void*, size_t, size_t) override {}
|
||||
bool do_is_equal(const memory_resource& other) const noexcept override { 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_SINCE_CXX14 ResourceInitHelper() : resources() {}
|
||||
~ResourceInitHelper() {}
|
||||
};
|
||||
|
||||
// Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority
|
||||
// attribute with a value that's reserved for the implementation (we're the implementation).
|
||||
#include "memory_resource_init_helper.h"
|
||||
|
||||
} // 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
|
||||
static constinit atomic<memory_resource*> __res{&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 std::atomic_exchange_explicit(&__res, new_res, memory_order_acq_rel);
|
||||
} else {
|
||||
return std::atomic_load_explicit(&__res, memory_order_acquire);
|
||||
}
|
||||
#elif !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
static constinit 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
|
||||
static constinit 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);
|
||||
}
|
||||
|
||||
// 23.12.5, mem.res.pool
|
||||
|
||||
static size_t roundup(size_t count, size_t alignment) {
|
||||
size_t mask = alignment - 1;
|
||||
return (count + mask) & ~mask;
|
||||
}
|
||||
|
||||
struct unsynchronized_pool_resource::__adhoc_pool::__chunk_footer {
|
||||
__chunk_footer* __next_;
|
||||
char* __start_;
|
||||
size_t __align_;
|
||||
size_t __allocation_size() { return (reinterpret_cast<char*>(this) - __start_) + sizeof(*this); }
|
||||
};
|
||||
|
||||
void unsynchronized_pool_resource::__adhoc_pool::__release_ptr(memory_resource* upstream) {
|
||||
while (__first_ != nullptr) {
|
||||
__chunk_footer* next = __first_->__next_;
|
||||
upstream->deallocate(__first_->__start_, __first_->__allocation_size(), __first_->__align_);
|
||||
__first_ = next;
|
||||
}
|
||||
}
|
||||
|
||||
void* unsynchronized_pool_resource::__adhoc_pool::__do_allocate(memory_resource* upstream, size_t bytes, size_t align) {
|
||||
const size_t footer_size = sizeof(__chunk_footer);
|
||||
const size_t footer_align = alignof(__chunk_footer);
|
||||
|
||||
if (align < footer_align)
|
||||
align = footer_align;
|
||||
|
||||
size_t aligned_capacity = roundup(bytes, footer_align) + footer_size;
|
||||
|
||||
void* result = upstream->allocate(aligned_capacity, align);
|
||||
|
||||
__chunk_footer* h = (__chunk_footer*)((char*)result + aligned_capacity - footer_size);
|
||||
h->__next_ = __first_;
|
||||
h->__start_ = (char*)result;
|
||||
h->__align_ = align;
|
||||
__first_ = h;
|
||||
return result;
|
||||
}
|
||||
|
||||
void unsynchronized_pool_resource::__adhoc_pool::__do_deallocate(
|
||||
memory_resource* upstream, void* p, size_t bytes, size_t align) {
|
||||
_LIBCPP_ASSERT(__first_ != nullptr, "deallocating a block that was not allocated with this allocator");
|
||||
if (__first_->__start_ == p) {
|
||||
__chunk_footer* next = __first_->__next_;
|
||||
upstream->deallocate(p, __first_->__allocation_size(), __first_->__align_);
|
||||
__first_ = next;
|
||||
} else {
|
||||
for (__chunk_footer* h = __first_; h->__next_ != nullptr; h = h->__next_) {
|
||||
if (h->__next_->__start_ == p) {
|
||||
__chunk_footer* next = h->__next_->__next_;
|
||||
upstream->deallocate(p, h->__next_->__allocation_size(), h->__next_->__align_);
|
||||
h->__next_ = next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
_LIBCPP_ASSERT(false, "deallocating a block that was not allocated with this allocator");
|
||||
}
|
||||
}
|
||||
|
||||
class unsynchronized_pool_resource::__fixed_pool {
|
||||
struct __chunk_footer {
|
||||
__chunk_footer* __next_;
|
||||
char* __start_;
|
||||
size_t __align_;
|
||||
size_t __allocation_size() { return (reinterpret_cast<char*>(this) - __start_) + sizeof(*this); }
|
||||
};
|
||||
|
||||
struct __vacancy_header {
|
||||
__vacancy_header* __next_vacancy_;
|
||||
};
|
||||
|
||||
__chunk_footer* __first_chunk_ = nullptr;
|
||||
__vacancy_header* __first_vacancy_ = nullptr;
|
||||
|
||||
public:
|
||||
explicit __fixed_pool() = default;
|
||||
|
||||
void __release_ptr(memory_resource* upstream) {
|
||||
__first_vacancy_ = nullptr;
|
||||
while (__first_chunk_ != nullptr) {
|
||||
__chunk_footer* next = __first_chunk_->__next_;
|
||||
upstream->deallocate(__first_chunk_->__start_, __first_chunk_->__allocation_size(), __first_chunk_->__align_);
|
||||
__first_chunk_ = next;
|
||||
}
|
||||
}
|
||||
|
||||
void* __try_allocate_from_vacancies() {
|
||||
if (__first_vacancy_ != nullptr) {
|
||||
void* result = __first_vacancy_;
|
||||
__first_vacancy_ = __first_vacancy_->__next_vacancy_;
|
||||
return result;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* __allocate_in_new_chunk(memory_resource* upstream, size_t block_size, size_t chunk_size) {
|
||||
_LIBCPP_ASSERT(chunk_size % block_size == 0, "");
|
||||
static_assert(__default_alignment >= alignof(std::max_align_t), "");
|
||||
static_assert(__default_alignment >= alignof(__chunk_footer), "");
|
||||
static_assert(__default_alignment >= alignof(__vacancy_header), "");
|
||||
|
||||
const size_t footer_size = sizeof(__chunk_footer);
|
||||
const size_t footer_align = alignof(__chunk_footer);
|
||||
|
||||
size_t aligned_capacity = roundup(chunk_size, footer_align) + footer_size;
|
||||
|
||||
void* result = upstream->allocate(aligned_capacity, __default_alignment);
|
||||
|
||||
__chunk_footer* h = (__chunk_footer*)((char*)result + aligned_capacity - footer_size);
|
||||
h->__next_ = __first_chunk_;
|
||||
h->__start_ = (char*)result;
|
||||
h->__align_ = __default_alignment;
|
||||
__first_chunk_ = h;
|
||||
|
||||
if (chunk_size > block_size) {
|
||||
__vacancy_header* last_vh = this->__first_vacancy_;
|
||||
for (size_t i = block_size; i != chunk_size; i += block_size) {
|
||||
__vacancy_header* vh = (__vacancy_header*)((char*)result + i);
|
||||
vh->__next_vacancy_ = last_vh;
|
||||
last_vh = vh;
|
||||
}
|
||||
this->__first_vacancy_ = last_vh;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void __evacuate(void* p) {
|
||||
__vacancy_header* vh = (__vacancy_header*)(p);
|
||||
vh->__next_vacancy_ = __first_vacancy_;
|
||||
__first_vacancy_ = vh;
|
||||
}
|
||||
|
||||
size_t __previous_chunk_size_in_bytes() const { return __first_chunk_ ? __first_chunk_->__allocation_size() : 0; }
|
||||
|
||||
static const size_t __default_alignment = alignof(max_align_t);
|
||||
};
|
||||
|
||||
size_t unsynchronized_pool_resource::__pool_block_size(int i) const { return size_t(1) << __log2_pool_block_size(i); }
|
||||
|
||||
int unsynchronized_pool_resource::__log2_pool_block_size(int i) const { return (i + __log2_smallest_block_size); }
|
||||
|
||||
int unsynchronized_pool_resource::__pool_index(size_t bytes, size_t align) const {
|
||||
if (align > alignof(std::max_align_t) || bytes > (size_t(1) << __num_fixed_pools_))
|
||||
return __num_fixed_pools_;
|
||||
else {
|
||||
int i = 0;
|
||||
bytes = (bytes > align) ? bytes : align;
|
||||
bytes -= 1;
|
||||
bytes >>= __log2_smallest_block_size;
|
||||
while (bytes != 0) {
|
||||
bytes >>= 1;
|
||||
i += 1;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
unsynchronized_pool_resource::unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream)
|
||||
: __res_(upstream), __fixed_pools_(nullptr) {
|
||||
size_t largest_block_size;
|
||||
if (opts.largest_required_pool_block == 0)
|
||||
largest_block_size = __default_largest_block_size;
|
||||
else if (opts.largest_required_pool_block < __smallest_block_size)
|
||||
largest_block_size = __smallest_block_size;
|
||||
else if (opts.largest_required_pool_block > __max_largest_block_size)
|
||||
largest_block_size = __max_largest_block_size;
|
||||
else
|
||||
largest_block_size = opts.largest_required_pool_block;
|
||||
|
||||
if (opts.max_blocks_per_chunk == 0)
|
||||
__options_max_blocks_per_chunk_ = __max_blocks_per_chunk;
|
||||
else if (opts.max_blocks_per_chunk < __min_blocks_per_chunk)
|
||||
__options_max_blocks_per_chunk_ = __min_blocks_per_chunk;
|
||||
else if (opts.max_blocks_per_chunk > __max_blocks_per_chunk)
|
||||
__options_max_blocks_per_chunk_ = __max_blocks_per_chunk;
|
||||
else
|
||||
__options_max_blocks_per_chunk_ = opts.max_blocks_per_chunk;
|
||||
|
||||
__num_fixed_pools_ = 1;
|
||||
size_t capacity = __smallest_block_size;
|
||||
while (capacity < largest_block_size) {
|
||||
capacity <<= 1;
|
||||
__num_fixed_pools_ += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pool_options unsynchronized_pool_resource::options() const {
|
||||
pool_options p;
|
||||
p.max_blocks_per_chunk = __options_max_blocks_per_chunk_;
|
||||
p.largest_required_pool_block = __pool_block_size(__num_fixed_pools_ - 1);
|
||||
return p;
|
||||
}
|
||||
|
||||
void unsynchronized_pool_resource::release() {
|
||||
__adhoc_pool_.__release_ptr(__res_);
|
||||
if (__fixed_pools_ != nullptr) {
|
||||
const int n = __num_fixed_pools_;
|
||||
for (int i = 0; i < n; ++i)
|
||||
__fixed_pools_[i].__release_ptr(__res_);
|
||||
__res_->deallocate(__fixed_pools_, __num_fixed_pools_ * sizeof(__fixed_pool), alignof(__fixed_pool));
|
||||
__fixed_pools_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void* unsynchronized_pool_resource::do_allocate(size_t bytes, size_t align) {
|
||||
// A pointer to allocated storage (6.6.4.4.1) with a size of at least bytes.
|
||||
// The size and alignment of the allocated memory shall meet the requirements for
|
||||
// a class derived from memory_resource (23.12).
|
||||
// If the pool selected for a block of size bytes is unable to satisfy the memory request
|
||||
// from its own internal data structures, it will call upstream_resource()->allocate()
|
||||
// to obtain more memory. If bytes is larger than that which the largest pool can handle,
|
||||
// then memory will be allocated using upstream_resource()->allocate().
|
||||
|
||||
int i = __pool_index(bytes, align);
|
||||
if (i == __num_fixed_pools_)
|
||||
return __adhoc_pool_.__do_allocate(__res_, bytes, align);
|
||||
else {
|
||||
if (__fixed_pools_ == nullptr) {
|
||||
__fixed_pools_ =
|
||||
(__fixed_pool*)__res_->allocate(__num_fixed_pools_ * sizeof(__fixed_pool), alignof(__fixed_pool));
|
||||
__fixed_pool* first = __fixed_pools_;
|
||||
__fixed_pool* last = __fixed_pools_ + __num_fixed_pools_;
|
||||
for (__fixed_pool* pool = first; pool != last; ++pool)
|
||||
::new ((void*)pool) __fixed_pool;
|
||||
}
|
||||
void* result = __fixed_pools_[i].__try_allocate_from_vacancies();
|
||||
if (result == nullptr) {
|
||||
auto min = [](size_t a, size_t b) { return a < b ? a : b; };
|
||||
auto max = [](size_t a, size_t b) { return a < b ? b : a; };
|
||||
|
||||
size_t prev_chunk_size_in_bytes = __fixed_pools_[i].__previous_chunk_size_in_bytes();
|
||||
size_t prev_chunk_size_in_blocks = prev_chunk_size_in_bytes >> __log2_pool_block_size(i);
|
||||
|
||||
size_t chunk_size_in_blocks;
|
||||
|
||||
if (prev_chunk_size_in_blocks == 0) {
|
||||
size_t min_blocks_per_chunk = max(__min_bytes_per_chunk >> __log2_pool_block_size(i), __min_blocks_per_chunk);
|
||||
chunk_size_in_blocks = min_blocks_per_chunk;
|
||||
} else {
|
||||
static_assert(__max_bytes_per_chunk <= SIZE_MAX - (__max_bytes_per_chunk / 4), "unsigned overflow is possible");
|
||||
chunk_size_in_blocks = prev_chunk_size_in_blocks + (prev_chunk_size_in_blocks / 4);
|
||||
}
|
||||
|
||||
size_t max_blocks_per_chunk =
|
||||
min((__max_bytes_per_chunk >> __log2_pool_block_size(i)),
|
||||
min(__max_blocks_per_chunk, __options_max_blocks_per_chunk_));
|
||||
if (chunk_size_in_blocks > max_blocks_per_chunk)
|
||||
chunk_size_in_blocks = max_blocks_per_chunk;
|
||||
|
||||
size_t block_size = __pool_block_size(i);
|
||||
|
||||
size_t chunk_size_in_bytes = (chunk_size_in_blocks << __log2_pool_block_size(i));
|
||||
result = __fixed_pools_[i].__allocate_in_new_chunk(__res_, block_size, chunk_size_in_bytes);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
void unsynchronized_pool_resource::do_deallocate(void* p, size_t bytes, size_t align) {
|
||||
// Returns the memory at p to the pool. It is unspecified if,
|
||||
// or under what circumstances, this operation will result in
|
||||
// a call to upstream_resource()->deallocate().
|
||||
|
||||
int i = __pool_index(bytes, align);
|
||||
if (i == __num_fixed_pools_)
|
||||
return __adhoc_pool_.__do_deallocate(__res_, p, bytes, align);
|
||||
else {
|
||||
_LIBCPP_ASSERT(__fixed_pools_ != nullptr, "deallocating a block that was not allocated with this allocator");
|
||||
__fixed_pools_[i].__evacuate(p);
|
||||
}
|
||||
}
|
||||
|
||||
bool synchronized_pool_resource::do_is_equal(const memory_resource& other) const noexcept { return &other == this; }
|
||||
|
||||
// 23.12.6, mem.res.monotonic.buffer
|
||||
|
||||
static void* align_down(size_t align, size_t size, void*& ptr, size_t& space) {
|
||||
if (size > space)
|
||||
return nullptr;
|
||||
|
||||
char* p1 = static_cast<char*>(ptr);
|
||||
char* new_ptr = reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(p1 - size) & ~(align - 1));
|
||||
|
||||
if (new_ptr < (p1 - space))
|
||||
return nullptr;
|
||||
|
||||
ptr = new_ptr;
|
||||
space -= p1 - new_ptr;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void* monotonic_buffer_resource::__initial_descriptor::__try_allocate_from_chunk(size_t bytes, size_t align) {
|
||||
if (!__cur_)
|
||||
return nullptr;
|
||||
void* new_ptr = static_cast<void*>(__cur_);
|
||||
size_t new_capacity = (__cur_ - __start_);
|
||||
void* aligned_ptr = align_down(align, bytes, new_ptr, new_capacity);
|
||||
if (aligned_ptr != nullptr)
|
||||
__cur_ = static_cast<char*>(new_ptr);
|
||||
return aligned_ptr;
|
||||
}
|
||||
|
||||
void* monotonic_buffer_resource::__chunk_footer::__try_allocate_from_chunk(size_t bytes, size_t align) {
|
||||
void* new_ptr = static_cast<void*>(__cur_);
|
||||
size_t new_capacity = (__cur_ - __start_);
|
||||
void* aligned_ptr = align_down(align, bytes, new_ptr, new_capacity);
|
||||
if (aligned_ptr != nullptr)
|
||||
__cur_ = static_cast<char*>(new_ptr);
|
||||
return aligned_ptr;
|
||||
}
|
||||
|
||||
void* monotonic_buffer_resource::do_allocate(size_t bytes, size_t align) {
|
||||
const size_t footer_size = sizeof(__chunk_footer);
|
||||
const size_t footer_align = alignof(__chunk_footer);
|
||||
|
||||
auto previous_allocation_size = [&]() {
|
||||
if (__chunks_ != nullptr)
|
||||
return __chunks_->__allocation_size();
|
||||
|
||||
size_t newsize = (__initial_.__start_ != nullptr) ? (__initial_.__end_ - __initial_.__start_) : __initial_.__size_;
|
||||
|
||||
return roundup(newsize, footer_align) + footer_size;
|
||||
};
|
||||
|
||||
if (void* result = __initial_.__try_allocate_from_chunk(bytes, align))
|
||||
return result;
|
||||
if (__chunks_ != nullptr) {
|
||||
if (void* result = __chunks_->__try_allocate_from_chunk(bytes, align))
|
||||
return result;
|
||||
}
|
||||
|
||||
// Allocate a brand-new chunk.
|
||||
|
||||
if (align < footer_align)
|
||||
align = footer_align;
|
||||
|
||||
size_t aligned_capacity = roundup(bytes, footer_align) + footer_size;
|
||||
size_t previous_capacity = previous_allocation_size();
|
||||
|
||||
if (aligned_capacity <= previous_capacity) {
|
||||
size_t newsize = 2 * (previous_capacity - footer_size);
|
||||
aligned_capacity = roundup(newsize, footer_align) + footer_size;
|
||||
}
|
||||
|
||||
char* start = (char*)__res_->allocate(aligned_capacity, align);
|
||||
auto end = start + aligned_capacity - footer_size;
|
||||
__chunk_footer* footer = (__chunk_footer*)(end);
|
||||
footer->__next_ = __chunks_;
|
||||
footer->__start_ = start;
|
||||
footer->__cur_ = end;
|
||||
footer->__align_ = align;
|
||||
__chunks_ = footer;
|
||||
|
||||
return __chunks_->__try_allocate_from_chunk(bytes, align);
|
||||
}
|
||||
|
||||
} // namespace pmr
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
2
third_party/libcxx/src/memory_resource_init_helper.h
vendored
Normal file
2
third_party/libcxx/src/memory_resource_init_helper.h
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
#pragma GCC system_header
|
||||
static constinit ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX;
|
262
third_party/libcxx/src/mutex.cpp
vendored
Normal file
262
third_party/libcxx/src/mutex.cpp
vendored
Normal file
|
@ -0,0 +1,262 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <__assert>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
|
||||
#include "third_party/libcxx/src/include/atomic_support.h"
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
# if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
|
||||
# pragma comment(lib, "pthread")
|
||||
# endif
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
|
||||
// ~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
|
||||
static constinit __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER;
|
||||
static constinit __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER;
|
||||
#endif
|
||||
|
||||
void __call_once(volatile once_flag::_State_type& flag, void* arg,
|
||||
void (*func)(void*))
|
||||
{
|
||||
#if defined(_LIBCPP_HAS_NO_THREADS)
|
||||
if (flag == 0)
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
flag = 1;
|
||||
func(arg);
|
||||
flag = ~once_flag::_State_type(0);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
flag = 0;
|
||||
throw;
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
#else // !_LIBCPP_HAS_NO_THREADS
|
||||
__libcpp_mutex_lock(&mut);
|
||||
while (flag == 1)
|
||||
__libcpp_condvar_wait(&cv, &mut);
|
||||
if (flag == 0)
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
__libcpp_relaxed_store(&flag, once_flag::_State_type(1));
|
||||
__libcpp_mutex_unlock(&mut);
|
||||
func(arg);
|
||||
__libcpp_mutex_lock(&mut);
|
||||
__libcpp_atomic_store(&flag, ~once_flag::_State_type(0),
|
||||
_AO_Release);
|
||||
__libcpp_mutex_unlock(&mut);
|
||||
__libcpp_condvar_broadcast(&cv);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
__libcpp_mutex_lock(&mut);
|
||||
__libcpp_relaxed_store(&flag, once_flag::_State_type(0));
|
||||
__libcpp_mutex_unlock(&mut);
|
||||
__libcpp_condvar_broadcast(&cv);
|
||||
throw;
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
else
|
||||
__libcpp_mutex_unlock(&mut);
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
50
third_party/libcxx/src/mutex_destructor.cpp
vendored
Normal file
50
third_party/libcxx/src/mutex_destructor.cpp
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
294
third_party/libcxx/src/new.cpp
vendored
Normal file
294
third_party/libcxx/src/new.cpp
vendored
Normal file
|
@ -0,0 +1,294 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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/aligned_alloc.h>
|
||||
#include <new>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "third_party/libcxx/src/include/atomic_support.h"
|
||||
|
||||
#if defined(_LIBCPP_ABI_MICROSOFT)
|
||||
# if !defined(_LIBCPP_ABI_VCRUNTIME)
|
||||
# include "third_party/libcxx/src/support/runtime/new_handler_fallback.ipp"
|
||||
# endif
|
||||
#elif defined(LIBCXX_BUILDING_LIBCXXABI)
|
||||
# include <cxxabi.h>
|
||||
#elif defined(LIBCXXRT)
|
||||
# include <cxxabi.h>
|
||||
# include "third_party/libcxx/src/support/runtime/new_handler_fallback.ipp"
|
||||
#elif defined(__GLIBCXX__)
|
||||
// nothing to do
|
||||
#else
|
||||
# include "third_party/libcxx/src/support/runtime/new_handler_fallback.ipp"
|
||||
#endif
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
#ifndef __GLIBCXX__
|
||||
const nothrow_t nothrow{};
|
||||
#endif
|
||||
|
||||
#ifndef LIBSTDCXX
|
||||
|
||||
void
|
||||
__throw_bad_alloc()
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_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_HAS_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new(size_t size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
void* p = nullptr;
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
p = ::operator new(size);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_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_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
p = ::operator new[](size);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
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) 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);
|
||||
}
|
||||
|
||||
#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_HAS_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_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
p = ::operator new(size, alignment);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCPP_HAS_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, const std::nothrow_t&) noexcept
|
||||
{
|
||||
void* p = nullptr;
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
p = ::operator new[](size, alignment);
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
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);
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
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);
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
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);
|
||||
}
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
|
||||
#endif // !__GLIBCXX__ && !_LIBCPP_ABI_VCRUNTIME && !_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS
|
42
third_party/libcxx/src/optional.cpp
vendored
Normal file
42
third_party/libcxx/src/optional.cpp
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <__availability>
|
||||
#include <optional>
|
||||
|
||||
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
|
216
third_party/libcxx/src/random.cpp
vendored
Normal file
216
third_party/libcxx/src/random.cpp
vendored
Normal file
|
@ -0,0 +1,216 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <__system_error/system_error.h>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
|
||||
#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>
|
||||
#elif defined(_LIBCPP_USING_FUCHSIA_CPRNG)
|
||||
# include <zircon/syscalls.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&)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#elif defined(_LIBCPP_USING_FUCHSIA_CPRNG)
|
||||
|
||||
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()() {
|
||||
// Implicitly link against the vDSO system call ABI without
|
||||
// requiring the final link to specify -lzircon explicitly when
|
||||
// statically linking libc++.
|
||||
# pragma comment(lib, "zircon")
|
||||
|
||||
// The system call cannot fail. It returns only when the bits are ready.
|
||||
unsigned r;
|
||||
_zx_cprng_draw(&r, sizeof(r));
|
||||
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(_LIBCPP_USING_ARC4_RANDOM) || defined(_LIBCPP_USING_FUCHSIA_CPRNG)
|
||||
return std::numeric_limits<result_type>::digits;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
436
third_party/libcxx/src/regex.cpp
vendored
Normal file
436
third_party/libcxx/src/regex.cpp
vendored
Normal file
|
@ -0,0 +1,436 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <iterator>
|
||||
#include <regex>
|
||||
|
||||
_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_;
|
||||
};
|
||||
|
||||
#if defined(__MVS__) && !defined(__NATIVE_ASCII_F)
|
||||
// EBCDIC IBM-1047
|
||||
// Sorted via the EBCDIC collating sequence
|
||||
const collationnames collatenames[] =
|
||||
{
|
||||
{"a", 0x81},
|
||||
{"alert", 0x2f},
|
||||
{"ampersand", 0x50},
|
||||
{"apostrophe", 0x7d},
|
||||
{"asterisk", 0x5c},
|
||||
{"b", 0x82},
|
||||
{"backslash", 0xe0},
|
||||
{"backspace", 0x16},
|
||||
{"c", 0x83},
|
||||
{"carriage-return", 0xd},
|
||||
{"circumflex", 0x5f},
|
||||
{"circumflex-accent", 0x5f},
|
||||
{"colon", 0x7a},
|
||||
{"comma", 0x6b},
|
||||
{"commercial-at", 0x7c},
|
||||
{"d", 0x84},
|
||||
{"dollar-sign", 0x5b},
|
||||
{"e", 0x85},
|
||||
{"eight", 0xf8},
|
||||
{"equals-sign", 0x7e},
|
||||
{"exclamation-mark", 0x5a},
|
||||
{"f", 0x86},
|
||||
{"five", 0xf5},
|
||||
{"form-feed", 0xc},
|
||||
{"four", 0xf4},
|
||||
{"full-stop", 0x4b},
|
||||
{"g", 0x87},
|
||||
{"grave-accent", 0x79},
|
||||
{"greater-than-sign", 0x6e},
|
||||
{"h", 0x88},
|
||||
{"hyphen", 0x60},
|
||||
{"hyphen-minus", 0x60},
|
||||
{"i", 0x89},
|
||||
{"j", 0x91},
|
||||
{"k", 0x92},
|
||||
{"l", 0x93},
|
||||
{"left-brace", 0xc0},
|
||||
{"left-curly-bracket", 0xc0},
|
||||
{"left-parenthesis", 0x4d},
|
||||
{"left-square-bracket", 0xad},
|
||||
{"less-than-sign", 0x4c},
|
||||
{"low-line", 0x6d},
|
||||
{"m", 0x94},
|
||||
{"n", 0x95},
|
||||
{"newline", 0x15},
|
||||
{"nine", 0xf9},
|
||||
{"number-sign", 0x7b},
|
||||
{"o", 0x96},
|
||||
{"one", 0xf1},
|
||||
{"p", 0x97},
|
||||
{"percent-sign", 0x6c},
|
||||
{"period", 0x4b},
|
||||
{"plus-sign", 0x4e},
|
||||
{"q", 0x98},
|
||||
{"question-mark", 0x6f},
|
||||
{"quotation-mark", 0x7f},
|
||||
{"r", 0x99},
|
||||
{"reverse-solidus", 0xe0},
|
||||
{"right-brace", 0xd0},
|
||||
{"right-curly-bracket", 0xd0},
|
||||
{"right-parenthesis", 0x5d},
|
||||
{"right-square-bracket", 0xbd},
|
||||
{"s", 0xa2},
|
||||
{"semicolon", 0x5e},
|
||||
{"seven", 0xf7},
|
||||
{"six", 0xf6},
|
||||
{"slash", 0x61},
|
||||
{"solidus", 0x61},
|
||||
{"space", 0x40},
|
||||
{"t", 0xa3},
|
||||
{"tab", 0x5},
|
||||
{"three", 0xf3},
|
||||
{"tilde", 0xa1},
|
||||
{"two", 0xf2},
|
||||
{"u", 0xa4},
|
||||
{"underscore", 0x6d},
|
||||
{"v", 0xa5},
|
||||
{"vertical-line", 0x4f},
|
||||
{"vertical-tab", 0xb},
|
||||
{"w", 0xa6},
|
||||
{"x", 0xa7},
|
||||
{"y", 0xa8},
|
||||
{"z", 0xa9},
|
||||
{"zero", 0xf0},
|
||||
{"A", 0xc1},
|
||||
{"B", 0xc2},
|
||||
{"C", 0xc3},
|
||||
{"D", 0xc4},
|
||||
{"E", 0xc5},
|
||||
{"F", 0xc6},
|
||||
{"G", 0xc7},
|
||||
{"H", 0xc8},
|
||||
{"I", 0xc9},
|
||||
{"J", 0xd1},
|
||||
{"K", 0xd2},
|
||||
{"L", 0xd3},
|
||||
{"M", 0xd4},
|
||||
{"N", 0xd5},
|
||||
{"NUL", 0},
|
||||
{"O", 0xd6},
|
||||
{"P", 0xd7},
|
||||
{"Q", 0xd8},
|
||||
{"R", 0xd9},
|
||||
{"S", 0xe2},
|
||||
{"T", 0xe3},
|
||||
{"U", 0xe4},
|
||||
{"V", 0xe5},
|
||||
{"W", 0xe6},
|
||||
{"X", 0xe7},
|
||||
{"Y", 0xe8},
|
||||
{"Z", 0xe9}
|
||||
};
|
||||
#else
|
||||
// ASCII
|
||||
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}
|
||||
};
|
||||
#endif
|
||||
|
||||
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
|
11
third_party/libcxx/src/ryu/README.txt
vendored
Normal file
11
third_party/libcxx/src/ryu/README.txt
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
The code in this directory is based on Ulf Adams's work. The upstream for the
|
||||
code is:
|
||||
|
||||
https://github.com/ulfjack/ryu/tree/59661c3/ryu
|
||||
|
||||
The code has been adapted by Stephan T. Lavavej of Microsoft for usage in
|
||||
std::to_chars. This code has been contributed by Microsoft for inclusion in
|
||||
libc++.
|
||||
|
||||
The code in this directory has a different coding style than other parts to
|
||||
minimize the number of changes by both upstream sources.
|
669
third_party/libcxx/src/ryu/d2fixed.cpp
vendored
Normal file
669
third_party/libcxx/src/ryu/d2fixed.cpp
vendored
Normal file
|
@ -0,0 +1,669 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Copyright 2018 Ulf Adams
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// Avoid formatting to keep the changes with the original code minimal.
|
||||
// clang-format off
|
||||
|
||||
#include <__assert>
|
||||
#include <__config>
|
||||
#include <charconv>
|
||||
#include <cstring>
|
||||
|
||||
#include "third_party/libcxx/src/include/ryu/common.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2fixed.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2fixed_full_table.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2s.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2s_intrinsics.h"
|
||||
#include "third_party/libcxx/src/include/ryu/digit_table.h"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
inline constexpr int __POW10_ADDITIONAL_BITS = 120;
|
||||
|
||||
#ifdef _LIBCPP_INTRINSIC128
|
||||
// Returns the low 64 bits of the high 128 bits of the 256-bit product of a and b.
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __umul256_hi128_lo64(
|
||||
const uint64_t __aHi, const uint64_t __aLo, const uint64_t __bHi, const uint64_t __bLo) {
|
||||
uint64_t __b00Hi;
|
||||
const uint64_t __b00Lo = __ryu_umul128(__aLo, __bLo, &__b00Hi);
|
||||
uint64_t __b01Hi;
|
||||
const uint64_t __b01Lo = __ryu_umul128(__aLo, __bHi, &__b01Hi);
|
||||
uint64_t __b10Hi;
|
||||
const uint64_t __b10Lo = __ryu_umul128(__aHi, __bLo, &__b10Hi);
|
||||
uint64_t __b11Hi;
|
||||
const uint64_t __b11Lo = __ryu_umul128(__aHi, __bHi, &__b11Hi);
|
||||
(void) __b00Lo; // unused
|
||||
(void) __b11Hi; // unused
|
||||
const uint64_t __temp1Lo = __b10Lo + __b00Hi;
|
||||
const uint64_t __temp1Hi = __b10Hi + (__temp1Lo < __b10Lo);
|
||||
const uint64_t __temp2Lo = __b01Lo + __temp1Lo;
|
||||
const uint64_t __temp2Hi = __b01Hi + (__temp2Lo < __b01Lo);
|
||||
return __b11Lo + __temp1Hi + __temp2Hi;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __uint128_mod1e9(const uint64_t __vHi, const uint64_t __vLo) {
|
||||
// After multiplying, we're going to shift right by 29, then truncate to uint32_t.
|
||||
// This means that we need only 29 + 32 = 61 bits, so we can truncate to uint64_t before shifting.
|
||||
const uint64_t __multiplied = __umul256_hi128_lo64(__vHi, __vLo, 0x89705F4136B4A597u, 0x31680A88F8953031u);
|
||||
|
||||
// For uint32_t truncation, see the __mod1e9() comment in d2s_intrinsics.h.
|
||||
const uint32_t __shifted = static_cast<uint32_t>(__multiplied >> 29);
|
||||
|
||||
return static_cast<uint32_t>(__vLo) - 1000000000 * __shifted;
|
||||
}
|
||||
#endif // ^^^ intrinsics available ^^^
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __mulShift_mod1e9(const uint64_t __m, const uint64_t* const __mul, const int32_t __j) {
|
||||
uint64_t __high0; // 64
|
||||
const uint64_t __low0 = __ryu_umul128(__m, __mul[0], &__high0); // 0
|
||||
uint64_t __high1; // 128
|
||||
const uint64_t __low1 = __ryu_umul128(__m, __mul[1], &__high1); // 64
|
||||
uint64_t __high2; // 192
|
||||
const uint64_t __low2 = __ryu_umul128(__m, __mul[2], &__high2); // 128
|
||||
const uint64_t __s0low = __low0; // 0
|
||||
(void) __s0low; // unused
|
||||
const uint64_t __s0high = __low1 + __high0; // 64
|
||||
const uint32_t __c1 = __s0high < __low1;
|
||||
const uint64_t __s1low = __low2 + __high1 + __c1; // 128
|
||||
const uint32_t __c2 = __s1low < __low2; // __high1 + __c1 can't overflow, so compare against __low2
|
||||
const uint64_t __s1high = __high2 + __c2; // 192
|
||||
_LIBCPP_ASSERT(__j >= 128, "");
|
||||
_LIBCPP_ASSERT(__j <= 180, "");
|
||||
#ifdef _LIBCPP_INTRINSIC128
|
||||
const uint32_t __dist = static_cast<uint32_t>(__j - 128); // __dist: [0, 52]
|
||||
const uint64_t __shiftedhigh = __s1high >> __dist;
|
||||
const uint64_t __shiftedlow = __ryu_shiftright128(__s1low, __s1high, __dist);
|
||||
return __uint128_mod1e9(__shiftedhigh, __shiftedlow);
|
||||
#else // ^^^ intrinsics available ^^^ / vvv intrinsics unavailable vvv
|
||||
if (__j < 160) { // __j: [128, 160)
|
||||
const uint64_t __r0 = __mod1e9(__s1high);
|
||||
const uint64_t __r1 = __mod1e9((__r0 << 32) | (__s1low >> 32));
|
||||
const uint64_t __r2 = ((__r1 << 32) | (__s1low & 0xffffffff));
|
||||
return __mod1e9(__r2 >> (__j - 128));
|
||||
} else { // __j: [160, 192)
|
||||
const uint64_t __r0 = __mod1e9(__s1high);
|
||||
const uint64_t __r1 = ((__r0 << 32) | (__s1low >> 32));
|
||||
return __mod1e9(__r1 >> (__j - 160));
|
||||
}
|
||||
#endif // ^^^ intrinsics unavailable ^^^
|
||||
}
|
||||
|
||||
void __append_n_digits(const uint32_t __olength, uint32_t __digits, char* const __result) {
|
||||
uint32_t __i = 0;
|
||||
while (__digits >= 10000) {
|
||||
#ifdef __clang__ // TRANSITION, LLVM-38217
|
||||
const uint32_t __c = __digits - 10000 * (__digits / 10000);
|
||||
#else
|
||||
const uint32_t __c = __digits % 10000;
|
||||
#endif
|
||||
__digits /= 10000;
|
||||
const uint32_t __c0 = (__c % 100) << 1;
|
||||
const uint32_t __c1 = (__c / 100) << 1;
|
||||
std::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c0, 2);
|
||||
std::memcpy(__result + __olength - __i - 4, __DIGIT_TABLE + __c1, 2);
|
||||
__i += 4;
|
||||
}
|
||||
if (__digits >= 100) {
|
||||
const uint32_t __c = (__digits % 100) << 1;
|
||||
__digits /= 100;
|
||||
std::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c, 2);
|
||||
__i += 2;
|
||||
}
|
||||
if (__digits >= 10) {
|
||||
const uint32_t __c = __digits << 1;
|
||||
std::memcpy(__result + __olength - __i - 2, __DIGIT_TABLE + __c, 2);
|
||||
} else {
|
||||
__result[0] = static_cast<char>('0' + __digits);
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI inline void __append_d_digits(const uint32_t __olength, uint32_t __digits, char* const __result) {
|
||||
uint32_t __i = 0;
|
||||
while (__digits >= 10000) {
|
||||
#ifdef __clang__ // TRANSITION, LLVM-38217
|
||||
const uint32_t __c = __digits - 10000 * (__digits / 10000);
|
||||
#else
|
||||
const uint32_t __c = __digits % 10000;
|
||||
#endif
|
||||
__digits /= 10000;
|
||||
const uint32_t __c0 = (__c % 100) << 1;
|
||||
const uint32_t __c1 = (__c / 100) << 1;
|
||||
std::memcpy(__result + __olength + 1 - __i - 2, __DIGIT_TABLE + __c0, 2);
|
||||
std::memcpy(__result + __olength + 1 - __i - 4, __DIGIT_TABLE + __c1, 2);
|
||||
__i += 4;
|
||||
}
|
||||
if (__digits >= 100) {
|
||||
const uint32_t __c = (__digits % 100) << 1;
|
||||
__digits /= 100;
|
||||
std::memcpy(__result + __olength + 1 - __i - 2, __DIGIT_TABLE + __c, 2);
|
||||
__i += 2;
|
||||
}
|
||||
if (__digits >= 10) {
|
||||
const uint32_t __c = __digits << 1;
|
||||
__result[2] = __DIGIT_TABLE[__c + 1];
|
||||
__result[1] = '.';
|
||||
__result[0] = __DIGIT_TABLE[__c];
|
||||
} else {
|
||||
__result[1] = '.';
|
||||
__result[0] = static_cast<char>('0' + __digits);
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI inline void __append_c_digits(const uint32_t __count, uint32_t __digits, char* const __result) {
|
||||
uint32_t __i = 0;
|
||||
for (; __i < __count - 1; __i += 2) {
|
||||
const uint32_t __c = (__digits % 100) << 1;
|
||||
__digits /= 100;
|
||||
std::memcpy(__result + __count - __i - 2, __DIGIT_TABLE + __c, 2);
|
||||
}
|
||||
if (__i < __count) {
|
||||
const char __c = static_cast<char>('0' + (__digits % 10));
|
||||
__result[__count - __i - 1] = __c;
|
||||
}
|
||||
}
|
||||
|
||||
void __append_nine_digits(uint32_t __digits, char* const __result) {
|
||||
if (__digits == 0) {
|
||||
std::memset(__result, '0', 9);
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t __i = 0; __i < 5; __i += 4) {
|
||||
#ifdef __clang__ // TRANSITION, LLVM-38217
|
||||
const uint32_t __c = __digits - 10000 * (__digits / 10000);
|
||||
#else
|
||||
const uint32_t __c = __digits % 10000;
|
||||
#endif
|
||||
__digits /= 10000;
|
||||
const uint32_t __c0 = (__c % 100) << 1;
|
||||
const uint32_t __c1 = (__c / 100) << 1;
|
||||
std::memcpy(__result + 7 - __i, __DIGIT_TABLE + __c0, 2);
|
||||
std::memcpy(__result + 5 - __i, __DIGIT_TABLE + __c1, 2);
|
||||
}
|
||||
__result[0] = static_cast<char>('0' + __digits);
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __indexForExponent(const uint32_t __e) {
|
||||
return (__e + 15) / 16;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __pow10BitsForIndex(const uint32_t __idx) {
|
||||
return 16 * __idx + __POW10_ADDITIONAL_BITS;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __lengthForIndex(const uint32_t __idx) {
|
||||
// +1 for ceil, +16 for mantissa, +8 to round up when dividing by 9
|
||||
return (__log10Pow2(16 * static_cast<int32_t>(__idx)) + 1 + 16 + 8) / 9;
|
||||
}
|
||||
|
||||
[[nodiscard]] to_chars_result __d2fixed_buffered_n(char* _First, char* const _Last, const double __d,
|
||||
const uint32_t __precision) {
|
||||
char* const _Original_first = _First;
|
||||
|
||||
const uint64_t __bits = __double_to_bits(__d);
|
||||
|
||||
// Case distinction; exit early for the easy cases.
|
||||
if (__bits == 0) {
|
||||
const int32_t _Total_zero_length = 1 // leading zero
|
||||
+ static_cast<int32_t>(__precision != 0) // possible decimal point
|
||||
+ static_cast<int32_t>(__precision); // zeroes after decimal point
|
||||
|
||||
if (_Last - _First < _Total_zero_length) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
|
||||
*_First++ = '0';
|
||||
if (__precision > 0) {
|
||||
*_First++ = '.';
|
||||
std::memset(_First, '0', __precision);
|
||||
_First += __precision;
|
||||
}
|
||||
return { _First, errc{} };
|
||||
}
|
||||
|
||||
// Decode __bits into mantissa and exponent.
|
||||
const uint64_t __ieeeMantissa = __bits & ((1ull << __DOUBLE_MANTISSA_BITS) - 1);
|
||||
const uint32_t __ieeeExponent = static_cast<uint32_t>(__bits >> __DOUBLE_MANTISSA_BITS);
|
||||
|
||||
int32_t __e2;
|
||||
uint64_t __m2;
|
||||
if (__ieeeExponent == 0) {
|
||||
__e2 = 1 - __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS;
|
||||
__m2 = __ieeeMantissa;
|
||||
} else {
|
||||
__e2 = static_cast<int32_t>(__ieeeExponent) - __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS;
|
||||
__m2 = (1ull << __DOUBLE_MANTISSA_BITS) | __ieeeMantissa;
|
||||
}
|
||||
|
||||
bool __nonzero = false;
|
||||
if (__e2 >= -52) {
|
||||
const uint32_t __idx = __e2 < 0 ? 0 : __indexForExponent(static_cast<uint32_t>(__e2));
|
||||
const uint32_t __p10bits = __pow10BitsForIndex(__idx);
|
||||
const int32_t __len = static_cast<int32_t>(__lengthForIndex(__idx));
|
||||
for (int32_t __i = __len - 1; __i >= 0; --__i) {
|
||||
const uint32_t __j = __p10bits - __e2;
|
||||
// Temporary: __j is usually around 128, and by shifting a bit, we push it to 128 or above, which is
|
||||
// a slightly faster code path in __mulShift_mod1e9. Instead, we can just increase the multipliers.
|
||||
const uint32_t __digits = __mulShift_mod1e9(__m2 << 8, __POW10_SPLIT[__POW10_OFFSET[__idx] + __i],
|
||||
static_cast<int32_t>(__j + 8));
|
||||
if (__nonzero) {
|
||||
if (_Last - _First < 9) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
__append_nine_digits(__digits, _First);
|
||||
_First += 9;
|
||||
} else if (__digits != 0) {
|
||||
const uint32_t __olength = __decimalLength9(__digits);
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(__olength)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
__append_n_digits(__olength, __digits, _First);
|
||||
_First += __olength;
|
||||
__nonzero = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!__nonzero) {
|
||||
if (_First == _Last) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
*_First++ = '0';
|
||||
}
|
||||
if (__precision > 0) {
|
||||
if (_First == _Last) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
*_First++ = '.';
|
||||
}
|
||||
if (__e2 < 0) {
|
||||
const int32_t __idx = -__e2 / 16;
|
||||
const uint32_t __blocks = __precision / 9 + 1;
|
||||
// 0 = don't round up; 1 = round up unconditionally; 2 = round up if odd.
|
||||
int __roundUp = 0;
|
||||
uint32_t __i = 0;
|
||||
if (__blocks <= __MIN_BLOCK_2[__idx]) {
|
||||
__i = __blocks;
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(__precision)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
std::memset(_First, '0', __precision);
|
||||
_First += __precision;
|
||||
} else if (__i < __MIN_BLOCK_2[__idx]) {
|
||||
__i = __MIN_BLOCK_2[__idx];
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(9 * __i)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
std::memset(_First, '0', 9 * __i);
|
||||
_First += 9 * __i;
|
||||
}
|
||||
for (; __i < __blocks; ++__i) {
|
||||
const int32_t __j = __ADDITIONAL_BITS_2 + (-__e2 - 16 * __idx);
|
||||
const uint32_t __p = __POW10_OFFSET_2[__idx] + __i - __MIN_BLOCK_2[__idx];
|
||||
if (__p >= __POW10_OFFSET_2[__idx + 1]) {
|
||||
// If the remaining digits are all 0, then we might as well use memset.
|
||||
// No rounding required in this case.
|
||||
const uint32_t __fill = __precision - 9 * __i;
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(__fill)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
std::memset(_First, '0', __fill);
|
||||
_First += __fill;
|
||||
break;
|
||||
}
|
||||
// Temporary: __j is usually around 128, and by shifting a bit, we push it to 128 or above, which is
|
||||
// a slightly faster code path in __mulShift_mod1e9. Instead, we can just increase the multipliers.
|
||||
uint32_t __digits = __mulShift_mod1e9(__m2 << 8, __POW10_SPLIT_2[__p], __j + 8);
|
||||
if (__i < __blocks - 1) {
|
||||
if (_Last - _First < 9) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
__append_nine_digits(__digits, _First);
|
||||
_First += 9;
|
||||
} else {
|
||||
const uint32_t __maximum = __precision - 9 * __i;
|
||||
uint32_t __lastDigit = 0;
|
||||
for (uint32_t __k = 0; __k < 9 - __maximum; ++__k) {
|
||||
__lastDigit = __digits % 10;
|
||||
__digits /= 10;
|
||||
}
|
||||
if (__lastDigit != 5) {
|
||||
__roundUp = __lastDigit > 5;
|
||||
} else {
|
||||
// Is m * 10^(additionalDigits + 1) / 2^(-__e2) integer?
|
||||
const int32_t __requiredTwos = -__e2 - static_cast<int32_t>(__precision) - 1;
|
||||
const bool __trailingZeros = __requiredTwos <= 0
|
||||
|| (__requiredTwos < 60 && __multipleOfPowerOf2(__m2, static_cast<uint32_t>(__requiredTwos)));
|
||||
__roundUp = __trailingZeros ? 2 : 1;
|
||||
}
|
||||
if (__maximum > 0) {
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(__maximum)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
__append_c_digits(__maximum, __digits, _First);
|
||||
_First += __maximum;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (__roundUp != 0) {
|
||||
char* _Round = _First;
|
||||
char* _Dot = _Last;
|
||||
while (true) {
|
||||
if (_Round == _Original_first) {
|
||||
_Round[0] = '1';
|
||||
if (_Dot != _Last) {
|
||||
_Dot[0] = '0';
|
||||
_Dot[1] = '.';
|
||||
}
|
||||
if (_First == _Last) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
*_First++ = '0';
|
||||
break;
|
||||
}
|
||||
--_Round;
|
||||
const char __c = _Round[0];
|
||||
if (__c == '.') {
|
||||
_Dot = _Round;
|
||||
} else if (__c == '9') {
|
||||
_Round[0] = '0';
|
||||
__roundUp = 1;
|
||||
} else {
|
||||
if (__roundUp == 1 || __c % 2 != 0) {
|
||||
_Round[0] = __c + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(__precision)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
std::memset(_First, '0', __precision);
|
||||
_First += __precision;
|
||||
}
|
||||
return { _First, errc{} };
|
||||
}
|
||||
|
||||
[[nodiscard]] to_chars_result __d2exp_buffered_n(char* _First, char* const _Last, const double __d,
|
||||
uint32_t __precision) {
|
||||
char* const _Original_first = _First;
|
||||
|
||||
const uint64_t __bits = __double_to_bits(__d);
|
||||
|
||||
// Case distinction; exit early for the easy cases.
|
||||
if (__bits == 0) {
|
||||
const int32_t _Total_zero_length = 1 // leading zero
|
||||
+ static_cast<int32_t>(__precision != 0) // possible decimal point
|
||||
+ static_cast<int32_t>(__precision) // zeroes after decimal point
|
||||
+ 4; // "e+00"
|
||||
if (_Last - _First < _Total_zero_length) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
*_First++ = '0';
|
||||
if (__precision > 0) {
|
||||
*_First++ = '.';
|
||||
std::memset(_First, '0', __precision);
|
||||
_First += __precision;
|
||||
}
|
||||
std::memcpy(_First, "e+00", 4);
|
||||
_First += 4;
|
||||
return { _First, errc{} };
|
||||
}
|
||||
|
||||
// Decode __bits into mantissa and exponent.
|
||||
const uint64_t __ieeeMantissa = __bits & ((1ull << __DOUBLE_MANTISSA_BITS) - 1);
|
||||
const uint32_t __ieeeExponent = static_cast<uint32_t>(__bits >> __DOUBLE_MANTISSA_BITS);
|
||||
|
||||
int32_t __e2;
|
||||
uint64_t __m2;
|
||||
if (__ieeeExponent == 0) {
|
||||
__e2 = 1 - __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS;
|
||||
__m2 = __ieeeMantissa;
|
||||
} else {
|
||||
__e2 = static_cast<int32_t>(__ieeeExponent) - __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS;
|
||||
__m2 = (1ull << __DOUBLE_MANTISSA_BITS) | __ieeeMantissa;
|
||||
}
|
||||
|
||||
const bool __printDecimalPoint = __precision > 0;
|
||||
++__precision;
|
||||
uint32_t __digits = 0;
|
||||
uint32_t __printedDigits = 0;
|
||||
uint32_t __availableDigits = 0;
|
||||
int32_t __exp = 0;
|
||||
if (__e2 >= -52) {
|
||||
const uint32_t __idx = __e2 < 0 ? 0 : __indexForExponent(static_cast<uint32_t>(__e2));
|
||||
const uint32_t __p10bits = __pow10BitsForIndex(__idx);
|
||||
const int32_t __len = static_cast<int32_t>(__lengthForIndex(__idx));
|
||||
for (int32_t __i = __len - 1; __i >= 0; --__i) {
|
||||
const uint32_t __j = __p10bits - __e2;
|
||||
// Temporary: __j is usually around 128, and by shifting a bit, we push it to 128 or above, which is
|
||||
// a slightly faster code path in __mulShift_mod1e9. Instead, we can just increase the multipliers.
|
||||
__digits = __mulShift_mod1e9(__m2 << 8, __POW10_SPLIT[__POW10_OFFSET[__idx] + __i],
|
||||
static_cast<int32_t>(__j + 8));
|
||||
if (__printedDigits != 0) {
|
||||
if (__printedDigits + 9 > __precision) {
|
||||
__availableDigits = 9;
|
||||
break;
|
||||
}
|
||||
if (_Last - _First < 9) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
__append_nine_digits(__digits, _First);
|
||||
_First += 9;
|
||||
__printedDigits += 9;
|
||||
} else if (__digits != 0) {
|
||||
__availableDigits = __decimalLength9(__digits);
|
||||
__exp = __i * 9 + static_cast<int32_t>(__availableDigits) - 1;
|
||||
if (__availableDigits > __precision) {
|
||||
break;
|
||||
}
|
||||
if (__printDecimalPoint) {
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(__availableDigits + 1)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
__append_d_digits(__availableDigits, __digits, _First);
|
||||
_First += __availableDigits + 1; // +1 for decimal point
|
||||
} else {
|
||||
if (_First == _Last) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
*_First++ = static_cast<char>('0' + __digits);
|
||||
}
|
||||
__printedDigits = __availableDigits;
|
||||
__availableDigits = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (__e2 < 0 && __availableDigits == 0) {
|
||||
const int32_t __idx = -__e2 / 16;
|
||||
for (int32_t __i = __MIN_BLOCK_2[__idx]; __i < 200; ++__i) {
|
||||
const int32_t __j = __ADDITIONAL_BITS_2 + (-__e2 - 16 * __idx);
|
||||
const uint32_t __p = __POW10_OFFSET_2[__idx] + static_cast<uint32_t>(__i) - __MIN_BLOCK_2[__idx];
|
||||
// Temporary: __j is usually around 128, and by shifting a bit, we push it to 128 or above, which is
|
||||
// a slightly faster code path in __mulShift_mod1e9. Instead, we can just increase the multipliers.
|
||||
__digits = (__p >= __POW10_OFFSET_2[__idx + 1]) ? 0 : __mulShift_mod1e9(__m2 << 8, __POW10_SPLIT_2[__p], __j + 8);
|
||||
if (__printedDigits != 0) {
|
||||
if (__printedDigits + 9 > __precision) {
|
||||
__availableDigits = 9;
|
||||
break;
|
||||
}
|
||||
if (_Last - _First < 9) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
__append_nine_digits(__digits, _First);
|
||||
_First += 9;
|
||||
__printedDigits += 9;
|
||||
} else if (__digits != 0) {
|
||||
__availableDigits = __decimalLength9(__digits);
|
||||
__exp = -(__i + 1) * 9 + static_cast<int32_t>(__availableDigits) - 1;
|
||||
if (__availableDigits > __precision) {
|
||||
break;
|
||||
}
|
||||
if (__printDecimalPoint) {
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(__availableDigits + 1)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
__append_d_digits(__availableDigits, __digits, _First);
|
||||
_First += __availableDigits + 1; // +1 for decimal point
|
||||
} else {
|
||||
if (_First == _Last) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
*_First++ = static_cast<char>('0' + __digits);
|
||||
}
|
||||
__printedDigits = __availableDigits;
|
||||
__availableDigits = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t __maximum = __precision - __printedDigits;
|
||||
if (__availableDigits == 0) {
|
||||
__digits = 0;
|
||||
}
|
||||
uint32_t __lastDigit = 0;
|
||||
if (__availableDigits > __maximum) {
|
||||
for (uint32_t __k = 0; __k < __availableDigits - __maximum; ++__k) {
|
||||
__lastDigit = __digits % 10;
|
||||
__digits /= 10;
|
||||
}
|
||||
}
|
||||
// 0 = don't round up; 1 = round up unconditionally; 2 = round up if odd.
|
||||
int __roundUp = 0;
|
||||
if (__lastDigit != 5) {
|
||||
__roundUp = __lastDigit > 5;
|
||||
} else {
|
||||
// Is m * 2^__e2 * 10^(__precision + 1 - __exp) integer?
|
||||
// __precision was already increased by 1, so we don't need to write + 1 here.
|
||||
const int32_t __rexp = static_cast<int32_t>(__precision) - __exp;
|
||||
const int32_t __requiredTwos = -__e2 - __rexp;
|
||||
bool __trailingZeros = __requiredTwos <= 0
|
||||
|| (__requiredTwos < 60 && __multipleOfPowerOf2(__m2, static_cast<uint32_t>(__requiredTwos)));
|
||||
if (__rexp < 0) {
|
||||
const int32_t __requiredFives = -__rexp;
|
||||
__trailingZeros = __trailingZeros && __multipleOfPowerOf5(__m2, static_cast<uint32_t>(__requiredFives));
|
||||
}
|
||||
__roundUp = __trailingZeros ? 2 : 1;
|
||||
}
|
||||
if (__printedDigits != 0) {
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(__maximum)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
if (__digits == 0) {
|
||||
std::memset(_First, '0', __maximum);
|
||||
} else {
|
||||
__append_c_digits(__maximum, __digits, _First);
|
||||
}
|
||||
_First += __maximum;
|
||||
} else {
|
||||
if (__printDecimalPoint) {
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(__maximum + 1)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
__append_d_digits(__maximum, __digits, _First);
|
||||
_First += __maximum + 1; // +1 for decimal point
|
||||
} else {
|
||||
if (_First == _Last) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
*_First++ = static_cast<char>('0' + __digits);
|
||||
}
|
||||
}
|
||||
if (__roundUp != 0) {
|
||||
char* _Round = _First;
|
||||
while (true) {
|
||||
if (_Round == _Original_first) {
|
||||
_Round[0] = '1';
|
||||
++__exp;
|
||||
break;
|
||||
}
|
||||
--_Round;
|
||||
const char __c = _Round[0];
|
||||
if (__c == '.') {
|
||||
// Keep going.
|
||||
} else if (__c == '9') {
|
||||
_Round[0] = '0';
|
||||
__roundUp = 1;
|
||||
} else {
|
||||
if (__roundUp == 1 || __c % 2 != 0) {
|
||||
_Round[0] = __c + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char _Sign_character;
|
||||
|
||||
if (__exp < 0) {
|
||||
_Sign_character = '-';
|
||||
__exp = -__exp;
|
||||
} else {
|
||||
_Sign_character = '+';
|
||||
}
|
||||
|
||||
const int _Exponent_part_length = __exp >= 100
|
||||
? 5 // "e+NNN"
|
||||
: 4; // "e+NN"
|
||||
|
||||
if (_Last - _First < _Exponent_part_length) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
|
||||
*_First++ = 'e';
|
||||
*_First++ = _Sign_character;
|
||||
|
||||
if (__exp >= 100) {
|
||||
const int32_t __c = __exp % 10;
|
||||
std::memcpy(_First, __DIGIT_TABLE + 2 * (__exp / 10), 2);
|
||||
_First[2] = static_cast<char>('0' + __c);
|
||||
_First += 3;
|
||||
} else {
|
||||
std::memcpy(_First, __DIGIT_TABLE + 2 * __exp, 2);
|
||||
_First += 2;
|
||||
}
|
||||
|
||||
return { _First, errc{} };
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
// clang-format on
|
783
third_party/libcxx/src/ryu/d2s.cpp
vendored
Normal file
783
third_party/libcxx/src/ryu/d2s.cpp
vendored
Normal file
|
@ -0,0 +1,783 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Copyright 2018 Ulf Adams
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// Avoid formatting to keep the changes with the original code minimal.
|
||||
// clang-format off
|
||||
|
||||
#include <__assert>
|
||||
#include <__config>
|
||||
#include <charconv>
|
||||
|
||||
#include "third_party/libcxx/src/include/ryu/common.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2fixed.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2s.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2s_full_table.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2s_intrinsics.h"
|
||||
#include "third_party/libcxx/src/include/ryu/digit_table.h"
|
||||
#include "third_party/libcxx/src/include/ryu/ryu.h"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// We need a 64x128-bit multiplication and a subsequent 128-bit shift.
|
||||
// Multiplication:
|
||||
// The 64-bit factor is variable and passed in, the 128-bit factor comes
|
||||
// from a lookup table. We know that the 64-bit factor only has 55
|
||||
// significant bits (i.e., the 9 topmost bits are zeros). The 128-bit
|
||||
// factor only has 124 significant bits (i.e., the 4 topmost bits are
|
||||
// zeros).
|
||||
// Shift:
|
||||
// In principle, the multiplication result requires 55 + 124 = 179 bits to
|
||||
// represent. However, we then shift this value to the right by __j, which is
|
||||
// at least __j >= 115, so the result is guaranteed to fit into 179 - 115 = 64
|
||||
// bits. This means that we only need the topmost 64 significant bits of
|
||||
// the 64x128-bit multiplication.
|
||||
//
|
||||
// There are several ways to do this:
|
||||
// 1. Best case: the compiler exposes a 128-bit type.
|
||||
// We perform two 64x64-bit multiplications, add the higher 64 bits of the
|
||||
// lower result to the higher result, and shift by __j - 64 bits.
|
||||
//
|
||||
// We explicitly cast from 64-bit to 128-bit, so the compiler can tell
|
||||
// that these are only 64-bit inputs, and can map these to the best
|
||||
// possible sequence of assembly instructions.
|
||||
// x64 machines happen to have matching assembly instructions for
|
||||
// 64x64-bit multiplications and 128-bit shifts.
|
||||
//
|
||||
// 2. Second best case: the compiler exposes intrinsics for the x64 assembly
|
||||
// instructions mentioned in 1.
|
||||
//
|
||||
// 3. We only have 64x64 bit instructions that return the lower 64 bits of
|
||||
// the result, i.e., we have to use plain C.
|
||||
// Our inputs are less than the full width, so we have three options:
|
||||
// a. Ignore this fact and just implement the intrinsics manually.
|
||||
// b. Split both into 31-bit pieces, which guarantees no internal overflow,
|
||||
// but requires extra work upfront (unless we change the lookup table).
|
||||
// c. Split only the first factor into 31-bit pieces, which also guarantees
|
||||
// no internal overflow, but requires extra work since the intermediate
|
||||
// results are not perfectly aligned.
|
||||
#ifdef _LIBCPP_INTRINSIC128
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __mulShift(const uint64_t __m, const uint64_t* const __mul, const int32_t __j) {
|
||||
// __m is maximum 55 bits
|
||||
uint64_t __high1; // 128
|
||||
const uint64_t __low1 = __ryu_umul128(__m, __mul[1], &__high1); // 64
|
||||
uint64_t __high0; // 64
|
||||
(void) __ryu_umul128(__m, __mul[0], &__high0); // 0
|
||||
const uint64_t __sum = __high0 + __low1;
|
||||
if (__sum < __high0) {
|
||||
++__high1; // overflow into __high1
|
||||
}
|
||||
return __ryu_shiftright128(__sum, __high1, static_cast<uint32_t>(__j - 64));
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint64_t __mulShiftAll(const uint64_t __m, const uint64_t* const __mul, const int32_t __j,
|
||||
uint64_t* const __vp, uint64_t* const __vm, const uint32_t __mmShift) {
|
||||
*__vp = __mulShift(4 * __m + 2, __mul, __j);
|
||||
*__vm = __mulShift(4 * __m - 1 - __mmShift, __mul, __j);
|
||||
return __mulShift(4 * __m, __mul, __j);
|
||||
}
|
||||
|
||||
#else // ^^^ intrinsics available ^^^ / vvv intrinsics unavailable vvv
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_ALWAYS_INLINE uint64_t __mulShiftAll(uint64_t __m, const uint64_t* const __mul, const int32_t __j,
|
||||
uint64_t* const __vp, uint64_t* const __vm, const uint32_t __mmShift) { // TRANSITION, VSO-634761
|
||||
__m <<= 1;
|
||||
// __m is maximum 55 bits
|
||||
uint64_t __tmp;
|
||||
const uint64_t __lo = __ryu_umul128(__m, __mul[0], &__tmp);
|
||||
uint64_t __hi;
|
||||
const uint64_t __mid = __tmp + __ryu_umul128(__m, __mul[1], &__hi);
|
||||
__hi += __mid < __tmp; // overflow into __hi
|
||||
|
||||
const uint64_t __lo2 = __lo + __mul[0];
|
||||
const uint64_t __mid2 = __mid + __mul[1] + (__lo2 < __lo);
|
||||
const uint64_t __hi2 = __hi + (__mid2 < __mid);
|
||||
*__vp = __ryu_shiftright128(__mid2, __hi2, static_cast<uint32_t>(__j - 64 - 1));
|
||||
|
||||
if (__mmShift == 1) {
|
||||
const uint64_t __lo3 = __lo - __mul[0];
|
||||
const uint64_t __mid3 = __mid - __mul[1] - (__lo3 > __lo);
|
||||
const uint64_t __hi3 = __hi - (__mid3 > __mid);
|
||||
*__vm = __ryu_shiftright128(__mid3, __hi3, static_cast<uint32_t>(__j - 64 - 1));
|
||||
} else {
|
||||
const uint64_t __lo3 = __lo + __lo;
|
||||
const uint64_t __mid3 = __mid + __mid + (__lo3 < __lo);
|
||||
const uint64_t __hi3 = __hi + __hi + (__mid3 < __mid);
|
||||
const uint64_t __lo4 = __lo3 - __mul[0];
|
||||
const uint64_t __mid4 = __mid3 - __mul[1] - (__lo4 > __lo3);
|
||||
const uint64_t __hi4 = __hi3 - (__mid4 > __mid3);
|
||||
*__vm = __ryu_shiftright128(__mid4, __hi4, static_cast<uint32_t>(__j - 64));
|
||||
}
|
||||
|
||||
return __ryu_shiftright128(__mid, __hi, static_cast<uint32_t>(__j - 64 - 1));
|
||||
}
|
||||
|
||||
#endif // ^^^ intrinsics unavailable ^^^
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __decimalLength17(const uint64_t __v) {
|
||||
// This is slightly faster than a loop.
|
||||
// The average output length is 16.38 digits, so we check high-to-low.
|
||||
// Function precondition: __v is not an 18, 19, or 20-digit number.
|
||||
// (17 digits are sufficient for round-tripping.)
|
||||
_LIBCPP_ASSERT(__v < 100000000000000000u, "");
|
||||
if (__v >= 10000000000000000u) { return 17; }
|
||||
if (__v >= 1000000000000000u) { return 16; }
|
||||
if (__v >= 100000000000000u) { return 15; }
|
||||
if (__v >= 10000000000000u) { return 14; }
|
||||
if (__v >= 1000000000000u) { return 13; }
|
||||
if (__v >= 100000000000u) { return 12; }
|
||||
if (__v >= 10000000000u) { return 11; }
|
||||
if (__v >= 1000000000u) { return 10; }
|
||||
if (__v >= 100000000u) { return 9; }
|
||||
if (__v >= 10000000u) { return 8; }
|
||||
if (__v >= 1000000u) { return 7; }
|
||||
if (__v >= 100000u) { return 6; }
|
||||
if (__v >= 10000u) { return 5; }
|
||||
if (__v >= 1000u) { return 4; }
|
||||
if (__v >= 100u) { return 3; }
|
||||
if (__v >= 10u) { return 2; }
|
||||
return 1;
|
||||
}
|
||||
|
||||
// A floating decimal representing m * 10^e.
|
||||
struct __floating_decimal_64 {
|
||||
uint64_t __mantissa;
|
||||
int32_t __exponent;
|
||||
};
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline __floating_decimal_64 __d2d(const uint64_t __ieeeMantissa, const uint32_t __ieeeExponent) {
|
||||
int32_t __e2;
|
||||
uint64_t __m2;
|
||||
if (__ieeeExponent == 0) {
|
||||
// We subtract 2 so that the bounds computation has 2 additional bits.
|
||||
__e2 = 1 - __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS - 2;
|
||||
__m2 = __ieeeMantissa;
|
||||
} else {
|
||||
__e2 = static_cast<int32_t>(__ieeeExponent) - __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS - 2;
|
||||
__m2 = (1ull << __DOUBLE_MANTISSA_BITS) | __ieeeMantissa;
|
||||
}
|
||||
const bool __even = (__m2 & 1) == 0;
|
||||
const bool __acceptBounds = __even;
|
||||
|
||||
// Step 2: Determine the interval of valid decimal representations.
|
||||
const uint64_t __mv = 4 * __m2;
|
||||
// Implicit bool -> int conversion. True is 1, false is 0.
|
||||
const uint32_t __mmShift = __ieeeMantissa != 0 || __ieeeExponent <= 1;
|
||||
// We would compute __mp and __mm like this:
|
||||
// uint64_t __mp = 4 * __m2 + 2;
|
||||
// uint64_t __mm = __mv - 1 - __mmShift;
|
||||
|
||||
// Step 3: Convert to a decimal power base using 128-bit arithmetic.
|
||||
uint64_t __vr, __vp, __vm;
|
||||
int32_t __e10;
|
||||
bool __vmIsTrailingZeros = false;
|
||||
bool __vrIsTrailingZeros = false;
|
||||
if (__e2 >= 0) {
|
||||
// I tried special-casing __q == 0, but there was no effect on performance.
|
||||
// This expression is slightly faster than max(0, __log10Pow2(__e2) - 1).
|
||||
const uint32_t __q = __log10Pow2(__e2) - (__e2 > 3);
|
||||
__e10 = static_cast<int32_t>(__q);
|
||||
const int32_t __k = __DOUBLE_POW5_INV_BITCOUNT + __pow5bits(static_cast<int32_t>(__q)) - 1;
|
||||
const int32_t __i = -__e2 + static_cast<int32_t>(__q) + __k;
|
||||
__vr = __mulShiftAll(__m2, __DOUBLE_POW5_INV_SPLIT[__q], __i, &__vp, &__vm, __mmShift);
|
||||
if (__q <= 21) {
|
||||
// This should use __q <= 22, but I think 21 is also safe. Smaller values
|
||||
// may still be safe, but it's more difficult to reason about them.
|
||||
// Only one of __mp, __mv, and __mm can be a multiple of 5, if any.
|
||||
const uint32_t __mvMod5 = static_cast<uint32_t>(__mv) - 5 * static_cast<uint32_t>(__div5(__mv));
|
||||
if (__mvMod5 == 0) {
|
||||
__vrIsTrailingZeros = __multipleOfPowerOf5(__mv, __q);
|
||||
} else if (__acceptBounds) {
|
||||
// Same as min(__e2 + (~__mm & 1), __pow5Factor(__mm)) >= __q
|
||||
// <=> __e2 + (~__mm & 1) >= __q && __pow5Factor(__mm) >= __q
|
||||
// <=> true && __pow5Factor(__mm) >= __q, since __e2 >= __q.
|
||||
__vmIsTrailingZeros = __multipleOfPowerOf5(__mv - 1 - __mmShift, __q);
|
||||
} else {
|
||||
// Same as min(__e2 + 1, __pow5Factor(__mp)) >= __q.
|
||||
__vp -= __multipleOfPowerOf5(__mv + 2, __q);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// This expression is slightly faster than max(0, __log10Pow5(-__e2) - 1).
|
||||
const uint32_t __q = __log10Pow5(-__e2) - (-__e2 > 1);
|
||||
__e10 = static_cast<int32_t>(__q) + __e2;
|
||||
const int32_t __i = -__e2 - static_cast<int32_t>(__q);
|
||||
const int32_t __k = __pow5bits(__i) - __DOUBLE_POW5_BITCOUNT;
|
||||
const int32_t __j = static_cast<int32_t>(__q) - __k;
|
||||
__vr = __mulShiftAll(__m2, __DOUBLE_POW5_SPLIT[__i], __j, &__vp, &__vm, __mmShift);
|
||||
if (__q <= 1) {
|
||||
// {__vr,__vp,__vm} is trailing zeros if {__mv,__mp,__mm} has at least __q trailing 0 bits.
|
||||
// __mv = 4 * __m2, so it always has at least two trailing 0 bits.
|
||||
__vrIsTrailingZeros = true;
|
||||
if (__acceptBounds) {
|
||||
// __mm = __mv - 1 - __mmShift, so it has 1 trailing 0 bit iff __mmShift == 1.
|
||||
__vmIsTrailingZeros = __mmShift == 1;
|
||||
} else {
|
||||
// __mp = __mv + 2, so it always has at least one trailing 0 bit.
|
||||
--__vp;
|
||||
}
|
||||
} else if (__q < 63) { // TRANSITION(ulfjack): Use a tighter bound here.
|
||||
// We need to compute min(ntz(__mv), __pow5Factor(__mv) - __e2) >= __q - 1
|
||||
// <=> ntz(__mv) >= __q - 1 && __pow5Factor(__mv) - __e2 >= __q - 1
|
||||
// <=> ntz(__mv) >= __q - 1 (__e2 is negative and -__e2 >= __q)
|
||||
// <=> (__mv & ((1 << (__q - 1)) - 1)) == 0
|
||||
// We also need to make sure that the left shift does not overflow.
|
||||
__vrIsTrailingZeros = __multipleOfPowerOf2(__mv, __q - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Find the shortest decimal representation in the interval of valid representations.
|
||||
int32_t __removed = 0;
|
||||
uint8_t __lastRemovedDigit = 0;
|
||||
uint64_t _Output;
|
||||
// On average, we remove ~2 digits.
|
||||
if (__vmIsTrailingZeros || __vrIsTrailingZeros) {
|
||||
// General case, which happens rarely (~0.7%).
|
||||
for (;;) {
|
||||
const uint64_t __vpDiv10 = __div10(__vp);
|
||||
const uint64_t __vmDiv10 = __div10(__vm);
|
||||
if (__vpDiv10 <= __vmDiv10) {
|
||||
break;
|
||||
}
|
||||
const uint32_t __vmMod10 = static_cast<uint32_t>(__vm) - 10 * static_cast<uint32_t>(__vmDiv10);
|
||||
const uint64_t __vrDiv10 = __div10(__vr);
|
||||
const uint32_t __vrMod10 = static_cast<uint32_t>(__vr) - 10 * static_cast<uint32_t>(__vrDiv10);
|
||||
__vmIsTrailingZeros &= __vmMod10 == 0;
|
||||
__vrIsTrailingZeros &= __lastRemovedDigit == 0;
|
||||
__lastRemovedDigit = static_cast<uint8_t>(__vrMod10);
|
||||
__vr = __vrDiv10;
|
||||
__vp = __vpDiv10;
|
||||
__vm = __vmDiv10;
|
||||
++__removed;
|
||||
}
|
||||
if (__vmIsTrailingZeros) {
|
||||
for (;;) {
|
||||
const uint64_t __vmDiv10 = __div10(__vm);
|
||||
const uint32_t __vmMod10 = static_cast<uint32_t>(__vm) - 10 * static_cast<uint32_t>(__vmDiv10);
|
||||
if (__vmMod10 != 0) {
|
||||
break;
|
||||
}
|
||||
const uint64_t __vpDiv10 = __div10(__vp);
|
||||
const uint64_t __vrDiv10 = __div10(__vr);
|
||||
const uint32_t __vrMod10 = static_cast<uint32_t>(__vr) - 10 * static_cast<uint32_t>(__vrDiv10);
|
||||
__vrIsTrailingZeros &= __lastRemovedDigit == 0;
|
||||
__lastRemovedDigit = static_cast<uint8_t>(__vrMod10);
|
||||
__vr = __vrDiv10;
|
||||
__vp = __vpDiv10;
|
||||
__vm = __vmDiv10;
|
||||
++__removed;
|
||||
}
|
||||
}
|
||||
if (__vrIsTrailingZeros && __lastRemovedDigit == 5 && __vr % 2 == 0) {
|
||||
// Round even if the exact number is .....50..0.
|
||||
__lastRemovedDigit = 4;
|
||||
}
|
||||
// We need to take __vr + 1 if __vr is outside bounds or we need to round up.
|
||||
_Output = __vr + ((__vr == __vm && (!__acceptBounds || !__vmIsTrailingZeros)) || __lastRemovedDigit >= 5);
|
||||
} else {
|
||||
// Specialized for the common case (~99.3%). Percentages below are relative to this.
|
||||
bool __roundUp = false;
|
||||
const uint64_t __vpDiv100 = __div100(__vp);
|
||||
const uint64_t __vmDiv100 = __div100(__vm);
|
||||
if (__vpDiv100 > __vmDiv100) { // Optimization: remove two digits at a time (~86.2%).
|
||||
const uint64_t __vrDiv100 = __div100(__vr);
|
||||
const uint32_t __vrMod100 = static_cast<uint32_t>(__vr) - 100 * static_cast<uint32_t>(__vrDiv100);
|
||||
__roundUp = __vrMod100 >= 50;
|
||||
__vr = __vrDiv100;
|
||||
__vp = __vpDiv100;
|
||||
__vm = __vmDiv100;
|
||||
__removed += 2;
|
||||
}
|
||||
// Loop iterations below (approximately), without optimization above:
|
||||
// 0: 0.03%, 1: 13.8%, 2: 70.6%, 3: 14.0%, 4: 1.40%, 5: 0.14%, 6+: 0.02%
|
||||
// Loop iterations below (approximately), with optimization above:
|
||||
// 0: 70.6%, 1: 27.8%, 2: 1.40%, 3: 0.14%, 4+: 0.02%
|
||||
for (;;) {
|
||||
const uint64_t __vpDiv10 = __div10(__vp);
|
||||
const uint64_t __vmDiv10 = __div10(__vm);
|
||||
if (__vpDiv10 <= __vmDiv10) {
|
||||
break;
|
||||
}
|
||||
const uint64_t __vrDiv10 = __div10(__vr);
|
||||
const uint32_t __vrMod10 = static_cast<uint32_t>(__vr) - 10 * static_cast<uint32_t>(__vrDiv10);
|
||||
__roundUp = __vrMod10 >= 5;
|
||||
__vr = __vrDiv10;
|
||||
__vp = __vpDiv10;
|
||||
__vm = __vmDiv10;
|
||||
++__removed;
|
||||
}
|
||||
// We need to take __vr + 1 if __vr is outside bounds or we need to round up.
|
||||
_Output = __vr + (__vr == __vm || __roundUp);
|
||||
}
|
||||
const int32_t __exp = __e10 + __removed;
|
||||
|
||||
__floating_decimal_64 __fd;
|
||||
__fd.__exponent = __exp;
|
||||
__fd.__mantissa = _Output;
|
||||
return __fd;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline to_chars_result __to_chars(char* const _First, char* const _Last, const __floating_decimal_64 __v,
|
||||
chars_format _Fmt, const double __f) {
|
||||
// Step 5: Print the decimal representation.
|
||||
uint64_t _Output = __v.__mantissa;
|
||||
int32_t _Ryu_exponent = __v.__exponent;
|
||||
const uint32_t __olength = __decimalLength17(_Output);
|
||||
int32_t _Scientific_exponent = _Ryu_exponent + static_cast<int32_t>(__olength) - 1;
|
||||
|
||||
if (_Fmt == chars_format{}) {
|
||||
int32_t _Lower;
|
||||
int32_t _Upper;
|
||||
|
||||
if (__olength == 1) {
|
||||
// Value | Fixed | Scientific
|
||||
// 1e-3 | "0.001" | "1e-03"
|
||||
// 1e4 | "10000" | "1e+04"
|
||||
_Lower = -3;
|
||||
_Upper = 4;
|
||||
} else {
|
||||
// Value | Fixed | Scientific
|
||||
// 1234e-7 | "0.0001234" | "1.234e-04"
|
||||
// 1234e5 | "123400000" | "1.234e+08"
|
||||
_Lower = -static_cast<int32_t>(__olength + 3);
|
||||
_Upper = 5;
|
||||
}
|
||||
|
||||
if (_Lower <= _Ryu_exponent && _Ryu_exponent <= _Upper) {
|
||||
_Fmt = chars_format::fixed;
|
||||
} else {
|
||||
_Fmt = chars_format::scientific;
|
||||
}
|
||||
} else if (_Fmt == chars_format::general) {
|
||||
// C11 7.21.6.1 "The fprintf function"/8:
|
||||
// "Let P equal [...] 6 if the precision is omitted [...].
|
||||
// Then, if a conversion with style E would have an exponent of X:
|
||||
// - if P > X >= -4, the conversion is with style f [...].
|
||||
// - otherwise, the conversion is with style e [...]."
|
||||
if (-4 <= _Scientific_exponent && _Scientific_exponent < 6) {
|
||||
_Fmt = chars_format::fixed;
|
||||
} else {
|
||||
_Fmt = chars_format::scientific;
|
||||
}
|
||||
}
|
||||
|
||||
if (_Fmt == chars_format::fixed) {
|
||||
// Example: _Output == 1729, __olength == 4
|
||||
|
||||
// _Ryu_exponent | Printed | _Whole_digits | _Total_fixed_length | Notes
|
||||
// --------------|----------|---------------|----------------------|---------------------------------------
|
||||
// 2 | 172900 | 6 | _Whole_digits | Ryu can't be used for printing
|
||||
// 1 | 17290 | 5 | (sometimes adjusted) | when the trimmed digits are nonzero.
|
||||
// --------------|----------|---------------|----------------------|---------------------------------------
|
||||
// 0 | 1729 | 4 | _Whole_digits | Unified length cases.
|
||||
// --------------|----------|---------------|----------------------|---------------------------------------
|
||||
// -1 | 172.9 | 3 | __olength + 1 | This case can't happen for
|
||||
// -2 | 17.29 | 2 | | __olength == 1, but no additional
|
||||
// -3 | 1.729 | 1 | | code is needed to avoid it.
|
||||
// --------------|----------|---------------|----------------------|---------------------------------------
|
||||
// -4 | 0.1729 | 0 | 2 - _Ryu_exponent | C11 7.21.6.1 "The fprintf function"/8:
|
||||
// -5 | 0.01729 | -1 | | "If a decimal-point character appears,
|
||||
// -6 | 0.001729 | -2 | | at least one digit appears before it."
|
||||
|
||||
const int32_t _Whole_digits = static_cast<int32_t>(__olength) + _Ryu_exponent;
|
||||
|
||||
uint32_t _Total_fixed_length;
|
||||
if (_Ryu_exponent >= 0) { // cases "172900" and "1729"
|
||||
_Total_fixed_length = static_cast<uint32_t>(_Whole_digits);
|
||||
if (_Output == 1) {
|
||||
// Rounding can affect the number of digits.
|
||||
// For example, 1e23 is exactly "99999999999999991611392" which is 23 digits instead of 24.
|
||||
// We can use a lookup table to detect this and adjust the total length.
|
||||
static constexpr uint8_t _Adjustment[309] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,1,0,1,1,1,0,1,1,1,0,0,0,0,0,
|
||||
1,1,0,0,1,0,1,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,1,0,1,0,1,1,0,0,0,0,1,1,1,
|
||||
1,0,0,0,0,0,0,0,1,1,0,1,1,0,0,1,0,1,0,1,0,1,1,0,0,0,0,0,1,1,1,0,0,1,1,1,1,1,0,1,0,1,1,0,1,
|
||||
1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,1,0,0,1,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,0,0,0,1,0,0,0,1,
|
||||
0,1,0,1,0,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,1,0,1,1,1,0,0,0,1,0,1,1,1,1,1,1,0,1,0,1,1,0,0,0,1,
|
||||
1,1,0,1,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,1,1,0,0,1,1,1,0,0,0,1,0,1,0,0,0,0,0,1,1,0,
|
||||
0,1,0,1,1,1,0,0,1,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,1,0,1,0,0,0,0,0,1,1,0,1,0 };
|
||||
_Total_fixed_length -= _Adjustment[_Ryu_exponent];
|
||||
// _Whole_digits doesn't need to be adjusted because these cases won't refer to it later.
|
||||
}
|
||||
} else if (_Whole_digits > 0) { // case "17.29"
|
||||
_Total_fixed_length = __olength + 1;
|
||||
} else { // case "0.001729"
|
||||
_Total_fixed_length = static_cast<uint32_t>(2 - _Ryu_exponent);
|
||||
}
|
||||
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(_Total_fixed_length)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
|
||||
char* _Mid;
|
||||
if (_Ryu_exponent > 0) { // case "172900"
|
||||
bool _Can_use_ryu;
|
||||
|
||||
if (_Ryu_exponent > 22) { // 10^22 is the largest power of 10 that's exactly representable as a double.
|
||||
_Can_use_ryu = false;
|
||||
} else {
|
||||
// Ryu generated X: __v.__mantissa * 10^_Ryu_exponent
|
||||
// __v.__mantissa == 2^_Trailing_zero_bits * (__v.__mantissa >> _Trailing_zero_bits)
|
||||
// 10^_Ryu_exponent == 2^_Ryu_exponent * 5^_Ryu_exponent
|
||||
|
||||
// _Trailing_zero_bits is [0, 56] (aside: because 2^56 is the largest power of 2
|
||||
// with 17 decimal digits, which is double's round-trip limit.)
|
||||
// _Ryu_exponent is [1, 22].
|
||||
// Normalization adds [2, 52] (aside: at least 2 because the pre-normalized mantissa is at least 5).
|
||||
// This adds up to [3, 130], which is well below double's maximum binary exponent 1023.
|
||||
|
||||
// Therefore, we just need to consider (__v.__mantissa >> _Trailing_zero_bits) * 5^_Ryu_exponent.
|
||||
|
||||
// If that product would exceed 53 bits, then X can't be exactly represented as a double.
|
||||
// (That's not a problem for round-tripping, because X is close enough to the original double,
|
||||
// but X isn't mathematically equal to the original double.) This requires a high-precision fallback.
|
||||
|
||||
// If the product is 53 bits or smaller, then X can be exactly represented as a double (and we don't
|
||||
// need to re-synthesize it; the original double must have been X, because Ryu wouldn't produce the
|
||||
// same output for two different doubles X and Y). This allows Ryu's output to be used (zero-filled).
|
||||
|
||||
// (2^53 - 1) / 5^0 (for indexing), (2^53 - 1) / 5^1, ..., (2^53 - 1) / 5^22
|
||||
static constexpr uint64_t _Max_shifted_mantissa[23] = {
|
||||
9007199254740991u, 1801439850948198u, 360287970189639u, 72057594037927u, 14411518807585u,
|
||||
2882303761517u, 576460752303u, 115292150460u, 23058430092u, 4611686018u, 922337203u, 184467440u,
|
||||
36893488u, 7378697u, 1475739u, 295147u, 59029u, 11805u, 2361u, 472u, 94u, 18u, 3u };
|
||||
|
||||
unsigned long _Trailing_zero_bits = 0;
|
||||
#ifdef _LIBCPP_HAS_BITSCAN64
|
||||
(void) _BitScanForward64(&_Trailing_zero_bits, __v.__mantissa); // __v.__mantissa is guaranteed nonzero
|
||||
#else // ^^^ 64-bit ^^^ / vvv 32-bit vvv
|
||||
const uint32_t _Low_mantissa = static_cast<uint32_t>(__v.__mantissa);
|
||||
if (_Low_mantissa != 0) {
|
||||
(void) _BitScanForward(&_Trailing_zero_bits, _Low_mantissa);
|
||||
} else {
|
||||
const uint32_t _High_mantissa = static_cast<uint32_t>(__v.__mantissa >> 32); // nonzero here
|
||||
(void) _BitScanForward(&_Trailing_zero_bits, _High_mantissa);
|
||||
_Trailing_zero_bits += 32;
|
||||
}
|
||||
#endif // ^^^ 32-bit ^^^
|
||||
const uint64_t _Shifted_mantissa = __v.__mantissa >> _Trailing_zero_bits;
|
||||
_Can_use_ryu = _Shifted_mantissa <= _Max_shifted_mantissa[_Ryu_exponent];
|
||||
}
|
||||
|
||||
if (!_Can_use_ryu) {
|
||||
// Print the integer exactly.
|
||||
// Performance note: This will redundantly perform bounds checking.
|
||||
// Performance note: This will redundantly decompose the IEEE representation.
|
||||
return __d2fixed_buffered_n(_First, _Last, __f, 0);
|
||||
}
|
||||
|
||||
// _Can_use_ryu
|
||||
// Print the decimal digits, left-aligned within [_First, _First + _Total_fixed_length).
|
||||
_Mid = _First + __olength;
|
||||
} else { // cases "1729", "17.29", and "0.001729"
|
||||
// Print the decimal digits, right-aligned within [_First, _First + _Total_fixed_length).
|
||||
_Mid = _First + _Total_fixed_length;
|
||||
}
|
||||
|
||||
// We prefer 32-bit operations, even on 64-bit platforms.
|
||||
// We have at most 17 digits, and uint32_t can store 9 digits.
|
||||
// If _Output doesn't fit into uint32_t, we cut off 8 digits,
|
||||
// so the rest will fit into uint32_t.
|
||||
if ((_Output >> 32) != 0) {
|
||||
// Expensive 64-bit division.
|
||||
const uint64_t __q = __div1e8(_Output);
|
||||
uint32_t __output2 = static_cast<uint32_t>(_Output - 100000000 * __q);
|
||||
_Output = __q;
|
||||
|
||||
const uint32_t __c = __output2 % 10000;
|
||||
__output2 /= 10000;
|
||||
const uint32_t __d = __output2 % 10000;
|
||||
const uint32_t __c0 = (__c % 100) << 1;
|
||||
const uint32_t __c1 = (__c / 100) << 1;
|
||||
const uint32_t __d0 = (__d % 100) << 1;
|
||||
const uint32_t __d1 = (__d / 100) << 1;
|
||||
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c0, 2);
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c1, 2);
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __d0, 2);
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __d1, 2);
|
||||
}
|
||||
uint32_t __output2 = static_cast<uint32_t>(_Output);
|
||||
while (__output2 >= 10000) {
|
||||
#ifdef __clang__ // TRANSITION, LLVM-38217
|
||||
const uint32_t __c = __output2 - 10000 * (__output2 / 10000);
|
||||
#else
|
||||
const uint32_t __c = __output2 % 10000;
|
||||
#endif
|
||||
__output2 /= 10000;
|
||||
const uint32_t __c0 = (__c % 100) << 1;
|
||||
const uint32_t __c1 = (__c / 100) << 1;
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c0, 2);
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c1, 2);
|
||||
}
|
||||
if (__output2 >= 100) {
|
||||
const uint32_t __c = (__output2 % 100) << 1;
|
||||
__output2 /= 100;
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2);
|
||||
}
|
||||
if (__output2 >= 10) {
|
||||
const uint32_t __c = __output2 << 1;
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2);
|
||||
} else {
|
||||
*--_Mid = static_cast<char>('0' + __output2);
|
||||
}
|
||||
|
||||
if (_Ryu_exponent > 0) { // case "172900" with _Can_use_ryu
|
||||
// Performance note: it might be more efficient to do this immediately after setting _Mid.
|
||||
std::memset(_First + __olength, '0', static_cast<size_t>(_Ryu_exponent));
|
||||
} else if (_Ryu_exponent == 0) { // case "1729"
|
||||
// Done!
|
||||
} else if (_Whole_digits > 0) { // case "17.29"
|
||||
// Performance note: moving digits might not be optimal.
|
||||
std::memmove(_First, _First + 1, static_cast<size_t>(_Whole_digits));
|
||||
_First[_Whole_digits] = '.';
|
||||
} else { // case "0.001729"
|
||||
// Performance note: a larger memset() followed by overwriting '.' might be more efficient.
|
||||
_First[0] = '0';
|
||||
_First[1] = '.';
|
||||
std::memset(_First + 2, '0', static_cast<size_t>(-_Whole_digits));
|
||||
}
|
||||
|
||||
return { _First + _Total_fixed_length, errc{} };
|
||||
}
|
||||
|
||||
const uint32_t _Total_scientific_length = __olength + (__olength > 1) // digits + possible decimal point
|
||||
+ (-100 < _Scientific_exponent && _Scientific_exponent < 100 ? 4 : 5); // + scientific exponent
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(_Total_scientific_length)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
char* const __result = _First;
|
||||
|
||||
// Print the decimal digits.
|
||||
uint32_t __i = 0;
|
||||
// We prefer 32-bit operations, even on 64-bit platforms.
|
||||
// We have at most 17 digits, and uint32_t can store 9 digits.
|
||||
// If _Output doesn't fit into uint32_t, we cut off 8 digits,
|
||||
// so the rest will fit into uint32_t.
|
||||
if ((_Output >> 32) != 0) {
|
||||
// Expensive 64-bit division.
|
||||
const uint64_t __q = __div1e8(_Output);
|
||||
uint32_t __output2 = static_cast<uint32_t>(_Output) - 100000000 * static_cast<uint32_t>(__q);
|
||||
_Output = __q;
|
||||
|
||||
const uint32_t __c = __output2 % 10000;
|
||||
__output2 /= 10000;
|
||||
const uint32_t __d = __output2 % 10000;
|
||||
const uint32_t __c0 = (__c % 100) << 1;
|
||||
const uint32_t __c1 = (__c / 100) << 1;
|
||||
const uint32_t __d0 = (__d % 100) << 1;
|
||||
const uint32_t __d1 = (__d / 100) << 1;
|
||||
std::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c0, 2);
|
||||
std::memcpy(__result + __olength - __i - 3, __DIGIT_TABLE + __c1, 2);
|
||||
std::memcpy(__result + __olength - __i - 5, __DIGIT_TABLE + __d0, 2);
|
||||
std::memcpy(__result + __olength - __i - 7, __DIGIT_TABLE + __d1, 2);
|
||||
__i += 8;
|
||||
}
|
||||
uint32_t __output2 = static_cast<uint32_t>(_Output);
|
||||
while (__output2 >= 10000) {
|
||||
#ifdef __clang__ // TRANSITION, LLVM-38217
|
||||
const uint32_t __c = __output2 - 10000 * (__output2 / 10000);
|
||||
#else
|
||||
const uint32_t __c = __output2 % 10000;
|
||||
#endif
|
||||
__output2 /= 10000;
|
||||
const uint32_t __c0 = (__c % 100) << 1;
|
||||
const uint32_t __c1 = (__c / 100) << 1;
|
||||
std::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c0, 2);
|
||||
std::memcpy(__result + __olength - __i - 3, __DIGIT_TABLE + __c1, 2);
|
||||
__i += 4;
|
||||
}
|
||||
if (__output2 >= 100) {
|
||||
const uint32_t __c = (__output2 % 100) << 1;
|
||||
__output2 /= 100;
|
||||
std::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c, 2);
|
||||
__i += 2;
|
||||
}
|
||||
if (__output2 >= 10) {
|
||||
const uint32_t __c = __output2 << 1;
|
||||
// We can't use memcpy here: the decimal dot goes between these two digits.
|
||||
__result[2] = __DIGIT_TABLE[__c + 1];
|
||||
__result[0] = __DIGIT_TABLE[__c];
|
||||
} else {
|
||||
__result[0] = static_cast<char>('0' + __output2);
|
||||
}
|
||||
|
||||
// Print decimal point if needed.
|
||||
uint32_t __index;
|
||||
if (__olength > 1) {
|
||||
__result[1] = '.';
|
||||
__index = __olength + 1;
|
||||
} else {
|
||||
__index = 1;
|
||||
}
|
||||
|
||||
// Print the exponent.
|
||||
__result[__index++] = 'e';
|
||||
if (_Scientific_exponent < 0) {
|
||||
__result[__index++] = '-';
|
||||
_Scientific_exponent = -_Scientific_exponent;
|
||||
} else {
|
||||
__result[__index++] = '+';
|
||||
}
|
||||
|
||||
if (_Scientific_exponent >= 100) {
|
||||
const int32_t __c = _Scientific_exponent % 10;
|
||||
std::memcpy(__result + __index, __DIGIT_TABLE + 2 * (_Scientific_exponent / 10), 2);
|
||||
__result[__index + 2] = static_cast<char>('0' + __c);
|
||||
__index += 3;
|
||||
} else {
|
||||
std::memcpy(__result + __index, __DIGIT_TABLE + 2 * _Scientific_exponent, 2);
|
||||
__index += 2;
|
||||
}
|
||||
|
||||
return { _First + _Total_scientific_length, errc{} };
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline bool __d2d_small_int(const uint64_t __ieeeMantissa, const uint32_t __ieeeExponent,
|
||||
__floating_decimal_64* const __v) {
|
||||
const uint64_t __m2 = (1ull << __DOUBLE_MANTISSA_BITS) | __ieeeMantissa;
|
||||
const int32_t __e2 = static_cast<int32_t>(__ieeeExponent) - __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS;
|
||||
|
||||
if (__e2 > 0) {
|
||||
// f = __m2 * 2^__e2 >= 2^53 is an integer.
|
||||
// Ignore this case for now.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (__e2 < -52) {
|
||||
// f < 1.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Since 2^52 <= __m2 < 2^53 and 0 <= -__e2 <= 52: 1 <= f = __m2 / 2^-__e2 < 2^53.
|
||||
// Test if the lower -__e2 bits of the significand are 0, i.e. whether the fraction is 0.
|
||||
const uint64_t __mask = (1ull << -__e2) - 1;
|
||||
const uint64_t __fraction = __m2 & __mask;
|
||||
if (__fraction != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// f is an integer in the range [1, 2^53).
|
||||
// Note: __mantissa might contain trailing (decimal) 0's.
|
||||
// Note: since 2^53 < 10^16, there is no need to adjust __decimalLength17().
|
||||
__v->__mantissa = __m2 >> -__e2;
|
||||
__v->__exponent = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] to_chars_result __d2s_buffered_n(char* const _First, char* const _Last, const double __f,
|
||||
const chars_format _Fmt) {
|
||||
|
||||
// Step 1: Decode the floating-point number, and unify normalized and subnormal cases.
|
||||
const uint64_t __bits = __double_to_bits(__f);
|
||||
|
||||
// Case distinction; exit early for the easy cases.
|
||||
if (__bits == 0) {
|
||||
if (_Fmt == chars_format::scientific) {
|
||||
if (_Last - _First < 5) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
|
||||
std::memcpy(_First, "0e+00", 5);
|
||||
|
||||
return { _First + 5, errc{} };
|
||||
}
|
||||
|
||||
// Print "0" for chars_format::fixed, chars_format::general, and chars_format{}.
|
||||
if (_First == _Last) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
|
||||
*_First = '0';
|
||||
|
||||
return { _First + 1, errc{} };
|
||||
}
|
||||
|
||||
// Decode __bits into mantissa and exponent.
|
||||
const uint64_t __ieeeMantissa = __bits & ((1ull << __DOUBLE_MANTISSA_BITS) - 1);
|
||||
const uint32_t __ieeeExponent = static_cast<uint32_t>(__bits >> __DOUBLE_MANTISSA_BITS);
|
||||
|
||||
if (_Fmt == chars_format::fixed) {
|
||||
// const uint64_t _Mantissa2 = __ieeeMantissa | (1ull << __DOUBLE_MANTISSA_BITS); // restore implicit bit
|
||||
const int32_t _Exponent2 = static_cast<int32_t>(__ieeeExponent)
|
||||
- __DOUBLE_BIAS - __DOUBLE_MANTISSA_BITS; // bias and normalization
|
||||
|
||||
// Normal values are equal to _Mantissa2 * 2^_Exponent2.
|
||||
// (Subnormals are different, but they'll be rejected by the _Exponent2 test here, so they can be ignored.)
|
||||
|
||||
// For nonzero integers, _Exponent2 >= -52. (The minimum value occurs when _Mantissa2 * 2^_Exponent2 is 1.
|
||||
// In that case, _Mantissa2 is the implicit 1 bit followed by 52 zeros, so _Exponent2 is -52 to shift away
|
||||
// the zeros.) The dense range of exactly representable integers has negative or zero exponents
|
||||
// (as positive exponents make the range non-dense). For that dense range, Ryu will always be used:
|
||||
// every digit is necessary to uniquely identify the value, so Ryu must print them all.
|
||||
|
||||
// Positive exponents are the non-dense range of exactly representable integers. This contains all of the values
|
||||
// for which Ryu can't be used (and a few Ryu-friendly values). We can save time by detecting positive
|
||||
// exponents here and skipping Ryu. Calling __d2fixed_buffered_n() with precision 0 is valid for all integers
|
||||
// (so it's okay if we call it with a Ryu-friendly value).
|
||||
if (_Exponent2 > 0) {
|
||||
return __d2fixed_buffered_n(_First, _Last, __f, 0);
|
||||
}
|
||||
}
|
||||
|
||||
__floating_decimal_64 __v;
|
||||
const bool __isSmallInt = __d2d_small_int(__ieeeMantissa, __ieeeExponent, &__v);
|
||||
if (__isSmallInt) {
|
||||
// For small integers in the range [1, 2^53), __v.__mantissa might contain trailing (decimal) zeros.
|
||||
// For scientific notation we need to move these zeros into the exponent.
|
||||
// (This is not needed for fixed-point notation, so it might be beneficial to trim
|
||||
// trailing zeros in __to_chars only if needed - once fixed-point notation output is implemented.)
|
||||
for (;;) {
|
||||
const uint64_t __q = __div10(__v.__mantissa);
|
||||
const uint32_t __r = static_cast<uint32_t>(__v.__mantissa) - 10 * static_cast<uint32_t>(__q);
|
||||
if (__r != 0) {
|
||||
break;
|
||||
}
|
||||
__v.__mantissa = __q;
|
||||
++__v.__exponent;
|
||||
}
|
||||
} else {
|
||||
__v = __d2d(__ieeeMantissa, __ieeeExponent);
|
||||
}
|
||||
|
||||
return __to_chars(_First, _Last, __v, _Fmt, __f);
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
// clang-format on
|
716
third_party/libcxx/src/ryu/f2s.cpp
vendored
Normal file
716
third_party/libcxx/src/ryu/f2s.cpp
vendored
Normal file
|
@ -0,0 +1,716 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Copyright 2018 Ulf Adams
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
// obtaining a copy of the software and accompanying documentation covered by
|
||||
// this license (the "Software") to use, reproduce, display, distribute,
|
||||
// execute, and transmit the Software, and to prepare derivative works of the
|
||||
// Software, and to permit third-parties to whom the Software is furnished to
|
||||
// do so, all subject to the following:
|
||||
|
||||
// The copyright notices in the Software and this entire statement, including
|
||||
// the above license grant, this restriction and the following disclaimer,
|
||||
// must be included in all copies of the Software, in whole or in part, and
|
||||
// all derivative works of the Software, unless such copies or derivative
|
||||
// works are solely in the form of machine-executable object code generated by
|
||||
// a source language processor.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// Avoid formatting to keep the changes with the original code minimal.
|
||||
// clang-format off
|
||||
|
||||
#include <__assert>
|
||||
#include <__config>
|
||||
#include <charconv>
|
||||
|
||||
#include "third_party/libcxx/src/include/ryu/common.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2fixed.h"
|
||||
#include "third_party/libcxx/src/include/ryu/d2s_intrinsics.h"
|
||||
#include "third_party/libcxx/src/include/ryu/digit_table.h"
|
||||
#include "third_party/libcxx/src/include/ryu/f2s.h"
|
||||
#include "third_party/libcxx/src/include/ryu/ryu.h"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
inline constexpr int __FLOAT_MANTISSA_BITS = 23;
|
||||
inline constexpr int __FLOAT_EXPONENT_BITS = 8;
|
||||
inline constexpr int __FLOAT_BIAS = 127;
|
||||
|
||||
inline constexpr int __FLOAT_POW5_INV_BITCOUNT = 59;
|
||||
inline constexpr uint64_t __FLOAT_POW5_INV_SPLIT[31] = {
|
||||
576460752303423489u, 461168601842738791u, 368934881474191033u, 295147905179352826u,
|
||||
472236648286964522u, 377789318629571618u, 302231454903657294u, 483570327845851670u,
|
||||
386856262276681336u, 309485009821345069u, 495176015714152110u, 396140812571321688u,
|
||||
316912650057057351u, 507060240091291761u, 405648192073033409u, 324518553658426727u,
|
||||
519229685853482763u, 415383748682786211u, 332306998946228969u, 531691198313966350u,
|
||||
425352958651173080u, 340282366920938464u, 544451787073501542u, 435561429658801234u,
|
||||
348449143727040987u, 557518629963265579u, 446014903970612463u, 356811923176489971u,
|
||||
570899077082383953u, 456719261665907162u, 365375409332725730u
|
||||
};
|
||||
inline constexpr int __FLOAT_POW5_BITCOUNT = 61;
|
||||
inline constexpr uint64_t __FLOAT_POW5_SPLIT[47] = {
|
||||
1152921504606846976u, 1441151880758558720u, 1801439850948198400u, 2251799813685248000u,
|
||||
1407374883553280000u, 1759218604441600000u, 2199023255552000000u, 1374389534720000000u,
|
||||
1717986918400000000u, 2147483648000000000u, 1342177280000000000u, 1677721600000000000u,
|
||||
2097152000000000000u, 1310720000000000000u, 1638400000000000000u, 2048000000000000000u,
|
||||
1280000000000000000u, 1600000000000000000u, 2000000000000000000u, 1250000000000000000u,
|
||||
1562500000000000000u, 1953125000000000000u, 1220703125000000000u, 1525878906250000000u,
|
||||
1907348632812500000u, 1192092895507812500u, 1490116119384765625u, 1862645149230957031u,
|
||||
1164153218269348144u, 1455191522836685180u, 1818989403545856475u, 2273736754432320594u,
|
||||
1421085471520200371u, 1776356839400250464u, 2220446049250313080u, 1387778780781445675u,
|
||||
1734723475976807094u, 2168404344971008868u, 1355252715606880542u, 1694065894508600678u,
|
||||
2117582368135750847u, 1323488980084844279u, 1654361225106055349u, 2067951531382569187u,
|
||||
1292469707114105741u, 1615587133892632177u, 2019483917365790221u
|
||||
};
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __pow5Factor(uint32_t __value) {
|
||||
uint32_t __count = 0;
|
||||
for (;;) {
|
||||
_LIBCPP_ASSERT(__value != 0, "");
|
||||
const uint32_t __q = __value / 5;
|
||||
const uint32_t __r = __value % 5;
|
||||
if (__r != 0) {
|
||||
break;
|
||||
}
|
||||
__value = __q;
|
||||
++__count;
|
||||
}
|
||||
return __count;
|
||||
}
|
||||
|
||||
// Returns true if __value is divisible by 5^__p.
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline bool __multipleOfPowerOf5(const uint32_t __value, const uint32_t __p) {
|
||||
return __pow5Factor(__value) >= __p;
|
||||
}
|
||||
|
||||
// Returns true if __value is divisible by 2^__p.
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline bool __multipleOfPowerOf2(const uint32_t __value, const uint32_t __p) {
|
||||
_LIBCPP_ASSERT(__value != 0, "");
|
||||
_LIBCPP_ASSERT(__p < 32, "");
|
||||
// __builtin_ctz doesn't appear to be faster here.
|
||||
return (__value & ((1u << __p) - 1)) == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __mulShift(const uint32_t __m, const uint64_t __factor, const int32_t __shift) {
|
||||
_LIBCPP_ASSERT(__shift > 32, "");
|
||||
|
||||
// The casts here help MSVC to avoid calls to the __allmul library
|
||||
// function.
|
||||
const uint32_t __factorLo = static_cast<uint32_t>(__factor);
|
||||
const uint32_t __factorHi = static_cast<uint32_t>(__factor >> 32);
|
||||
const uint64_t __bits0 = static_cast<uint64_t>(__m) * __factorLo;
|
||||
const uint64_t __bits1 = static_cast<uint64_t>(__m) * __factorHi;
|
||||
|
||||
#ifndef _LIBCPP_64_BIT
|
||||
// On 32-bit platforms we can avoid a 64-bit shift-right since we only
|
||||
// need the upper 32 bits of the result and the shift value is > 32.
|
||||
const uint32_t __bits0Hi = static_cast<uint32_t>(__bits0 >> 32);
|
||||
uint32_t __bits1Lo = static_cast<uint32_t>(__bits1);
|
||||
uint32_t __bits1Hi = static_cast<uint32_t>(__bits1 >> 32);
|
||||
__bits1Lo += __bits0Hi;
|
||||
__bits1Hi += (__bits1Lo < __bits0Hi);
|
||||
const int32_t __s = __shift - 32;
|
||||
return (__bits1Hi << (32 - __s)) | (__bits1Lo >> __s);
|
||||
#else // ^^^ 32-bit ^^^ / vvv 64-bit vvv
|
||||
const uint64_t __sum = (__bits0 >> 32) + __bits1;
|
||||
const uint64_t __shiftedSum = __sum >> (__shift - 32);
|
||||
_LIBCPP_ASSERT(__shiftedSum <= UINT32_MAX, "");
|
||||
return static_cast<uint32_t>(__shiftedSum);
|
||||
#endif // ^^^ 64-bit ^^^
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __mulPow5InvDivPow2(const uint32_t __m, const uint32_t __q, const int32_t __j) {
|
||||
return __mulShift(__m, __FLOAT_POW5_INV_SPLIT[__q], __j);
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline uint32_t __mulPow5divPow2(const uint32_t __m, const uint32_t __i, const int32_t __j) {
|
||||
return __mulShift(__m, __FLOAT_POW5_SPLIT[__i], __j);
|
||||
}
|
||||
|
||||
// A floating decimal representing m * 10^e.
|
||||
struct __floating_decimal_32 {
|
||||
uint32_t __mantissa;
|
||||
int32_t __exponent;
|
||||
};
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline __floating_decimal_32 __f2d(const uint32_t __ieeeMantissa, const uint32_t __ieeeExponent) {
|
||||
int32_t __e2;
|
||||
uint32_t __m2;
|
||||
if (__ieeeExponent == 0) {
|
||||
// We subtract 2 so that the bounds computation has 2 additional bits.
|
||||
__e2 = 1 - __FLOAT_BIAS - __FLOAT_MANTISSA_BITS - 2;
|
||||
__m2 = __ieeeMantissa;
|
||||
} else {
|
||||
__e2 = static_cast<int32_t>(__ieeeExponent) - __FLOAT_BIAS - __FLOAT_MANTISSA_BITS - 2;
|
||||
__m2 = (1u << __FLOAT_MANTISSA_BITS) | __ieeeMantissa;
|
||||
}
|
||||
const bool __even = (__m2 & 1) == 0;
|
||||
const bool __acceptBounds = __even;
|
||||
|
||||
// Step 2: Determine the interval of valid decimal representations.
|
||||
const uint32_t __mv = 4 * __m2;
|
||||
const uint32_t __mp = 4 * __m2 + 2;
|
||||
// Implicit bool -> int conversion. True is 1, false is 0.
|
||||
const uint32_t __mmShift = __ieeeMantissa != 0 || __ieeeExponent <= 1;
|
||||
const uint32_t __mm = 4 * __m2 - 1 - __mmShift;
|
||||
|
||||
// Step 3: Convert to a decimal power base using 64-bit arithmetic.
|
||||
uint32_t __vr, __vp, __vm;
|
||||
int32_t __e10;
|
||||
bool __vmIsTrailingZeros = false;
|
||||
bool __vrIsTrailingZeros = false;
|
||||
uint8_t __lastRemovedDigit = 0;
|
||||
if (__e2 >= 0) {
|
||||
const uint32_t __q = __log10Pow2(__e2);
|
||||
__e10 = static_cast<int32_t>(__q);
|
||||
const int32_t __k = __FLOAT_POW5_INV_BITCOUNT + __pow5bits(static_cast<int32_t>(__q)) - 1;
|
||||
const int32_t __i = -__e2 + static_cast<int32_t>(__q) + __k;
|
||||
__vr = __mulPow5InvDivPow2(__mv, __q, __i);
|
||||
__vp = __mulPow5InvDivPow2(__mp, __q, __i);
|
||||
__vm = __mulPow5InvDivPow2(__mm, __q, __i);
|
||||
if (__q != 0 && (__vp - 1) / 10 <= __vm / 10) {
|
||||
// We need to know one removed digit even if we are not going to loop below. We could use
|
||||
// __q = X - 1 above, except that would require 33 bits for the result, and we've found that
|
||||
// 32-bit arithmetic is faster even on 64-bit machines.
|
||||
const int32_t __l = __FLOAT_POW5_INV_BITCOUNT + __pow5bits(static_cast<int32_t>(__q - 1)) - 1;
|
||||
__lastRemovedDigit = static_cast<uint8_t>(__mulPow5InvDivPow2(__mv, __q - 1,
|
||||
-__e2 + static_cast<int32_t>(__q) - 1 + __l) % 10);
|
||||
}
|
||||
if (__q <= 9) {
|
||||
// The largest power of 5 that fits in 24 bits is 5^10, but __q <= 9 seems to be safe as well.
|
||||
// Only one of __mp, __mv, and __mm can be a multiple of 5, if any.
|
||||
if (__mv % 5 == 0) {
|
||||
__vrIsTrailingZeros = __multipleOfPowerOf5(__mv, __q);
|
||||
} else if (__acceptBounds) {
|
||||
__vmIsTrailingZeros = __multipleOfPowerOf5(__mm, __q);
|
||||
} else {
|
||||
__vp -= __multipleOfPowerOf5(__mp, __q);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const uint32_t __q = __log10Pow5(-__e2);
|
||||
__e10 = static_cast<int32_t>(__q) + __e2;
|
||||
const int32_t __i = -__e2 - static_cast<int32_t>(__q);
|
||||
const int32_t __k = __pow5bits(__i) - __FLOAT_POW5_BITCOUNT;
|
||||
int32_t __j = static_cast<int32_t>(__q) - __k;
|
||||
__vr = __mulPow5divPow2(__mv, static_cast<uint32_t>(__i), __j);
|
||||
__vp = __mulPow5divPow2(__mp, static_cast<uint32_t>(__i), __j);
|
||||
__vm = __mulPow5divPow2(__mm, static_cast<uint32_t>(__i), __j);
|
||||
if (__q != 0 && (__vp - 1) / 10 <= __vm / 10) {
|
||||
__j = static_cast<int32_t>(__q) - 1 - (__pow5bits(__i + 1) - __FLOAT_POW5_BITCOUNT);
|
||||
__lastRemovedDigit = static_cast<uint8_t>(__mulPow5divPow2(__mv, static_cast<uint32_t>(__i + 1), __j) % 10);
|
||||
}
|
||||
if (__q <= 1) {
|
||||
// {__vr,__vp,__vm} is trailing zeros if {__mv,__mp,__mm} has at least __q trailing 0 bits.
|
||||
// __mv = 4 * __m2, so it always has at least two trailing 0 bits.
|
||||
__vrIsTrailingZeros = true;
|
||||
if (__acceptBounds) {
|
||||
// __mm = __mv - 1 - __mmShift, so it has 1 trailing 0 bit iff __mmShift == 1.
|
||||
__vmIsTrailingZeros = __mmShift == 1;
|
||||
} else {
|
||||
// __mp = __mv + 2, so it always has at least one trailing 0 bit.
|
||||
--__vp;
|
||||
}
|
||||
} else if (__q < 31) { // TRANSITION(ulfjack): Use a tighter bound here.
|
||||
__vrIsTrailingZeros = __multipleOfPowerOf2(__mv, __q - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: Find the shortest decimal representation in the interval of valid representations.
|
||||
int32_t __removed = 0;
|
||||
uint32_t _Output;
|
||||
if (__vmIsTrailingZeros || __vrIsTrailingZeros) {
|
||||
// General case, which happens rarely (~4.0%).
|
||||
while (__vp / 10 > __vm / 10) {
|
||||
#ifdef __clang__ // TRANSITION, LLVM-23106
|
||||
__vmIsTrailingZeros &= __vm - (__vm / 10) * 10 == 0;
|
||||
#else
|
||||
__vmIsTrailingZeros &= __vm % 10 == 0;
|
||||
#endif
|
||||
__vrIsTrailingZeros &= __lastRemovedDigit == 0;
|
||||
__lastRemovedDigit = static_cast<uint8_t>(__vr % 10);
|
||||
__vr /= 10;
|
||||
__vp /= 10;
|
||||
__vm /= 10;
|
||||
++__removed;
|
||||
}
|
||||
if (__vmIsTrailingZeros) {
|
||||
while (__vm % 10 == 0) {
|
||||
__vrIsTrailingZeros &= __lastRemovedDigit == 0;
|
||||
__lastRemovedDigit = static_cast<uint8_t>(__vr % 10);
|
||||
__vr /= 10;
|
||||
__vp /= 10;
|
||||
__vm /= 10;
|
||||
++__removed;
|
||||
}
|
||||
}
|
||||
if (__vrIsTrailingZeros && __lastRemovedDigit == 5 && __vr % 2 == 0) {
|
||||
// Round even if the exact number is .....50..0.
|
||||
__lastRemovedDigit = 4;
|
||||
}
|
||||
// We need to take __vr + 1 if __vr is outside bounds or we need to round up.
|
||||
_Output = __vr + ((__vr == __vm && (!__acceptBounds || !__vmIsTrailingZeros)) || __lastRemovedDigit >= 5);
|
||||
} else {
|
||||
// Specialized for the common case (~96.0%). Percentages below are relative to this.
|
||||
// Loop iterations below (approximately):
|
||||
// 0: 13.6%, 1: 70.7%, 2: 14.1%, 3: 1.39%, 4: 0.14%, 5+: 0.01%
|
||||
while (__vp / 10 > __vm / 10) {
|
||||
__lastRemovedDigit = static_cast<uint8_t>(__vr % 10);
|
||||
__vr /= 10;
|
||||
__vp /= 10;
|
||||
__vm /= 10;
|
||||
++__removed;
|
||||
}
|
||||
// We need to take __vr + 1 if __vr is outside bounds or we need to round up.
|
||||
_Output = __vr + (__vr == __vm || __lastRemovedDigit >= 5);
|
||||
}
|
||||
const int32_t __exp = __e10 + __removed;
|
||||
|
||||
__floating_decimal_32 __fd;
|
||||
__fd.__exponent = __exp;
|
||||
__fd.__mantissa = _Output;
|
||||
return __fd;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline to_chars_result _Large_integer_to_chars(char* const _First, char* const _Last,
|
||||
const uint32_t _Mantissa2, const int32_t _Exponent2) {
|
||||
|
||||
// Print the integer _Mantissa2 * 2^_Exponent2 exactly.
|
||||
|
||||
// For nonzero integers, _Exponent2 >= -23. (The minimum value occurs when _Mantissa2 * 2^_Exponent2 is 1.
|
||||
// In that case, _Mantissa2 is the implicit 1 bit followed by 23 zeros, so _Exponent2 is -23 to shift away
|
||||
// the zeros.) The dense range of exactly representable integers has negative or zero exponents
|
||||
// (as positive exponents make the range non-dense). For that dense range, Ryu will always be used:
|
||||
// every digit is necessary to uniquely identify the value, so Ryu must print them all.
|
||||
|
||||
// Positive exponents are the non-dense range of exactly representable integers.
|
||||
// This contains all of the values for which Ryu can't be used (and a few Ryu-friendly values).
|
||||
|
||||
// Performance note: Long division appears to be faster than losslessly widening float to double and calling
|
||||
// __d2fixed_buffered_n(). If __f2fixed_buffered_n() is implemented, it might be faster than long division.
|
||||
|
||||
_LIBCPP_ASSERT(_Exponent2 > 0, "");
|
||||
_LIBCPP_ASSERT(_Exponent2 <= 104, ""); // because __ieeeExponent <= 254
|
||||
|
||||
// Manually represent _Mantissa2 * 2^_Exponent2 as a large integer. _Mantissa2 is always 24 bits
|
||||
// (due to the implicit bit), while _Exponent2 indicates a shift of at most 104 bits.
|
||||
// 24 + 104 equals 128 equals 4 * 32, so we need exactly 4 32-bit elements.
|
||||
// We use a little-endian representation, visualized like this:
|
||||
|
||||
// << left shift <<
|
||||
// most significant
|
||||
// _Data[3] _Data[2] _Data[1] _Data[0]
|
||||
// least significant
|
||||
// >> right shift >>
|
||||
|
||||
constexpr uint32_t _Data_size = 4;
|
||||
uint32_t _Data[_Data_size]{};
|
||||
|
||||
// _Maxidx is the index of the most significant nonzero element.
|
||||
uint32_t _Maxidx = ((24 + static_cast<uint32_t>(_Exponent2) + 31) / 32) - 1;
|
||||
_LIBCPP_ASSERT(_Maxidx < _Data_size, "");
|
||||
|
||||
const uint32_t _Bit_shift = static_cast<uint32_t>(_Exponent2) % 32;
|
||||
if (_Bit_shift <= 8) { // _Mantissa2's 24 bits don't cross an element boundary
|
||||
_Data[_Maxidx] = _Mantissa2 << _Bit_shift;
|
||||
} else { // _Mantissa2's 24 bits cross an element boundary
|
||||
_Data[_Maxidx - 1] = _Mantissa2 << _Bit_shift;
|
||||
_Data[_Maxidx] = _Mantissa2 >> (32 - _Bit_shift);
|
||||
}
|
||||
|
||||
// If Ryu hasn't determined the total output length, we need to buffer the digits generated from right to left
|
||||
// by long division. The largest possible float is: 340'282346638'528859811'704183484'516925440
|
||||
uint32_t _Blocks[4];
|
||||
int32_t _Filled_blocks = 0;
|
||||
// From left to right, we're going to print:
|
||||
// _Data[0] will be [1, 10] digits.
|
||||
// Then if _Filled_blocks > 0:
|
||||
// _Blocks[_Filled_blocks - 1], ..., _Blocks[0] will be 0-filled 9-digit blocks.
|
||||
|
||||
if (_Maxidx != 0) { // If the integer is actually large, perform long division.
|
||||
// Otherwise, skip to printing _Data[0].
|
||||
for (;;) {
|
||||
// Loop invariant: _Maxidx != 0 (i.e. the integer is actually large)
|
||||
|
||||
const uint32_t _Most_significant_elem = _Data[_Maxidx];
|
||||
const uint32_t _Initial_remainder = _Most_significant_elem % 1000000000;
|
||||
const uint32_t _Initial_quotient = _Most_significant_elem / 1000000000;
|
||||
_Data[_Maxidx] = _Initial_quotient;
|
||||
uint64_t _Remainder = _Initial_remainder;
|
||||
|
||||
// Process less significant elements.
|
||||
uint32_t _Idx = _Maxidx;
|
||||
do {
|
||||
--_Idx; // Initially, _Remainder is at most 10^9 - 1.
|
||||
|
||||
// Now, _Remainder is at most (10^9 - 1) * 2^32 + 2^32 - 1, simplified to 10^9 * 2^32 - 1.
|
||||
_Remainder = (_Remainder << 32) | _Data[_Idx];
|
||||
|
||||
// floor((10^9 * 2^32 - 1) / 10^9) == 2^32 - 1, so uint32_t _Quotient is lossless.
|
||||
const uint32_t _Quotient = static_cast<uint32_t>(__div1e9(_Remainder));
|
||||
|
||||
// _Remainder is at most 10^9 - 1 again.
|
||||
// For uint32_t truncation, see the __mod1e9() comment in d2s_intrinsics.h.
|
||||
_Remainder = static_cast<uint32_t>(_Remainder) - 1000000000u * _Quotient;
|
||||
|
||||
_Data[_Idx] = _Quotient;
|
||||
} while (_Idx != 0);
|
||||
|
||||
// Store a 0-filled 9-digit block.
|
||||
_Blocks[_Filled_blocks++] = static_cast<uint32_t>(_Remainder);
|
||||
|
||||
if (_Initial_quotient == 0) { // Is the large integer shrinking?
|
||||
--_Maxidx; // log2(10^9) is 29.9, so we can't shrink by more than one element.
|
||||
if (_Maxidx == 0) {
|
||||
break; // We've finished long division. Now we need to print _Data[0].
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_ASSERT(_Data[0] != 0, "");
|
||||
for (uint32_t _Idx = 1; _Idx < _Data_size; ++_Idx) {
|
||||
_LIBCPP_ASSERT(_Data[_Idx] == 0, "");
|
||||
}
|
||||
|
||||
const uint32_t _Data_olength = _Data[0] >= 1000000000 ? 10 : __decimalLength9(_Data[0]);
|
||||
const uint32_t _Total_fixed_length = _Data_olength + 9 * _Filled_blocks;
|
||||
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(_Total_fixed_length)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
|
||||
char* _Result = _First;
|
||||
|
||||
// Print _Data[0]. While it's up to 10 digits,
|
||||
// which is more than Ryu generates, the code below can handle this.
|
||||
__append_n_digits(_Data_olength, _Data[0], _Result);
|
||||
_Result += _Data_olength;
|
||||
|
||||
// Print 0-filled 9-digit blocks.
|
||||
for (int32_t _Idx = _Filled_blocks - 1; _Idx >= 0; --_Idx) {
|
||||
__append_nine_digits(_Blocks[_Idx], _Result);
|
||||
_Result += 9;
|
||||
}
|
||||
|
||||
return { _Result, errc{} };
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline to_chars_result __to_chars(char* const _First, char* const _Last, const __floating_decimal_32 __v,
|
||||
chars_format _Fmt, const uint32_t __ieeeMantissa, const uint32_t __ieeeExponent) {
|
||||
// Step 5: Print the decimal representation.
|
||||
uint32_t _Output = __v.__mantissa;
|
||||
int32_t _Ryu_exponent = __v.__exponent;
|
||||
const uint32_t __olength = __decimalLength9(_Output);
|
||||
int32_t _Scientific_exponent = _Ryu_exponent + static_cast<int32_t>(__olength) - 1;
|
||||
|
||||
if (_Fmt == chars_format{}) {
|
||||
int32_t _Lower;
|
||||
int32_t _Upper;
|
||||
|
||||
if (__olength == 1) {
|
||||
// Value | Fixed | Scientific
|
||||
// 1e-3 | "0.001" | "1e-03"
|
||||
// 1e4 | "10000" | "1e+04"
|
||||
_Lower = -3;
|
||||
_Upper = 4;
|
||||
} else {
|
||||
// Value | Fixed | Scientific
|
||||
// 1234e-7 | "0.0001234" | "1.234e-04"
|
||||
// 1234e5 | "123400000" | "1.234e+08"
|
||||
_Lower = -static_cast<int32_t>(__olength + 3);
|
||||
_Upper = 5;
|
||||
}
|
||||
|
||||
if (_Lower <= _Ryu_exponent && _Ryu_exponent <= _Upper) {
|
||||
_Fmt = chars_format::fixed;
|
||||
} else {
|
||||
_Fmt = chars_format::scientific;
|
||||
}
|
||||
} else if (_Fmt == chars_format::general) {
|
||||
// C11 7.21.6.1 "The fprintf function"/8:
|
||||
// "Let P equal [...] 6 if the precision is omitted [...].
|
||||
// Then, if a conversion with style E would have an exponent of X:
|
||||
// - if P > X >= -4, the conversion is with style f [...].
|
||||
// - otherwise, the conversion is with style e [...]."
|
||||
if (-4 <= _Scientific_exponent && _Scientific_exponent < 6) {
|
||||
_Fmt = chars_format::fixed;
|
||||
} else {
|
||||
_Fmt = chars_format::scientific;
|
||||
}
|
||||
}
|
||||
|
||||
if (_Fmt == chars_format::fixed) {
|
||||
// Example: _Output == 1729, __olength == 4
|
||||
|
||||
// _Ryu_exponent | Printed | _Whole_digits | _Total_fixed_length | Notes
|
||||
// --------------|----------|---------------|----------------------|---------------------------------------
|
||||
// 2 | 172900 | 6 | _Whole_digits | Ryu can't be used for printing
|
||||
// 1 | 17290 | 5 | (sometimes adjusted) | when the trimmed digits are nonzero.
|
||||
// --------------|----------|---------------|----------------------|---------------------------------------
|
||||
// 0 | 1729 | 4 | _Whole_digits | Unified length cases.
|
||||
// --------------|----------|---------------|----------------------|---------------------------------------
|
||||
// -1 | 172.9 | 3 | __olength + 1 | This case can't happen for
|
||||
// -2 | 17.29 | 2 | | __olength == 1, but no additional
|
||||
// -3 | 1.729 | 1 | | code is needed to avoid it.
|
||||
// --------------|----------|---------------|----------------------|---------------------------------------
|
||||
// -4 | 0.1729 | 0 | 2 - _Ryu_exponent | C11 7.21.6.1 "The fprintf function"/8:
|
||||
// -5 | 0.01729 | -1 | | "If a decimal-point character appears,
|
||||
// -6 | 0.001729 | -2 | | at least one digit appears before it."
|
||||
|
||||
const int32_t _Whole_digits = static_cast<int32_t>(__olength) + _Ryu_exponent;
|
||||
|
||||
uint32_t _Total_fixed_length;
|
||||
if (_Ryu_exponent >= 0) { // cases "172900" and "1729"
|
||||
_Total_fixed_length = static_cast<uint32_t>(_Whole_digits);
|
||||
if (_Output == 1) {
|
||||
// Rounding can affect the number of digits.
|
||||
// For example, 1e11f is exactly "99999997952" which is 11 digits instead of 12.
|
||||
// We can use a lookup table to detect this and adjust the total length.
|
||||
static constexpr uint8_t _Adjustment[39] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,1,1,0,1,1,1 };
|
||||
_Total_fixed_length -= _Adjustment[_Ryu_exponent];
|
||||
// _Whole_digits doesn't need to be adjusted because these cases won't refer to it later.
|
||||
}
|
||||
} else if (_Whole_digits > 0) { // case "17.29"
|
||||
_Total_fixed_length = __olength + 1;
|
||||
} else { // case "0.001729"
|
||||
_Total_fixed_length = static_cast<uint32_t>(2 - _Ryu_exponent);
|
||||
}
|
||||
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(_Total_fixed_length)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
|
||||
char* _Mid;
|
||||
if (_Ryu_exponent > 0) { // case "172900"
|
||||
bool _Can_use_ryu;
|
||||
|
||||
if (_Ryu_exponent > 10) { // 10^10 is the largest power of 10 that's exactly representable as a float.
|
||||
_Can_use_ryu = false;
|
||||
} else {
|
||||
// Ryu generated X: __v.__mantissa * 10^_Ryu_exponent
|
||||
// __v.__mantissa == 2^_Trailing_zero_bits * (__v.__mantissa >> _Trailing_zero_bits)
|
||||
// 10^_Ryu_exponent == 2^_Ryu_exponent * 5^_Ryu_exponent
|
||||
|
||||
// _Trailing_zero_bits is [0, 29] (aside: because 2^29 is the largest power of 2
|
||||
// with 9 decimal digits, which is float's round-trip limit.)
|
||||
// _Ryu_exponent is [1, 10].
|
||||
// Normalization adds [2, 23] (aside: at least 2 because the pre-normalized mantissa is at least 5).
|
||||
// This adds up to [3, 62], which is well below float's maximum binary exponent 127.
|
||||
|
||||
// Therefore, we just need to consider (__v.__mantissa >> _Trailing_zero_bits) * 5^_Ryu_exponent.
|
||||
|
||||
// If that product would exceed 24 bits, then X can't be exactly represented as a float.
|
||||
// (That's not a problem for round-tripping, because X is close enough to the original float,
|
||||
// but X isn't mathematically equal to the original float.) This requires a high-precision fallback.
|
||||
|
||||
// If the product is 24 bits or smaller, then X can be exactly represented as a float (and we don't
|
||||
// need to re-synthesize it; the original float must have been X, because Ryu wouldn't produce the
|
||||
// same output for two different floats X and Y). This allows Ryu's output to be used (zero-filled).
|
||||
|
||||
// (2^24 - 1) / 5^0 (for indexing), (2^24 - 1) / 5^1, ..., (2^24 - 1) / 5^10
|
||||
static constexpr uint32_t _Max_shifted_mantissa[11] = {
|
||||
16777215, 3355443, 671088, 134217, 26843, 5368, 1073, 214, 42, 8, 1 };
|
||||
|
||||
unsigned long _Trailing_zero_bits;
|
||||
(void) _BitScanForward(&_Trailing_zero_bits, __v.__mantissa); // __v.__mantissa is guaranteed nonzero
|
||||
const uint32_t _Shifted_mantissa = __v.__mantissa >> _Trailing_zero_bits;
|
||||
_Can_use_ryu = _Shifted_mantissa <= _Max_shifted_mantissa[_Ryu_exponent];
|
||||
}
|
||||
|
||||
if (!_Can_use_ryu) {
|
||||
const uint32_t _Mantissa2 = __ieeeMantissa | (1u << __FLOAT_MANTISSA_BITS); // restore implicit bit
|
||||
const int32_t _Exponent2 = static_cast<int32_t>(__ieeeExponent)
|
||||
- __FLOAT_BIAS - __FLOAT_MANTISSA_BITS; // bias and normalization
|
||||
|
||||
// Performance note: We've already called Ryu, so this will redundantly perform buffering and bounds checking.
|
||||
return _Large_integer_to_chars(_First, _Last, _Mantissa2, _Exponent2);
|
||||
}
|
||||
|
||||
// _Can_use_ryu
|
||||
// Print the decimal digits, left-aligned within [_First, _First + _Total_fixed_length).
|
||||
_Mid = _First + __olength;
|
||||
} else { // cases "1729", "17.29", and "0.001729"
|
||||
// Print the decimal digits, right-aligned within [_First, _First + _Total_fixed_length).
|
||||
_Mid = _First + _Total_fixed_length;
|
||||
}
|
||||
|
||||
while (_Output >= 10000) {
|
||||
#ifdef __clang__ // TRANSITION, LLVM-38217
|
||||
const uint32_t __c = _Output - 10000 * (_Output / 10000);
|
||||
#else
|
||||
const uint32_t __c = _Output % 10000;
|
||||
#endif
|
||||
_Output /= 10000;
|
||||
const uint32_t __c0 = (__c % 100) << 1;
|
||||
const uint32_t __c1 = (__c / 100) << 1;
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c0, 2);
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c1, 2);
|
||||
}
|
||||
if (_Output >= 100) {
|
||||
const uint32_t __c = (_Output % 100) << 1;
|
||||
_Output /= 100;
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2);
|
||||
}
|
||||
if (_Output >= 10) {
|
||||
const uint32_t __c = _Output << 1;
|
||||
std::memcpy(_Mid -= 2, __DIGIT_TABLE + __c, 2);
|
||||
} else {
|
||||
*--_Mid = static_cast<char>('0' + _Output);
|
||||
}
|
||||
|
||||
if (_Ryu_exponent > 0) { // case "172900" with _Can_use_ryu
|
||||
// Performance note: it might be more efficient to do this immediately after setting _Mid.
|
||||
std::memset(_First + __olength, '0', static_cast<size_t>(_Ryu_exponent));
|
||||
} else if (_Ryu_exponent == 0) { // case "1729"
|
||||
// Done!
|
||||
} else if (_Whole_digits > 0) { // case "17.29"
|
||||
// Performance note: moving digits might not be optimal.
|
||||
std::memmove(_First, _First + 1, static_cast<size_t>(_Whole_digits));
|
||||
_First[_Whole_digits] = '.';
|
||||
} else { // case "0.001729"
|
||||
// Performance note: a larger memset() followed by overwriting '.' might be more efficient.
|
||||
_First[0] = '0';
|
||||
_First[1] = '.';
|
||||
std::memset(_First + 2, '0', static_cast<size_t>(-_Whole_digits));
|
||||
}
|
||||
|
||||
return { _First + _Total_fixed_length, errc{} };
|
||||
}
|
||||
|
||||
const uint32_t _Total_scientific_length =
|
||||
__olength + (__olength > 1) + 4; // digits + possible decimal point + scientific exponent
|
||||
if (_Last - _First < static_cast<ptrdiff_t>(_Total_scientific_length)) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
char* const __result = _First;
|
||||
|
||||
// Print the decimal digits.
|
||||
uint32_t __i = 0;
|
||||
while (_Output >= 10000) {
|
||||
#ifdef __clang__ // TRANSITION, LLVM-38217
|
||||
const uint32_t __c = _Output - 10000 * (_Output / 10000);
|
||||
#else
|
||||
const uint32_t __c = _Output % 10000;
|
||||
#endif
|
||||
_Output /= 10000;
|
||||
const uint32_t __c0 = (__c % 100) << 1;
|
||||
const uint32_t __c1 = (__c / 100) << 1;
|
||||
std::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c0, 2);
|
||||
std::memcpy(__result + __olength - __i - 3, __DIGIT_TABLE + __c1, 2);
|
||||
__i += 4;
|
||||
}
|
||||
if (_Output >= 100) {
|
||||
const uint32_t __c = (_Output % 100) << 1;
|
||||
_Output /= 100;
|
||||
std::memcpy(__result + __olength - __i - 1, __DIGIT_TABLE + __c, 2);
|
||||
__i += 2;
|
||||
}
|
||||
if (_Output >= 10) {
|
||||
const uint32_t __c = _Output << 1;
|
||||
// We can't use memcpy here: the decimal dot goes between these two digits.
|
||||
__result[2] = __DIGIT_TABLE[__c + 1];
|
||||
__result[0] = __DIGIT_TABLE[__c];
|
||||
} else {
|
||||
__result[0] = static_cast<char>('0' + _Output);
|
||||
}
|
||||
|
||||
// Print decimal point if needed.
|
||||
uint32_t __index;
|
||||
if (__olength > 1) {
|
||||
__result[1] = '.';
|
||||
__index = __olength + 1;
|
||||
} else {
|
||||
__index = 1;
|
||||
}
|
||||
|
||||
// Print the exponent.
|
||||
__result[__index++] = 'e';
|
||||
if (_Scientific_exponent < 0) {
|
||||
__result[__index++] = '-';
|
||||
_Scientific_exponent = -_Scientific_exponent;
|
||||
} else {
|
||||
__result[__index++] = '+';
|
||||
}
|
||||
|
||||
std::memcpy(__result + __index, __DIGIT_TABLE + 2 * _Scientific_exponent, 2);
|
||||
__index += 2;
|
||||
|
||||
return { _First + _Total_scientific_length, errc{} };
|
||||
}
|
||||
|
||||
[[nodiscard]] to_chars_result __f2s_buffered_n(char* const _First, char* const _Last, const float __f,
|
||||
const chars_format _Fmt) {
|
||||
|
||||
// Step 1: Decode the floating-point number, and unify normalized and subnormal cases.
|
||||
const uint32_t __bits = __float_to_bits(__f);
|
||||
|
||||
// Case distinction; exit early for the easy cases.
|
||||
if (__bits == 0) {
|
||||
if (_Fmt == chars_format::scientific) {
|
||||
if (_Last - _First < 5) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
|
||||
std::memcpy(_First, "0e+00", 5);
|
||||
|
||||
return { _First + 5, errc{} };
|
||||
}
|
||||
|
||||
// Print "0" for chars_format::fixed, chars_format::general, and chars_format{}.
|
||||
if (_First == _Last) {
|
||||
return { _Last, errc::value_too_large };
|
||||
}
|
||||
|
||||
*_First = '0';
|
||||
|
||||
return { _First + 1, errc{} };
|
||||
}
|
||||
|
||||
// Decode __bits into mantissa and exponent.
|
||||
const uint32_t __ieeeMantissa = __bits & ((1u << __FLOAT_MANTISSA_BITS) - 1);
|
||||
const uint32_t __ieeeExponent = __bits >> __FLOAT_MANTISSA_BITS;
|
||||
|
||||
// When _Fmt == chars_format::fixed and the floating-point number is a large integer,
|
||||
// it's faster to skip Ryu and immediately print the integer exactly.
|
||||
if (_Fmt == chars_format::fixed) {
|
||||
const uint32_t _Mantissa2 = __ieeeMantissa | (1u << __FLOAT_MANTISSA_BITS); // restore implicit bit
|
||||
const int32_t _Exponent2 = static_cast<int32_t>(__ieeeExponent)
|
||||
- __FLOAT_BIAS - __FLOAT_MANTISSA_BITS; // bias and normalization
|
||||
|
||||
// Normal values are equal to _Mantissa2 * 2^_Exponent2.
|
||||
// (Subnormals are different, but they'll be rejected by the _Exponent2 test here, so they can be ignored.)
|
||||
|
||||
if (_Exponent2 > 0) {
|
||||
return _Large_integer_to_chars(_First, _Last, _Mantissa2, _Exponent2);
|
||||
}
|
||||
}
|
||||
|
||||
const __floating_decimal_32 __v = __f2d(__ieeeMantissa, __ieeeExponent);
|
||||
return __to_chars(_First, _Last, __v, _Fmt, __ieeeMantissa, __ieeeExponent);
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
// clang-format on
|
120
third_party/libcxx/src/shared_mutex.cpp
vendored
Normal file
120
third_party/libcxx/src/shared_mutex.cpp
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <mutex>
|
||||
#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
|
361
third_party/libcxx/src/std_stream.h
vendored
Normal file
361
third_party/libcxx/src/std_stream.h
vendored
Normal file
|
@ -0,0 +1,361 @@
|
|||
// -*- 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_STD_STREAM_H
|
||||
#define _LIBCPP_STD_STREAM_H
|
||||
|
||||
#include <__config>
|
||||
#include <__locale>
|
||||
#include <cstdio>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
static const int __limit = 8;
|
||||
|
||||
// __stdinbuf
|
||||
|
||||
template <class _CharT>
|
||||
class _LIBCPP_HIDDEN __stdinbuf
|
||||
: public basic_streambuf<_CharT, char_traits<_CharT> >
|
||||
{
|
||||
public:
|
||||
typedef _CharT char_type;
|
||||
typedef char_traits<char_type> traits_type;
|
||||
typedef typename traits_type::int_type int_type;
|
||||
typedef typename traits_type::pos_type pos_type;
|
||||
typedef typename traits_type::off_type off_type;
|
||||
typedef typename traits_type::state_type state_type;
|
||||
|
||||
__stdinbuf(FILE* __fp, state_type* __st);
|
||||
|
||||
protected:
|
||||
virtual int_type underflow();
|
||||
virtual int_type uflow();
|
||||
virtual int_type pbackfail(int_type __c = traits_type::eof());
|
||||
virtual void imbue(const locale& __loc);
|
||||
|
||||
private:
|
||||
|
||||
FILE* __file_;
|
||||
const codecvt<char_type, char, state_type>* __cv_;
|
||||
state_type* __st_;
|
||||
int __encoding_;
|
||||
int_type __last_consumed_;
|
||||
bool __last_consumed_is_next_;
|
||||
bool __always_noconv_;
|
||||
|
||||
__stdinbuf(const __stdinbuf&);
|
||||
__stdinbuf& operator=(const __stdinbuf&);
|
||||
|
||||
int_type __getchar(bool __consume);
|
||||
};
|
||||
|
||||
template <class _CharT>
|
||||
__stdinbuf<_CharT>::__stdinbuf(FILE* __fp, state_type* __st)
|
||||
: __file_(__fp),
|
||||
__st_(__st),
|
||||
__last_consumed_(traits_type::eof()),
|
||||
__last_consumed_is_next_(false)
|
||||
{
|
||||
imbue(this->getloc());
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
void
|
||||
__stdinbuf<_CharT>::imbue(const locale& __loc)
|
||||
{
|
||||
__cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc);
|
||||
__encoding_ = __cv_->encoding();
|
||||
__always_noconv_ = __cv_->always_noconv();
|
||||
if (__encoding_ > __limit)
|
||||
__throw_runtime_error("unsupported locale for standard input");
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
typename __stdinbuf<_CharT>::int_type
|
||||
__stdinbuf<_CharT>::underflow()
|
||||
{
|
||||
return __getchar(false);
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
typename __stdinbuf<_CharT>::int_type
|
||||
__stdinbuf<_CharT>::uflow()
|
||||
{
|
||||
return __getchar(true);
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
typename __stdinbuf<_CharT>::int_type
|
||||
__stdinbuf<_CharT>::__getchar(bool __consume)
|
||||
{
|
||||
if (__last_consumed_is_next_)
|
||||
{
|
||||
int_type __result = __last_consumed_;
|
||||
if (__consume)
|
||||
{
|
||||
__last_consumed_ = traits_type::eof();
|
||||
__last_consumed_is_next_ = false;
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
char __extbuf[__limit];
|
||||
int __nread = _VSTD::max(1, __encoding_);
|
||||
for (int __i = 0; __i < __nread; ++__i)
|
||||
{
|
||||
int __c = getc(__file_);
|
||||
if (__c == EOF)
|
||||
return traits_type::eof();
|
||||
__extbuf[__i] = static_cast<char>(__c);
|
||||
}
|
||||
char_type __1buf;
|
||||
if (__always_noconv_)
|
||||
__1buf = static_cast<char_type>(__extbuf[0]);
|
||||
else
|
||||
{
|
||||
const char* __enxt;
|
||||
char_type* __inxt;
|
||||
codecvt_base::result __r;
|
||||
do
|
||||
{
|
||||
state_type __sv_st = *__st_;
|
||||
__r = __cv_->in(*__st_, __extbuf, __extbuf + __nread, __enxt,
|
||||
&__1buf, &__1buf + 1, __inxt);
|
||||
switch (__r)
|
||||
{
|
||||
case _VSTD::codecvt_base::ok:
|
||||
break;
|
||||
case codecvt_base::partial:
|
||||
*__st_ = __sv_st;
|
||||
if (__nread == sizeof(__extbuf))
|
||||
return traits_type::eof();
|
||||
{
|
||||
int __c = getc(__file_);
|
||||
if (__c == EOF)
|
||||
return traits_type::eof();
|
||||
__extbuf[__nread] = static_cast<char>(__c);
|
||||
}
|
||||
++__nread;
|
||||
break;
|
||||
case codecvt_base::error:
|
||||
return traits_type::eof();
|
||||
case _VSTD::codecvt_base::noconv:
|
||||
__1buf = static_cast<char_type>(__extbuf[0]);
|
||||
break;
|
||||
}
|
||||
} while (__r == _VSTD::codecvt_base::partial);
|
||||
}
|
||||
if (!__consume)
|
||||
{
|
||||
for (int __i = __nread; __i > 0;)
|
||||
{
|
||||
if (ungetc(traits_type::to_int_type(__extbuf[--__i]), __file_) == EOF)
|
||||
return traits_type::eof();
|
||||
}
|
||||
}
|
||||
else
|
||||
__last_consumed_ = traits_type::to_int_type(__1buf);
|
||||
return traits_type::to_int_type(__1buf);
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
typename __stdinbuf<_CharT>::int_type
|
||||
__stdinbuf<_CharT>::pbackfail(int_type __c)
|
||||
{
|
||||
if (traits_type::eq_int_type(__c, traits_type::eof()))
|
||||
{
|
||||
if (!__last_consumed_is_next_)
|
||||
{
|
||||
__c = __last_consumed_;
|
||||
__last_consumed_is_next_ = !traits_type::eq_int_type(__last_consumed_,
|
||||
traits_type::eof());
|
||||
}
|
||||
return __c;
|
||||
}
|
||||
if (__last_consumed_is_next_)
|
||||
{
|
||||
char __extbuf[__limit];
|
||||
char* __enxt;
|
||||
const char_type __ci = traits_type::to_char_type(__last_consumed_);
|
||||
const char_type* __inxt;
|
||||
switch (__cv_->out(*__st_, &__ci, &__ci + 1, __inxt,
|
||||
__extbuf, __extbuf + sizeof(__extbuf), __enxt))
|
||||
{
|
||||
case _VSTD::codecvt_base::ok:
|
||||
break;
|
||||
case _VSTD::codecvt_base::noconv:
|
||||
__extbuf[0] = static_cast<char>(__last_consumed_);
|
||||
__enxt = __extbuf + 1;
|
||||
break;
|
||||
case codecvt_base::partial:
|
||||
case codecvt_base::error:
|
||||
return traits_type::eof();
|
||||
}
|
||||
while (__enxt > __extbuf)
|
||||
if (ungetc(*--__enxt, __file_) == EOF)
|
||||
return traits_type::eof();
|
||||
}
|
||||
__last_consumed_ = __c;
|
||||
__last_consumed_is_next_ = true;
|
||||
return __c;
|
||||
}
|
||||
|
||||
// __stdoutbuf
|
||||
|
||||
template <class _CharT>
|
||||
class _LIBCPP_HIDDEN __stdoutbuf
|
||||
: public basic_streambuf<_CharT, char_traits<_CharT> >
|
||||
{
|
||||
public:
|
||||
typedef _CharT char_type;
|
||||
typedef char_traits<char_type> traits_type;
|
||||
typedef typename traits_type::int_type int_type;
|
||||
typedef typename traits_type::pos_type pos_type;
|
||||
typedef typename traits_type::off_type off_type;
|
||||
typedef typename traits_type::state_type state_type;
|
||||
|
||||
__stdoutbuf(FILE* __fp, state_type* __st);
|
||||
|
||||
protected:
|
||||
virtual int_type overflow (int_type __c = traits_type::eof());
|
||||
virtual streamsize xsputn(const char_type* __s, streamsize __n);
|
||||
virtual int sync();
|
||||
virtual void imbue(const locale& __loc);
|
||||
|
||||
private:
|
||||
FILE* __file_;
|
||||
const codecvt<char_type, char, state_type>* __cv_;
|
||||
state_type* __st_;
|
||||
bool __always_noconv_;
|
||||
|
||||
__stdoutbuf(const __stdoutbuf&);
|
||||
__stdoutbuf& operator=(const __stdoutbuf&);
|
||||
};
|
||||
|
||||
template <class _CharT>
|
||||
__stdoutbuf<_CharT>::__stdoutbuf(FILE* __fp, state_type* __st)
|
||||
: __file_(__fp),
|
||||
__cv_(&use_facet<codecvt<char_type, char, state_type> >(this->getloc())),
|
||||
__st_(__st),
|
||||
__always_noconv_(__cv_->always_noconv())
|
||||
{
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
typename __stdoutbuf<_CharT>::int_type
|
||||
__stdoutbuf<_CharT>::overflow(int_type __c)
|
||||
{
|
||||
char __extbuf[__limit];
|
||||
char_type __1buf;
|
||||
if (!traits_type::eq_int_type(__c, traits_type::eof()))
|
||||
{
|
||||
__1buf = traits_type::to_char_type(__c);
|
||||
if (__always_noconv_)
|
||||
{
|
||||
if (fwrite(&__1buf, sizeof(char_type), 1, __file_) != 1)
|
||||
return traits_type::eof();
|
||||
}
|
||||
else
|
||||
{
|
||||
char* __extbe = __extbuf;
|
||||
codecvt_base::result __r;
|
||||
char_type* pbase = &__1buf;
|
||||
char_type* pptr = pbase + 1;
|
||||
do
|
||||
{
|
||||
const char_type* __e;
|
||||
__r = __cv_->out(*__st_, pbase, pptr, __e,
|
||||
__extbuf,
|
||||
__extbuf + sizeof(__extbuf),
|
||||
__extbe);
|
||||
if (__e == pbase)
|
||||
return traits_type::eof();
|
||||
if (__r == codecvt_base::noconv)
|
||||
{
|
||||
if (fwrite(pbase, 1, 1, __file_) != 1)
|
||||
return traits_type::eof();
|
||||
}
|
||||
else if (__r == codecvt_base::ok || __r == codecvt_base::partial)
|
||||
{
|
||||
size_t __nmemb = static_cast<size_t>(__extbe - __extbuf);
|
||||
if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb)
|
||||
return traits_type::eof();
|
||||
if (__r == codecvt_base::partial)
|
||||
{
|
||||
pbase = const_cast<char_type*>(__e);
|
||||
}
|
||||
}
|
||||
else
|
||||
return traits_type::eof();
|
||||
} while (__r == codecvt_base::partial);
|
||||
}
|
||||
}
|
||||
return traits_type::not_eof(__c);
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
streamsize
|
||||
__stdoutbuf<_CharT>::xsputn(const char_type* __s, streamsize __n)
|
||||
{
|
||||
if (__always_noconv_)
|
||||
return fwrite(__s, sizeof(char_type), __n, __file_);
|
||||
streamsize __i = 0;
|
||||
for (; __i < __n; ++__i, ++__s)
|
||||
if (overflow(traits_type::to_int_type(*__s)) == traits_type::eof())
|
||||
break;
|
||||
return __i;
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
int
|
||||
__stdoutbuf<_CharT>::sync()
|
||||
{
|
||||
char __extbuf[__limit];
|
||||
codecvt_base::result __r;
|
||||
do
|
||||
{
|
||||
char* __extbe;
|
||||
__r = __cv_->unshift(*__st_, __extbuf,
|
||||
__extbuf + sizeof(__extbuf),
|
||||
__extbe);
|
||||
size_t __nmemb = static_cast<size_t>(__extbe - __extbuf);
|
||||
if (fwrite(__extbuf, 1, __nmemb, __file_) != __nmemb)
|
||||
return -1;
|
||||
} while (__r == codecvt_base::partial);
|
||||
if (__r == codecvt_base::error)
|
||||
return -1;
|
||||
if (fflush(__file_))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
void
|
||||
__stdoutbuf<_CharT>::imbue(const locale& __loc)
|
||||
{
|
||||
sync();
|
||||
__cv_ = &use_facet<codecvt<char_type, char, state_type> >(__loc);
|
||||
__always_noconv_ = __cv_->always_noconv();
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP_STD_STREAM_H
|
17
third_party/libcxx/src/stdexcept.cpp
vendored
Normal file
17
third_party/libcxx/src/stdexcept.cpp
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <new>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#ifdef _LIBCPP_ABI_VCRUNTIME
|
||||
#include "third_party/libcxx/src/support/runtime/stdexcept_vcruntime.ipp"
|
||||
#else
|
||||
#include "third_party/libcxx/src/support/runtime/stdexcept_default.ipp"
|
||||
#endif
|
392
third_party/libcxx/src/string.cpp
vendored
Normal file
392
third_party/libcxx/src/string.cpp
vendored
Normal file
|
@ -0,0 +1,392 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <__assert>
|
||||
#include <cerrno>
|
||||
#include <charconv>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
# include <cwchar>
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifndef _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
|
||||
|
||||
template <bool>
|
||||
struct __basic_string_common;
|
||||
|
||||
// The struct isn't declared anymore in the headers. It's only here for ABI compatibility.
|
||||
template <>
|
||||
struct __basic_string_common<true> {
|
||||
_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_length_error() const;
|
||||
_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_out_of_range() const;
|
||||
};
|
||||
|
||||
void __basic_string_common<true>::__throw_length_error() const {
|
||||
std::__throw_length_error("basic_string");
|
||||
}
|
||||
void __basic_string_common<true>::__throw_out_of_range() const {
|
||||
std::__throw_out_of_range("basic_string");
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
|
||||
|
||||
#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_HAS_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();
|
||||
__libcpp_remove_reference_t<decltype(errno)> 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();
|
||||
__libcpp_remove_reference_t<decltype(errno)> 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);
|
||||
}
|
||||
|
||||
long stol(const string& str, size_t* idx, int base) {
|
||||
return as_integer<long>("stol", str, idx, base);
|
||||
}
|
||||
|
||||
unsigned long stoul(const string& str, size_t* idx, int base) {
|
||||
return as_integer<unsigned long>("stoul", str, idx, base);
|
||||
}
|
||||
|
||||
long long stoll(const string& str, size_t* idx, int base) {
|
||||
return as_integer<long long>("stoll", str, idx, base);
|
||||
}
|
||||
|
||||
unsigned long long stoull(const string& str, size_t* idx, int base) {
|
||||
return as_integer<unsigned long long>("stoull", str, idx, base);
|
||||
}
|
||||
|
||||
float stof(const string& str, size_t* idx) {
|
||||
return as_float<float>("stof", str, idx);
|
||||
}
|
||||
|
||||
double stod(const string& str, size_t* idx) {
|
||||
return as_float<double>("stod", str, idx);
|
||||
}
|
||||
|
||||
long double stold(const string& str, size_t* idx) {
|
||||
return as_float<long double>("stold", str, idx);
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
int stoi(const wstring& str, size_t* idx, int base) {
|
||||
return as_integer<int>("stoi", str, idx, base);
|
||||
}
|
||||
|
||||
long stol(const wstring& str, size_t* idx, int base) {
|
||||
return as_integer<long>("stol", str, idx, base);
|
||||
}
|
||||
|
||||
unsigned long stoul(const wstring& str, size_t* idx, int base) {
|
||||
return as_integer<unsigned long>("stoul", str, idx, base);
|
||||
}
|
||||
|
||||
long long stoll(const wstring& str, size_t* idx, int base) {
|
||||
return as_integer<long long>("stoll", str, idx, base);
|
||||
}
|
||||
|
||||
unsigned long long stoull(const wstring& str, size_t* idx, int base) {
|
||||
return as_integer<unsigned long long>("stoull", str, idx, base);
|
||||
}
|
||||
|
||||
float stof(const wstring& str, size_t* idx) {
|
||||
return as_float<float>("stof", str, idx);
|
||||
}
|
||||
|
||||
double stod(const wstring& str, size_t* idx) {
|
||||
return as_float<double>("stod", str, idx);
|
||||
}
|
||||
|
||||
long double stold(const wstring& str, size_t* idx) {
|
||||
return as_float<long double>("stold", str, idx);
|
||||
}
|
||||
#endif // !_LIBCPP_HAS_NO_WIDE_CHARACTERS
|
||||
|
||||
// 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
|
340
third_party/libcxx/src/strstream.cpp
vendored
Normal file
340
third_party/libcxx/src/strstream.cpp
vendored
Normal file
|
@ -0,0 +1,340 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <__assert>
|
||||
#include <__utility/unreachable.h>
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <strstream>
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#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
|
||||
|
||||
_LIBCPP_POP_MACROS
|
95
third_party/libcxx/src/support/ibm/mbsnrtowcs.cpp
vendored
Normal file
95
third_party/libcxx/src/support/ibm/mbsnrtowcs.cpp
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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;
|
||||
}
|
93
third_party/libcxx/src/support/ibm/wcsnrtombs.cpp
vendored
Normal file
93
third_party/libcxx/src/support/ibm/wcsnrtombs.cpp
vendored
Normal file
|
@ -0,0 +1,93 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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;
|
||||
}
|
138
third_party/libcxx/src/support/ibm/xlocale_zos.cpp
vendored
Normal file
138
third_party/libcxx/src/support/ibm/xlocale_zos.cpp
vendored
Normal file
|
@ -0,0 +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 <__assert>
|
||||
#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
|
158
third_party/libcxx/src/support/runtime/exception_fallback.ipp
vendored
Normal file
158
third_party/libcxx/src/support/runtime/exception_fallback.ipp
vendored
Normal file
|
@ -0,0 +1,158 @@
|
|||
// -*- 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>
|
||||
|
||||
namespace std {
|
||||
|
||||
static constinit std::terminate_handler __terminate_handler = nullptr;
|
||||
static constinit std::unexpected_handler __unexpected_handler = nullptr;
|
||||
|
||||
// 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_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
(*get_terminate())();
|
||||
// handler should not return
|
||||
fprintf(stderr, "terminate_handler unexpectedly returned\n");
|
||||
::abort();
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// handler should not throw exception
|
||||
fprintf(stderr, "terminate_handler unexpectedly threw an exception\n");
|
||||
::abort();
|
||||
}
|
||||
#endif // _LIBCPP_HAS_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
|
32
third_party/libcxx/src/support/runtime/exception_glibcxx.ipp
vendored
Normal file
32
third_party/libcxx/src/support/runtime/exception_glibcxx.ipp
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
// -*- 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
|
27
third_party/libcxx/src/support/runtime/exception_libcxxabi.ipp
vendored
Normal file
27
third_party/libcxx/src/support/runtime/exception_libcxxabi.ipp
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
// -*- 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
|
25
third_party/libcxx/src/support/runtime/exception_libcxxrt.ipp
vendored
Normal file
25
third_party/libcxx/src/support/runtime/exception_libcxxrt.ipp
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
// -*- 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 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
|
163
third_party/libcxx/src/support/runtime/exception_msvc.ipp
vendored
Normal file
163
third_party/libcxx/src/support/runtime/exception_msvc.ipp
vendored
Normal file
|
@ -0,0 +1,163 @@
|
|||
// -*- 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>
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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_HAS_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
(*get_terminate())();
|
||||
// handler should not return
|
||||
fprintf(stderr, "terminate_handler unexpectedly returned\n");
|
||||
::abort();
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// handler should not throw exception
|
||||
fprintf(stderr, "terminate_handler unexpectedly threw an exception\n");
|
||||
::abort();
|
||||
}
|
||||
#endif // _LIBCPP_HAS_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
|
73
third_party/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp
vendored
Normal file
73
third_party/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
// -*- 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
|
77
third_party/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp
vendored
Normal file
77
third_party/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
// -*- 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
|
86
third_party/libcxx/src/support/runtime/exception_pointer_msvc.ipp
vendored
Normal file
86
third_party/libcxx/src/support/runtime/exception_pointer_msvc.ipp
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
// -*- 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>
|
||||
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrCreate(void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrDestroy(void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrCopy(void*, const void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrAssign(void*, const void*);
|
||||
_LIBCPP_CRT_FUNC bool __cdecl __ExceptionPtrCompare(const void*, const void*);
|
||||
_LIBCPP_CRT_FUNC bool __cdecl __ExceptionPtrToBool(const void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrSwap(void*, void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrCurrentException(void*);
|
||||
[[noreturn]] _LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrRethrow(const void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl
|
||||
__ExceptionPtrCopyException(void*, const void*, const void*);
|
||||
|
||||
namespace std {
|
||||
|
||||
exception_ptr::exception_ptr() noexcept { __ExceptionPtrCreate(this); }
|
||||
exception_ptr::exception_ptr(nullptr_t) noexcept { __ExceptionPtrCreate(this); }
|
||||
|
||||
exception_ptr::exception_ptr(const exception_ptr& __other) noexcept {
|
||||
__ExceptionPtrCopy(this, &__other);
|
||||
}
|
||||
exception_ptr& exception_ptr::operator=(const exception_ptr& __other) noexcept {
|
||||
__ExceptionPtrAssign(this, &__other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
exception_ptr& exception_ptr::operator=(nullptr_t) noexcept {
|
||||
exception_ptr dummy;
|
||||
__ExceptionPtrAssign(this, &dummy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
exception_ptr::~exception_ptr() noexcept { __ExceptionPtrDestroy(this); }
|
||||
|
||||
exception_ptr::operator bool() const noexcept {
|
||||
return __ExceptionPtrToBool(this);
|
||||
}
|
||||
|
||||
bool operator==(const exception_ptr& __x, const exception_ptr& __y) noexcept {
|
||||
return __ExceptionPtrCompare(&__x, &__y);
|
||||
}
|
||||
|
||||
|
||||
void swap(exception_ptr& lhs, exception_ptr& rhs) noexcept {
|
||||
__ExceptionPtrSwap(&rhs, &lhs);
|
||||
}
|
||||
|
||||
exception_ptr __copy_exception_ptr(void* __except, const void* __ptr) {
|
||||
exception_ptr __ret = nullptr;
|
||||
if (__ptr)
|
||||
__ExceptionPtrCopyException(&__ret, __except, __ptr);
|
||||
return __ret;
|
||||
}
|
||||
|
||||
exception_ptr current_exception() noexcept {
|
||||
exception_ptr __ret;
|
||||
__ExceptionPtrCurrentException(&__ret);
|
||||
return __ret;
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void rethrow_exception(exception_ptr p) { __ExceptionPtrRethrow(&p); }
|
||||
|
||||
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
|
79
third_party/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp
vendored
Normal file
79
third_party/libcxx/src/support/runtime/exception_pointer_unimplemented.ipp
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
// -*- 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
|
26
third_party/libcxx/src/support/runtime/new_handler_fallback.ipp
vendored
Normal file
26
third_party/libcxx/src/support/runtime/new_handler_fallback.ipp
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
// -*- 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace std {
|
||||
|
||||
static constinit std::new_handler __new_handler = nullptr;
|
||||
|
||||
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
|
64
third_party/libcxx/src/support/runtime/stdexcept_default.ipp
vendored
Normal file
64
third_party/libcxx/src/support/runtime/stdexcept_default.ipp
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 "third_party/libcxx/src/include/refstring.h"
|
||||
|
||||
/* For _LIBCPPABI_VERSION */
|
||||
#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \
|
||||
(defined(LIBCXX_BUILDING_LIBCXXABI) || defined(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
|
16
third_party/libcxx/src/support/runtime/stdexcept_vcruntime.ipp
vendored
Normal file
16
third_party/libcxx/src/support/runtime/stdexcept_vcruntime.ipp
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 deferring 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
|
143
third_party/libcxx/src/support/win32/locale_win32.cpp
vendored
Normal file
143
third_party/libcxx/src/support/win32/locale_win32.cpp
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <locale>
|
||||
#include <cstdarg> // va_start, va_end
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include <__locale_dir/locale_base_api/locale_guard.h>
|
||||
|
||||
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);
|
||||
_LIBCPP_DIAGNOSTIC_PUSH
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
|
||||
int result = vsnprintf( ret, n, format, ap );
|
||||
_LIBCPP_DIAGNOSTIC_POP
|
||||
#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
|
172
third_party/libcxx/src/support/win32/support.cpp
vendored
Normal file
172
third_party/libcxx/src/support/win32/support.cpp
vendored
Normal file
|
@ -0,0 +1,172 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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);
|
||||
_LIBCPP_DIAGNOSTIC_PUSH
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
|
||||
int count = vsnprintf( NULL, 0, format, ap_copy );
|
||||
_LIBCPP_DIAGNOSTIC_POP
|
||||
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.
|
||||
_LIBCPP_DIAGNOSTIC_PUSH
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral")
|
||||
if (vsnprintf(p, buffer_size, format, ap) != count) {
|
||||
_LIBCPP_DIAGNOSTIC_POP
|
||||
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
|
||||
// null terminator. When dst is NULL, no characters are copied
|
||||
// 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 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.
|
||||
// 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;
|
||||
|
||||
// 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);
|
||||
// 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;
|
||||
}
|
274
third_party/libcxx/src/support/win32/thread_win32.cpp
vendored
Normal file
274
third_party/libcxx/src/support/win32/thread_win32.cpp
vendored
Normal file
|
@ -0,0 +1,274 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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), "");
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
298
third_party/libcxx/src/system_error.cpp
vendored
Normal file
298
third_party/libcxx/src/system_error.cpp
vendored
Normal file
|
@ -0,0 +1,298 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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>
|
||||
#ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
|
||||
# define _LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS
|
||||
#endif
|
||||
|
||||
#include <__assert>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#include <system_error>
|
||||
|
||||
#include "third_party/libcxx/src/include/config_elast.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/api-level.h>
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// class error_category
|
||||
|
||||
#if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_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]) {
|
||||
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_HAS_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
|
217
third_party/libcxx/src/thread.cpp
vendored
Normal file
217
third_party/libcxx/src/thread.cpp
vendored
Normal file
|
@ -0,0 +1,217 @@
|
|||
//===------------------------- 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 <exception>
|
||||
#include <future>
|
||||
#include <limits>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#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()
|
||||
{
|
||||
// Even though __thread_specific_ptr's destructor doesn't actually destroy
|
||||
// anything (see comments there), we can't call it at all because threads may
|
||||
// outlive the static variable and calling its destructor means accessing an
|
||||
// object outside of its lifetime, which is UB.
|
||||
alignas(__thread_specific_ptr<__thread_struct>) static char __b[sizeof(__thread_specific_ptr<__thread_struct>)];
|
||||
static __thread_specific_ptr<__thread_struct>* __p = new (__b) __thread_specific_ptr<__thread_struct>();
|
||||
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->first->notify_all();
|
||||
i->second->unlock();
|
||||
}
|
||||
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
|
58
third_party/libcxx/src/typeinfo.cpp
vendored
Normal file
58
third_party/libcxx/src/typeinfo.cpp
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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) && \
|
||||
!defined(LIBCXXRT) && \
|
||||
!defined(__GLIBCXX__) && \
|
||||
!defined(_LIBCPP_ABI_VCRUNTIME)) || \
|
||||
defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
|
||||
std::type_info::~type_info()
|
||||
{
|
||||
}
|
||||
#endif
|
57
third_party/libcxx/src/valarray.cpp
vendored
Normal file
57
third_party/libcxx/src/valarray.cpp
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
17
third_party/libcxx/src/variant.cpp
vendored
Normal file
17
third_party/libcxx/src/variant.cpp
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
34
third_party/libcxx/src/vector.cpp
vendored
Normal file
34
third_party/libcxx/src/vector.cpp
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
#ifndef _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON
|
||||
|
||||
template <bool>
|
||||
struct __vector_base_common;
|
||||
|
||||
template <>
|
||||
struct __vector_base_common<true> {
|
||||
_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_length_error() const;
|
||||
_LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_out_of_range() const;
|
||||
};
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
77
third_party/libcxx/src/verbose_abort.cpp
vendored
Normal file
77
third_party/libcxx/src/verbose_abort.cpp
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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 <__verbose_abort>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef __BIONIC__
|
||||
# include <android/api-level.h>
|
||||
# if __ANDROID_API__ >= 21
|
||||
# include <syslog.h>
|
||||
extern "C" void android_set_abort_message(const char* msg);
|
||||
# else
|
||||
# include <assert.h>
|
||||
# endif // __ANDROID_API__ >= 21
|
||||
#endif // __BIONIC__
|
||||
|
||||
#if defined(__APPLE__) && __has_include(<CrashReporterClient.h>)
|
||||
# include <CrashReporterClient.h>
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_WEAK
|
||||
void __libcpp_verbose_abort(char const* format, ...) {
|
||||
// Write message to stderr. We do this before formatting into a
|
||||
// buffer so that we still get some information out if that fails.
|
||||
{
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
std::vfprintf(stderr, format, list);
|
||||
va_end(list);
|
||||
}
|
||||
|
||||
// Format the arguments into an allocated buffer for CrashReport & friends.
|
||||
// We leak the buffer on purpose, since we're about to abort() anyway.
|
||||
char* buffer; (void)buffer;
|
||||
va_list list;
|
||||
va_start(list, format);
|
||||
|
||||
#if defined(__APPLE__) && __has_include(<CrashReporterClient.h>)
|
||||
// Note that we should technically synchronize accesses here (by e.g. taking a lock),
|
||||
// however concretely we're only setting a pointer, so the likelihood of a race here
|
||||
// is low.
|
||||
vasprintf(&buffer, format, list);
|
||||
CRSetCrashLogMessage(buffer);
|
||||
#elif defined(__BIONIC__)
|
||||
vasprintf(&buffer, format, list);
|
||||
|
||||
# if __ANDROID_API__ >= 21
|
||||
// Show error in tombstone.
|
||||
android_set_abort_message(buffer);
|
||||
|
||||
// Show error in logcat.
|
||||
openlog("libc++", 0, 0);
|
||||
syslog(LOG_CRIT, "%s", buffer);
|
||||
closelog();
|
||||
# else
|
||||
// The good error reporting wasn't available in Android until L. Since we're
|
||||
// about to abort anyway, just call __assert2, which will log _somewhere_
|
||||
// (tombstone and/or logcat) in older releases.
|
||||
__assert2(__FILE__, __LINE__, __func__, buffer);
|
||||
# endif // __ANDROID_API__ >= 21
|
||||
#endif
|
||||
va_end(list);
|
||||
|
||||
std::abort();
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
Loading…
Add table
Add a link
Reference in a new issue