Upgrade to 2022-era LLVM LIBCXX

This commit is contained in:
Justine Tunney 2024-05-27 02:12:27 -07:00
parent 2f4ca71f26
commit 8e68384e15
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
2078 changed files with 165657 additions and 65010 deletions

47
third_party/libcxx/src/algorithm.cpp vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View file

@ -0,0 +1,2 @@
#pragma GCC system_header
GetSystemTimeInit GetSystemTimeAsFileTimeFunc _LIBCPP_INIT_PRIORITY_MAX;

View 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

View 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
View 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
View 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

View 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

View file

@ -0,0 +1,2 @@
#pragma GCC system_header
static constinit ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX;

View 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

View 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

View 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

File diff suppressed because it is too large Load diff

View 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
View 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
View 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
View 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

View 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

View 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

View 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

View 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

View 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

View 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

File diff suppressed because it is too large Load diff

View 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

View 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

View 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

View 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

View 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
View 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

View 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

File diff suppressed because it is too large Load diff

443
third_party/libcxx/src/ios.cpp vendored Normal file
View 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

View 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
View 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

View file

@ -0,0 +1,2 @@
#pragma GCC system_header
_LIBCPP_HIDDEN ios_base::Init __start_std_streams _LIBCPP_INIT_PRIORITY_MAX;

View 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

View 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

File diff suppressed because it is too large Load diff

207
third_party/libcxx/src/memory.cpp vendored Normal file
View 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

View 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

View 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
View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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;
}

View 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;
}

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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;
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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