add libc++ and libc++abi sources
upstream: LLVM 10
This commit is contained in:
95
lib/libcxx/src/algorithm.cpp
Normal file
95
lib/libcxx/src/algorithm.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
//===----------------------- algorithm.cpp --------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "algorithm"
|
||||
#include "random"
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
#include "mutex"
|
||||
#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
|
||||
#pragma comment(lib, "pthread")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template void __sort<__less<char>&, char*>(char*, char*, __less<char>&);
|
||||
template void __sort<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&);
|
||||
template void __sort<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&);
|
||||
template void __sort<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&);
|
||||
template void __sort<__less<short>&, short*>(short*, short*, __less<short>&);
|
||||
template void __sort<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&);
|
||||
template void __sort<__less<int>&, int*>(int*, int*, __less<int>&);
|
||||
template void __sort<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&);
|
||||
template void __sort<__less<long>&, long*>(long*, long*, __less<long>&);
|
||||
template void __sort<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&);
|
||||
template void __sort<__less<long long>&, long long*>(long long*, long long*, __less<long long>&);
|
||||
template void __sort<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&);
|
||||
template void __sort<__less<float>&, float*>(float*, float*, __less<float>&);
|
||||
template void __sort<__less<double>&, double*>(double*, double*, __less<double>&);
|
||||
template void __sort<__less<long double>&, long double*>(long double*, long double*, __less<long double>&);
|
||||
|
||||
template bool __insertion_sort_incomplete<__less<char>&, char*>(char*, char*, __less<char>&);
|
||||
template bool __insertion_sort_incomplete<__less<wchar_t>&, wchar_t*>(wchar_t*, wchar_t*, __less<wchar_t>&);
|
||||
template bool __insertion_sort_incomplete<__less<signed char>&, signed char*>(signed char*, signed char*, __less<signed char>&);
|
||||
template bool __insertion_sort_incomplete<__less<unsigned char>&, unsigned char*>(unsigned char*, unsigned char*, __less<unsigned char>&);
|
||||
template bool __insertion_sort_incomplete<__less<short>&, short*>(short*, short*, __less<short>&);
|
||||
template bool __insertion_sort_incomplete<__less<unsigned short>&, unsigned short*>(unsigned short*, unsigned short*, __less<unsigned short>&);
|
||||
template bool __insertion_sort_incomplete<__less<int>&, int*>(int*, int*, __less<int>&);
|
||||
template bool __insertion_sort_incomplete<__less<unsigned>&, unsigned*>(unsigned*, unsigned*, __less<unsigned>&);
|
||||
template bool __insertion_sort_incomplete<__less<long>&, long*>(long*, long*, __less<long>&);
|
||||
template bool __insertion_sort_incomplete<__less<unsigned long>&, unsigned long*>(unsigned long*, unsigned long*, __less<unsigned long>&);
|
||||
template bool __insertion_sort_incomplete<__less<long long>&, long long*>(long long*, long long*, __less<long long>&);
|
||||
template bool __insertion_sort_incomplete<__less<unsigned long long>&, unsigned long long*>(unsigned long long*, unsigned long long*, __less<unsigned long long>&);
|
||||
template bool __insertion_sort_incomplete<__less<float>&, float*>(float*, float*, __less<float>&);
|
||||
template bool __insertion_sort_incomplete<__less<double>&, double*>(double*, double*, __less<double>&);
|
||||
template bool __insertion_sort_incomplete<__less<long double>&, long double*>(long double*, long double*, __less<long double>&);
|
||||
|
||||
template unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&);
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
_LIBCPP_SAFE_STATIC static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
unsigned __rs_default::__c_ = 0;
|
||||
|
||||
__rs_default::__rs_default()
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
__libcpp_mutex_lock(&__rs_mut);
|
||||
#endif
|
||||
__c_ = 1;
|
||||
}
|
||||
|
||||
__rs_default::__rs_default(const __rs_default&)
|
||||
{
|
||||
++__c_;
|
||||
}
|
||||
|
||||
__rs_default::~__rs_default()
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
if (--__c_ == 0)
|
||||
__libcpp_mutex_unlock(&__rs_mut);
|
||||
#else
|
||||
--__c_;
|
||||
#endif
|
||||
}
|
||||
|
||||
__rs_default::result_type
|
||||
__rs_default::operator()()
|
||||
{
|
||||
static mt19937 __rs_g;
|
||||
return __rs_g();
|
||||
}
|
||||
|
||||
__rs_default
|
||||
__rs_get()
|
||||
{
|
||||
return __rs_default();
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
34
lib/libcxx/src/any.cpp
Normal file
34
lib/libcxx/src/any.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
//===---------------------------- any.cpp ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "any"
|
||||
|
||||
namespace std {
|
||||
const char* bad_any_cast::what() const _NOEXCEPT {
|
||||
return "bad any cast";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include <experimental/__config>
|
||||
|
||||
// Preserve std::experimental::any_bad_cast for ABI compatibility
|
||||
// Even though it no longer exists in a header file
|
||||
_LIBCPP_BEGIN_NAMESPACE_LFTS
|
||||
|
||||
class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast
|
||||
{
|
||||
public:
|
||||
virtual const char* what() const _NOEXCEPT;
|
||||
};
|
||||
|
||||
const char* bad_any_cast::what() const _NOEXCEPT {
|
||||
return "bad any cast";
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_LFTS
|
||||
29
lib/libcxx/src/bind.cpp
Normal file
29
lib/libcxx/src/bind.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
//===-------------------------- bind.cpp ----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "functional"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace placeholders
|
||||
{
|
||||
|
||||
const __ph<1> _1{};
|
||||
const __ph<2> _2{};
|
||||
const __ph<3> _3{};
|
||||
const __ph<4> _4{};
|
||||
const __ph<5> _5{};
|
||||
const __ph<6> _6{};
|
||||
const __ph<7> _7{};
|
||||
const __ph<8> _8{};
|
||||
const __ph<9> _9{};
|
||||
const __ph<10> _10{};
|
||||
|
||||
} // placeholders
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
160
lib/libcxx/src/charconv.cpp
Normal file
160
lib/libcxx/src/charconv.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
//===------------------------- charconv.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 "charconv"
|
||||
#include <string.h>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace __itoa
|
||||
{
|
||||
|
||||
static constexpr char cDigitsLut[200] = {
|
||||
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0',
|
||||
'7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
|
||||
'1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2',
|
||||
'2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
|
||||
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3',
|
||||
'7', '3', '8', '3', '9', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4',
|
||||
'4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0', '5', '1', '5',
|
||||
'2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
|
||||
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6',
|
||||
'7', '6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4',
|
||||
'7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8',
|
||||
'2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
|
||||
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9',
|
||||
'7', '9', '8', '9', '9'};
|
||||
|
||||
template <typename T>
|
||||
inline _LIBCPP_INLINE_VISIBILITY char*
|
||||
append1(char* buffer, T i)
|
||||
{
|
||||
*buffer = '0' + static_cast<char>(i);
|
||||
return buffer + 1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline _LIBCPP_INLINE_VISIBILITY char*
|
||||
append2(char* buffer, T i)
|
||||
{
|
||||
memcpy(buffer, &cDigitsLut[(i)*2], 2);
|
||||
return buffer + 2;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline _LIBCPP_INLINE_VISIBILITY char*
|
||||
append3(char* buffer, T i)
|
||||
{
|
||||
return append2(append1(buffer, (i) / 100), (i) % 100);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline _LIBCPP_INLINE_VISIBILITY char*
|
||||
append4(char* buffer, T i)
|
||||
{
|
||||
return append2(append2(buffer, (i) / 100), (i) % 100);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline _LIBCPP_INLINE_VISIBILITY char*
|
||||
append2_no_zeros(char* buffer, T v)
|
||||
{
|
||||
if (v < 10)
|
||||
return append1(buffer, v);
|
||||
else
|
||||
return append2(buffer, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline _LIBCPP_INLINE_VISIBILITY char*
|
||||
append4_no_zeros(char* buffer, T v)
|
||||
{
|
||||
if (v < 100)
|
||||
return append2_no_zeros(buffer, v);
|
||||
else if (v < 1000)
|
||||
return append3(buffer, v);
|
||||
else
|
||||
return append4(buffer, v);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline _LIBCPP_INLINE_VISIBILITY char*
|
||||
append8_no_zeros(char* buffer, T v)
|
||||
{
|
||||
if (v < 10000)
|
||||
{
|
||||
buffer = append4_no_zeros(buffer, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = append4_no_zeros(buffer, v / 10000);
|
||||
buffer = append4(buffer, v % 10000);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char*
|
||||
__u32toa(uint32_t value, char* buffer)
|
||||
{
|
||||
if (value < 100000000)
|
||||
{
|
||||
buffer = append8_no_zeros(buffer, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// value = aabbbbcccc in decimal
|
||||
const uint32_t a = value / 100000000; // 1 to 42
|
||||
value %= 100000000;
|
||||
|
||||
buffer = append2_no_zeros(buffer, a);
|
||||
buffer = append4(buffer, value / 10000);
|
||||
buffer = append4(buffer, value % 10000);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char*
|
||||
__u64toa(uint64_t value, char* buffer)
|
||||
{
|
||||
if (value < 100000000)
|
||||
{
|
||||
uint32_t v = static_cast<uint32_t>(value);
|
||||
buffer = append8_no_zeros(buffer, v);
|
||||
}
|
||||
else if (value < 10000000000000000)
|
||||
{
|
||||
const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
|
||||
const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
|
||||
|
||||
buffer = append8_no_zeros(buffer, v0);
|
||||
buffer = append4(buffer, v1 / 10000);
|
||||
buffer = append4(buffer, v1 % 10000);
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t a =
|
||||
static_cast<uint32_t>(value / 10000000000000000); // 1 to 1844
|
||||
value %= 10000000000000000;
|
||||
|
||||
buffer = append4_no_zeros(buffer, a);
|
||||
|
||||
const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
|
||||
const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
|
||||
buffer = append4(buffer, v0 / 10000);
|
||||
buffer = append4(buffer, v0 % 10000);
|
||||
buffer = append4(buffer, v1 / 10000);
|
||||
buffer = append4(buffer, v1 % 10000);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
} // namespace __itoa
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
233
lib/libcxx/src/chrono.cpp
Normal file
233
lib/libcxx/src/chrono.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
//===------------------------- chrono.cpp ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "chrono"
|
||||
#include "cerrno" // errno
|
||||
#include "system_error" // __throw_system_error
|
||||
#include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME
|
||||
#include "include/apple_availability.h"
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
#define _LIBCPP_USE_CLOCK_GETTIME
|
||||
#endif // __APPLE__
|
||||
|
||||
#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
|
||||
#else
|
||||
#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME)
|
||||
#include <sys/time.h> // for gettimeofday and timeval
|
||||
#endif // !defined(CLOCK_REALTIME)
|
||||
#endif // defined(_LIBCPP_WIN32API)
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK)
|
||||
#if __APPLE__
|
||||
#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t
|
||||
#elif !defined(_LIBCPP_WIN32API) && !defined(CLOCK_MONOTONIC)
|
||||
#error "Monotonic clock not implemented"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__ELF__) && defined(_LIBCPP_LINK_RT_LIB)
|
||||
#pragma comment(lib, "rt")
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace chrono
|
||||
{
|
||||
|
||||
// system_clock
|
||||
|
||||
const bool system_clock::is_steady;
|
||||
|
||||
system_clock::time_point
|
||||
system_clock::now() _NOEXCEPT
|
||||
{
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
// 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
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
GetSystemTimePreciseAsFileTime(&ft);
|
||||
#else
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
#endif
|
||||
#else
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
#endif
|
||||
|
||||
filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) |
|
||||
static_cast<__int64>(ft.dwLowDateTime)};
|
||||
return time_point(duration_cast<duration>(d - nt_to_unix_epoch));
|
||||
#else
|
||||
#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
|
||||
struct timespec tp;
|
||||
if (0 != clock_gettime(CLOCK_REALTIME, &tp))
|
||||
__throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
|
||||
return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000));
|
||||
#else
|
||||
timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
|
||||
#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME
|
||||
#endif
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK
|
||||
// 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.
|
||||
|
||||
const bool steady_clock::is_steady;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
// Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW
|
||||
#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
|
||||
steady_clock::time_point
|
||||
steady_clock::now() _NOEXCEPT
|
||||
{
|
||||
struct timespec tp;
|
||||
if (0 != clock_gettime(CLOCK_UPTIME_RAW, &tp))
|
||||
__throw_system_error(errno, "clock_gettime(CLOCK_UPTIME_RAW) failed");
|
||||
return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
|
||||
}
|
||||
|
||||
#else
|
||||
// mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
|
||||
// nanoseconds since the computer booted up. MachInfo.numer and MachInfo.denom
|
||||
// are run time constants supplied by the OS. This clock has no relationship
|
||||
// to the Gregorian calendar. It's main use is as a high resolution timer.
|
||||
|
||||
// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment. Specialize
|
||||
// for that case as an optimization.
|
||||
|
||||
static
|
||||
steady_clock::rep
|
||||
steady_simplified()
|
||||
{
|
||||
return static_cast<steady_clock::rep>(mach_absolute_time());
|
||||
}
|
||||
|
||||
static
|
||||
double
|
||||
compute_steady_factor()
|
||||
{
|
||||
mach_timebase_info_data_t MachInfo;
|
||||
mach_timebase_info(&MachInfo);
|
||||
return static_cast<double>(MachInfo.numer) / MachInfo.denom;
|
||||
}
|
||||
|
||||
static
|
||||
steady_clock::rep
|
||||
steady_full()
|
||||
{
|
||||
static const double factor = compute_steady_factor();
|
||||
return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
|
||||
}
|
||||
|
||||
typedef steady_clock::rep (*FP)();
|
||||
|
||||
static
|
||||
FP
|
||||
init_steady_clock()
|
||||
{
|
||||
mach_timebase_info_data_t MachInfo;
|
||||
mach_timebase_info(&MachInfo);
|
||||
if (MachInfo.numer == MachInfo.denom)
|
||||
return &steady_simplified;
|
||||
return &steady_full;
|
||||
}
|
||||
|
||||
steady_clock::time_point
|
||||
steady_clock::now() _NOEXCEPT
|
||||
{
|
||||
static FP fp = init_steady_clock();
|
||||
return time_point(duration(fp()));
|
||||
}
|
||||
#endif // defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
steady_clock::time_point
|
||||
steady_clock::now() _NOEXCEPT
|
||||
{
|
||||
static const LARGE_INTEGER freq = __QueryPerformanceFrequency();
|
||||
|
||||
LARGE_INTEGER counter;
|
||||
(void) QueryPerformanceCounter(&counter);
|
||||
return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart));
|
||||
}
|
||||
|
||||
#elif defined(CLOCK_MONOTONIC)
|
||||
|
||||
// On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able to
|
||||
// time functions in the nanosecond range. Thus, they are the only acceptable
|
||||
// implementations of steady_clock.
|
||||
#ifdef __APPLE__
|
||||
#error "Never use CLOCK_MONOTONIC for steady_clock::now on Apple platforms"
|
||||
#endif
|
||||
|
||||
steady_clock::time_point
|
||||
steady_clock::now() _NOEXCEPT
|
||||
{
|
||||
struct timespec tp;
|
||||
if (0 != clock_gettime(CLOCK_MONOTONIC, &tp))
|
||||
__throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed");
|
||||
return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Monotonic clock not implemented"
|
||||
#endif
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK
|
||||
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
93
lib/libcxx/src/condition_variable.cpp
Normal file
93
lib/libcxx/src/condition_variable.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
//===-------------------- condition_variable.cpp --------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "__config"
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
|
||||
#include "condition_variable"
|
||||
#include "thread"
|
||||
#include "system_error"
|
||||
#include "__undef_macros"
|
||||
|
||||
#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
|
||||
#pragma comment(lib, "pthread")
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// ~condition_variable is defined elsewhere.
|
||||
|
||||
void
|
||||
condition_variable::notify_one() _NOEXCEPT
|
||||
{
|
||||
__libcpp_condvar_signal(&__cv_);
|
||||
}
|
||||
|
||||
void
|
||||
condition_variable::notify_all() _NOEXCEPT
|
||||
{
|
||||
__libcpp_condvar_broadcast(&__cv_);
|
||||
}
|
||||
|
||||
void
|
||||
condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT
|
||||
{
|
||||
if (!lk.owns_lock())
|
||||
__throw_system_error(EPERM,
|
||||
"condition_variable::wait: mutex not locked");
|
||||
int ec = __libcpp_condvar_wait(&__cv_, lk.mutex()->native_handle());
|
||||
if (ec)
|
||||
__throw_system_error(ec, "condition_variable wait failed");
|
||||
}
|
||||
|
||||
void
|
||||
condition_variable::__do_timed_wait(unique_lock<mutex>& lk,
|
||||
chrono::time_point<chrono::system_clock, chrono::nanoseconds> tp) _NOEXCEPT
|
||||
{
|
||||
using namespace chrono;
|
||||
if (!lk.owns_lock())
|
||||
__throw_system_error(EPERM,
|
||||
"condition_variable::timed wait: mutex not locked");
|
||||
nanoseconds d = tp.time_since_epoch();
|
||||
if (d > nanoseconds(0x59682F000000E941))
|
||||
d = nanoseconds(0x59682F000000E941);
|
||||
__libcpp_timespec_t ts;
|
||||
seconds s = duration_cast<seconds>(d);
|
||||
typedef decltype(ts.tv_sec) ts_sec;
|
||||
_LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
|
||||
if (s.count() < ts_sec_max)
|
||||
{
|
||||
ts.tv_sec = static_cast<ts_sec>(s.count());
|
||||
ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count());
|
||||
}
|
||||
else
|
||||
{
|
||||
ts.tv_sec = ts_sec_max;
|
||||
ts.tv_nsec = giga::num - 1;
|
||||
}
|
||||
int ec = __libcpp_condvar_timedwait(&__cv_, lk.mutex()->native_handle(), &ts);
|
||||
if (ec != 0 && ec != ETIMEDOUT)
|
||||
__throw_system_error(ec, "condition_variable timed_wait failed");
|
||||
}
|
||||
|
||||
void
|
||||
notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk)
|
||||
{
|
||||
auto& tl_ptr = __thread_local_data();
|
||||
// If this thread was not created using std::thread then it will not have
|
||||
// previously allocated.
|
||||
if (tl_ptr.get() == nullptr) {
|
||||
tl_ptr.set_pointer(new __thread_struct);
|
||||
}
|
||||
__thread_local_data()->notify_all_at_thread_exit(&cond, lk.release());
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
46
lib/libcxx/src/condition_variable_destructor.cpp
Normal file
46
lib/libcxx/src/condition_variable_destructor.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
//===---------------- condition_variable_destructor.cpp ------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Define ~condition_variable.
|
||||
//
|
||||
// On some platforms ~condition_variable has been made trivial and the
|
||||
// definition is only provided for ABI compatibility.
|
||||
|
||||
#include "__config"
|
||||
#include "__threading_support"
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
# if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION)
|
||||
# define NEEDS_CONDVAR_DESTRUCTOR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifdef NEEDS_CONDVAR_DESTRUCTOR
|
||||
|
||||
class _LIBCPP_TYPE_VIS condition_variable
|
||||
{
|
||||
__libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
|
||||
public:
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
constexpr condition_variable() noexcept = default;
|
||||
|
||||
~condition_variable();
|
||||
|
||||
condition_variable(const condition_variable&) = delete;
|
||||
condition_variable& operator=(const condition_variable&) = delete;
|
||||
};
|
||||
|
||||
condition_variable::~condition_variable()
|
||||
{
|
||||
__libcpp_condvar_destroy(&__cv_);
|
||||
}
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
578
lib/libcxx/src/debug.cpp
Normal file
578
lib/libcxx/src/debug.cpp
Normal file
@@ -0,0 +1,578 @@
|
||||
//===-------------------------- debug.cpp ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "__config"
|
||||
#include "__debug"
|
||||
#include "functional"
|
||||
#include "algorithm"
|
||||
#include "string"
|
||||
#include "cstdio"
|
||||
#include "__hash_table"
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
#include "mutex"
|
||||
#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
|
||||
#pragma comment(lib, "pthread")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
std::string __libcpp_debug_info::what() const {
|
||||
string msg = __file_;
|
||||
msg += ":" + to_string(__line_) + ": _LIBCPP_ASSERT '";
|
||||
msg += __pred_;
|
||||
msg += "' failed. ";
|
||||
msg += __msg_;
|
||||
return msg;
|
||||
}
|
||||
_LIBCPP_NORETURN void __libcpp_abort_debug_function(__libcpp_debug_info const& info) {
|
||||
std::fprintf(stderr, "%s\n", info.what().c_str());
|
||||
std::abort();
|
||||
}
|
||||
|
||||
_LIBCPP_SAFE_STATIC __libcpp_debug_function_type
|
||||
__libcpp_debug_function = __libcpp_abort_debug_function;
|
||||
|
||||
bool __libcpp_set_debug_function(__libcpp_debug_function_type __func) {
|
||||
__libcpp_debug_function = __func;
|
||||
return true;
|
||||
}
|
||||
|
||||
_LIBCPP_FUNC_VIS
|
||||
__libcpp_db*
|
||||
__get_db()
|
||||
{
|
||||
static _LIBCPP_NO_DESTROY __libcpp_db db;
|
||||
return &db;
|
||||
}
|
||||
|
||||
_LIBCPP_FUNC_VIS
|
||||
const __libcpp_db*
|
||||
__get_const_db()
|
||||
{
|
||||
return __get_db();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
typedef mutex mutex_type;
|
||||
typedef lock_guard<mutex_type> WLock;
|
||||
typedef lock_guard<mutex_type> RLock;
|
||||
|
||||
mutex_type&
|
||||
mut()
|
||||
{
|
||||
static _LIBCPP_NO_DESTROY mutex_type m;
|
||||
return m;
|
||||
}
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
__i_node::~__i_node()
|
||||
{
|
||||
if (__next_)
|
||||
{
|
||||
__next_->~__i_node();
|
||||
free(__next_);
|
||||
}
|
||||
}
|
||||
|
||||
__c_node::~__c_node()
|
||||
{
|
||||
free(beg_);
|
||||
if (__next_)
|
||||
{
|
||||
__next_->~__c_node();
|
||||
free(__next_);
|
||||
}
|
||||
}
|
||||
|
||||
__libcpp_db::__libcpp_db()
|
||||
: __cbeg_(nullptr),
|
||||
__cend_(nullptr),
|
||||
__csz_(0),
|
||||
__ibeg_(nullptr),
|
||||
__iend_(nullptr),
|
||||
__isz_(0)
|
||||
{
|
||||
}
|
||||
|
||||
__libcpp_db::~__libcpp_db()
|
||||
{
|
||||
if (__cbeg_)
|
||||
{
|
||||
for (__c_node** p = __cbeg_; p != __cend_; ++p)
|
||||
{
|
||||
if (*p != nullptr)
|
||||
{
|
||||
(*p)->~__c_node();
|
||||
free(*p);
|
||||
}
|
||||
}
|
||||
free(__cbeg_);
|
||||
}
|
||||
if (__ibeg_)
|
||||
{
|
||||
for (__i_node** p = __ibeg_; p != __iend_; ++p)
|
||||
{
|
||||
if (*p != nullptr)
|
||||
{
|
||||
(*p)->~__i_node();
|
||||
free(*p);
|
||||
}
|
||||
}
|
||||
free(__ibeg_);
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
__libcpp_db::__find_c_from_i(void* __i) const
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
RLock _(mut());
|
||||
#endif
|
||||
__i_node* i = __find_iterator(__i);
|
||||
_LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
|
||||
return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
__libcpp_db::__insert_ic(void* __i, const void* __c)
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
WLock _(mut());
|
||||
#endif
|
||||
if (__cbeg_ == __cend_)
|
||||
return;
|
||||
size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
|
||||
__c_node* c = __cbeg_[hc];
|
||||
if (c == nullptr)
|
||||
return;
|
||||
while (c->__c_ != __c)
|
||||
{
|
||||
c = c->__next_;
|
||||
if (c == nullptr)
|
||||
return;
|
||||
}
|
||||
__i_node* i = __insert_iterator(__i);
|
||||
c->__add(i);
|
||||
i->__c_ = c;
|
||||
}
|
||||
|
||||
void
|
||||
__libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn)
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
WLock _(mut());
|
||||
#endif
|
||||
if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
|
||||
{
|
||||
size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
|
||||
__c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*)));
|
||||
if (cbeg == nullptr)
|
||||
__throw_bad_alloc();
|
||||
|
||||
for (__c_node** p = __cbeg_; p != __cend_; ++p)
|
||||
{
|
||||
__c_node* q = *p;
|
||||
while (q != nullptr)
|
||||
{
|
||||
size_t h = hash<void*>()(q->__c_) % nc;
|
||||
__c_node* r = q->__next_;
|
||||
q->__next_ = cbeg[h];
|
||||
cbeg[h] = q;
|
||||
q = r;
|
||||
}
|
||||
}
|
||||
free(__cbeg_);
|
||||
__cbeg_ = cbeg;
|
||||
__cend_ = __cbeg_ + nc;
|
||||
}
|
||||
size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
|
||||
__c_node* p = __cbeg_[hc];
|
||||
void *buf = malloc(sizeof(__c_node));
|
||||
if (buf == nullptr)
|
||||
__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 != nullptr && 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
lib/libcxx/src/exception.cpp
Normal file
35
lib/libcxx/src/exception.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
//===------------------------ exception.cpp -------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "exception"
|
||||
#include "new"
|
||||
#include "typeinfo"
|
||||
|
||||
#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 "support/runtime/exception_msvc.ipp"
|
||||
#include "support/runtime/exception_pointer_msvc.ipp"
|
||||
#elif defined(_LIBCPPABI_VERSION)
|
||||
#include "support/runtime/exception_libcxxabi.ipp"
|
||||
#include "support/runtime/exception_pointer_cxxabi.ipp"
|
||||
#elif defined(LIBCXXRT)
|
||||
#include "support/runtime/exception_libcxxrt.ipp"
|
||||
#include "support/runtime/exception_pointer_cxxabi.ipp"
|
||||
#elif defined(__GLIBCXX__)
|
||||
#include "support/runtime/exception_glibcxx.ipp"
|
||||
#include "support/runtime/exception_pointer_glibcxx.ipp"
|
||||
#else
|
||||
#include "include/atomic_support.h"
|
||||
#include "support/runtime/exception_fallback.ipp"
|
||||
#include "support/runtime/exception_pointer_unimplemented.ipp"
|
||||
#endif
|
||||
161
lib/libcxx/src/experimental/memory_resource.cpp
Normal file
161
lib/libcxx/src/experimental/memory_resource.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
//===------------------------ memory_resource.cpp -------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "experimental/memory_resource"
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
|
||||
#include "atomic"
|
||||
#elif !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#include "mutex"
|
||||
#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
|
||||
#pragma comment(lib, "pthread")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR
|
||||
|
||||
// memory_resource
|
||||
|
||||
//memory_resource::~memory_resource() {}
|
||||
|
||||
// new_delete_resource()
|
||||
|
||||
class _LIBCPP_TYPE_VIS __new_delete_memory_resource_imp
|
||||
: public memory_resource
|
||||
{
|
||||
void *do_allocate(size_t size, size_t align) override {
|
||||
#ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
|
||||
if (__is_overaligned_for_new(align))
|
||||
__throw_bad_alloc();
|
||||
#endif
|
||||
return _VSTD::__libcpp_allocate(size, align);
|
||||
}
|
||||
|
||||
void do_deallocate(void *p, size_t n, size_t align) override {
|
||||
_VSTD::__libcpp_deallocate(p, n, align);
|
||||
}
|
||||
|
||||
bool do_is_equal(memory_resource const & other) const _NOEXCEPT override
|
||||
{ return &other == this; }
|
||||
|
||||
public:
|
||||
~__new_delete_memory_resource_imp() override = default;
|
||||
};
|
||||
|
||||
// null_memory_resource()
|
||||
|
||||
class _LIBCPP_TYPE_VIS __null_memory_resource_imp
|
||||
: public memory_resource
|
||||
{
|
||||
public:
|
||||
~__null_memory_resource_imp() = default;
|
||||
|
||||
protected:
|
||||
virtual void* do_allocate(size_t, size_t) {
|
||||
__throw_bad_alloc();
|
||||
}
|
||||
virtual void do_deallocate(void *, size_t, size_t) {}
|
||||
virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT
|
||||
{ return &__other == this; }
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
union ResourceInitHelper {
|
||||
struct {
|
||||
__new_delete_memory_resource_imp new_delete_res;
|
||||
__null_memory_resource_imp null_res;
|
||||
} resources;
|
||||
char dummy;
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {}
|
||||
~ResourceInitHelper() {}
|
||||
};
|
||||
|
||||
// Detect if the init_priority attribute is supported.
|
||||
#if (defined(_LIBCPP_COMPILER_GCC) && defined(__APPLE__)) \
|
||||
|| defined(_LIBCPP_COMPILER_MSVC)
|
||||
// GCC on Apple doesn't support the init priority attribute,
|
||||
// and MSVC doesn't support any GCC attributes.
|
||||
# define _LIBCPP_INIT_PRIORITY_MAX
|
||||
#else
|
||||
# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((init_priority(101)))
|
||||
#endif
|
||||
|
||||
// When compiled in C++14 this initialization should be a constant expression.
|
||||
// Only in C++11 is "init_priority" needed to ensure initialization order.
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
_LIBCPP_SAFE_STATIC
|
||||
#endif
|
||||
ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX;
|
||||
|
||||
} // end namespace
|
||||
|
||||
|
||||
memory_resource * new_delete_resource() _NOEXCEPT {
|
||||
return &res_init.resources.new_delete_res;
|
||||
}
|
||||
|
||||
memory_resource * null_memory_resource() _NOEXCEPT {
|
||||
return &res_init.resources.null_res;
|
||||
}
|
||||
|
||||
// default_memory_resource()
|
||||
|
||||
static memory_resource *
|
||||
__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER
|
||||
_LIBCPP_SAFE_STATIC static atomic<memory_resource*> __res =
|
||||
ATOMIC_VAR_INIT(&res_init.resources.new_delete_res);
|
||||
if (set) {
|
||||
new_res = new_res ? new_res : new_delete_resource();
|
||||
// TODO: Can a weaker ordering be used?
|
||||
return _VSTD::atomic_exchange_explicit(
|
||||
&__res, new_res, memory_order_acq_rel);
|
||||
}
|
||||
else {
|
||||
return _VSTD::atomic_load_explicit(
|
||||
&__res, memory_order_acquire);
|
||||
}
|
||||
#elif !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
_LIBCPP_SAFE_STATIC static memory_resource * res = &res_init.resources.new_delete_res;
|
||||
static mutex res_lock;
|
||||
if (set) {
|
||||
new_res = new_res ? new_res : new_delete_resource();
|
||||
lock_guard<mutex> guard(res_lock);
|
||||
memory_resource * old_res = res;
|
||||
res = new_res;
|
||||
return old_res;
|
||||
} else {
|
||||
lock_guard<mutex> guard(res_lock);
|
||||
return res;
|
||||
}
|
||||
#else
|
||||
_LIBCPP_SAFE_STATIC static memory_resource* res = &res_init.resources.new_delete_res;
|
||||
if (set) {
|
||||
new_res = new_res ? new_res : new_delete_resource();
|
||||
memory_resource * old_res = res;
|
||||
res = new_res;
|
||||
return old_res;
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
memory_resource * get_default_resource() _NOEXCEPT
|
||||
{
|
||||
return __default_memory_resource();
|
||||
}
|
||||
|
||||
memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT
|
||||
{
|
||||
return __default_memory_resource(true, __new_res);
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_LFTS_PMR
|
||||
398
lib/libcxx/src/filesystem/directory_iterator.cpp
Normal file
398
lib/libcxx/src/filesystem/directory_iterator.cpp
Normal file
@@ -0,0 +1,398 @@
|
||||
//===------------------ directory_iterator.cpp ----------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "filesystem"
|
||||
#include "__config"
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include "filesystem_common.h"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
|
||||
|
||||
namespace detail {
|
||||
namespace {
|
||||
|
||||
#if !defined(_LIBCPP_WIN32API)
|
||||
|
||||
#if defined(DT_BLK)
|
||||
template <class DirEntT, class = decltype(DirEntT::d_type)>
|
||||
static file_type get_file_type(DirEntT* ent, int) {
|
||||
switch (ent->d_type) {
|
||||
case DT_BLK:
|
||||
return file_type::block;
|
||||
case DT_CHR:
|
||||
return file_type::character;
|
||||
case DT_DIR:
|
||||
return file_type::directory;
|
||||
case DT_FIFO:
|
||||
return file_type::fifo;
|
||||
case DT_LNK:
|
||||
return file_type::symlink;
|
||||
case DT_REG:
|
||||
return file_type::regular;
|
||||
case DT_SOCK:
|
||||
return file_type::socket;
|
||||
// Unlike in lstat, hitting "unknown" here simply means that the underlying
|
||||
// filesystem doesn't support d_type. Report is as 'none' so we correctly
|
||||
// set the cache to empty.
|
||||
case DT_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
return file_type::none;
|
||||
}
|
||||
#endif // defined(DT_BLK)
|
||||
|
||||
template <class DirEntT>
|
||||
static file_type get_file_type(DirEntT* ent, 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
|
||||
|
||||
static file_type get_file_type(const WIN32_FIND_DATA& data) {
|
||||
//auto attrs = data.dwFileAttributes;
|
||||
// FIXME(EricWF)
|
||||
return file_type::unknown;
|
||||
}
|
||||
static uintmax_t get_file_size(const WIN32_FIND_DATA& data) {
|
||||
return (data.nFileSizeHigh * (MAXDWORD + 1)) + data.nFileSizeLow;
|
||||
}
|
||||
static file_time_type get_write_time(const WIN32_FIND_DATA& data) {
|
||||
ULARGE_INTEGER tmp;
|
||||
const FILETIME& time = data.ftLastWriteTime;
|
||||
tmp.u.LowPart = time.dwLowDateTime;
|
||||
tmp.u.HighPart = time.dwHighDateTime;
|
||||
return file_time_type(file_time_type::duration(tmp.QuadPart));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
} // namespace detail
|
||||
|
||||
using detail::ErrorHandler;
|
||||
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
class __dir_stream {
|
||||
public:
|
||||
__dir_stream() = delete;
|
||||
__dir_stream& operator=(const __dir_stream&) = delete;
|
||||
|
||||
__dir_stream(__dir_stream&& __ds) noexcept : __stream_(__ds.__stream_),
|
||||
__root_(move(__ds.__root_)),
|
||||
__entry_(move(__ds.__entry_)) {
|
||||
__ds.__stream_ = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
__dir_stream(const path& root, directory_options opts, error_code& ec)
|
||||
: __stream_(INVALID_HANDLE_VALUE), __root_(root) {
|
||||
__stream_ = ::FindFirstFile(root.c_str(), &__data_);
|
||||
if (__stream_ == INVALID_HANDLE_VALUE) {
|
||||
ec = error_code(::GetLastError(), generic_category());
|
||||
const bool ignore_permission_denied =
|
||||
bool(opts & directory_options::skip_permission_denied);
|
||||
if (ignore_permission_denied && ec.value() == ERROR_ACCESS_DENIED)
|
||||
ec.clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
~__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 (::FindNextFile(__stream_, &__data_)) {
|
||||
if (!strcmp(__data_.cFileName, ".") || strcmp(__data_.cFileName, ".."))
|
||||
continue;
|
||||
// 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;
|
||||
}
|
||||
ec = error_code(::GetLastError(), generic_category());
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
error_code close() noexcept {
|
||||
error_code ec;
|
||||
if (!::FindClose(__stream_))
|
||||
ec = error_code(::GetLastError(), generic_category());
|
||||
__stream_ = INVALID_HANDLE_VALUE;
|
||||
return ec;
|
||||
}
|
||||
|
||||
HANDLE __stream_{INVALID_HANDLE_VALUE};
|
||||
WIN32_FIND_DATA __data_;
|
||||
|
||||
public:
|
||||
path __root_;
|
||||
directory_entry __entry_;
|
||||
};
|
||||
#else
|
||||
class __dir_stream {
|
||||
public:
|
||||
__dir_stream() = delete;
|
||||
__dir_stream& operator=(const __dir_stream&) = delete;
|
||||
|
||||
__dir_stream(__dir_stream&& other) noexcept : __stream_(other.__stream_),
|
||||
__root_(move(other.__root_)),
|
||||
__entry_(move(other.__entry_)) {
|
||||
other.__stream_ = nullptr;
|
||||
}
|
||||
|
||||
__dir_stream(const path& root, directory_options opts, error_code& ec)
|
||||
: __stream_(nullptr), __root_(root) {
|
||||
if ((__stream_ = ::opendir(root.c_str())) == nullptr) {
|
||||
ec = detail::capture_errno();
|
||||
const bool allow_eacess =
|
||||
bool(opts & directory_options::skip_permission_denied);
|
||||
if (allow_eacess && ec.value() == EACCES)
|
||||
ec.clear();
|
||||
return;
|
||||
}
|
||||
advance(ec);
|
||||
}
|
||||
|
||||
~__dir_stream() noexcept {
|
||||
if (__stream_)
|
||||
close();
|
||||
}
|
||||
|
||||
bool good() const noexcept { return __stream_ != nullptr; }
|
||||
|
||||
bool advance(error_code& ec) {
|
||||
while (true) {
|
||||
auto str_type_pair = detail::posix_readdir(__stream_, ec);
|
||||
auto& str = str_type_pair.first;
|
||||
if (str == "." || str == "..") {
|
||||
continue;
|
||||
} else if (ec || str.empty()) {
|
||||
close();
|
||||
return false;
|
||||
} else {
|
||||
__entry_.__assign_iter_entry(
|
||||
__root_ / str,
|
||||
directory_entry::__create_iter_result(str_type_pair.second));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
error_code close() noexcept {
|
||||
error_code m_ec;
|
||||
if (::closedir(__stream_) == -1)
|
||||
m_ec = detail::capture_errno();
|
||||
__stream_ = nullptr;
|
||||
return m_ec;
|
||||
}
|
||||
|
||||
DIR* __stream_{nullptr};
|
||||
|
||||
public:
|
||||
path __root_;
|
||||
directory_entry __entry_;
|
||||
};
|
||||
#endif
|
||||
|
||||
// directory_iterator
|
||||
|
||||
directory_iterator::directory_iterator(const path& p, error_code* ec,
|
||||
directory_options opts) {
|
||||
ErrorHandler<void> err("directory_iterator::directory_iterator(...)", ec, &p);
|
||||
|
||||
error_code m_ec;
|
||||
__imp_ = make_shared<__dir_stream>(p, opts, m_ec);
|
||||
if (ec)
|
||||
*ec = m_ec;
|
||||
if (!__imp_->good()) {
|
||||
__imp_.reset();
|
||||
if (m_ec)
|
||||
err.report(m_ec);
|
||||
}
|
||||
}
|
||||
|
||||
directory_iterator& directory_iterator::__increment(error_code* ec) {
|
||||
_LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator");
|
||||
ErrorHandler<void> err("directory_iterator::operator++()", ec);
|
||||
|
||||
error_code m_ec;
|
||||
if (!__imp_->advance(m_ec)) {
|
||||
path root = move(__imp_->__root_);
|
||||
__imp_.reset();
|
||||
if (m_ec)
|
||||
err.report(m_ec, "at root \"%s\"", root);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
directory_entry const& directory_iterator::__dereference() const {
|
||||
_LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator");
|
||||
return __imp_->__entry_;
|
||||
}
|
||||
|
||||
// recursive_directory_iterator
|
||||
|
||||
struct recursive_directory_iterator::__shared_imp {
|
||||
stack<__dir_stream> __stack_;
|
||||
directory_options __options_;
|
||||
};
|
||||
|
||||
recursive_directory_iterator::recursive_directory_iterator(
|
||||
const path& p, directory_options opt, error_code* ec)
|
||||
: __imp_(nullptr), __rec_(true) {
|
||||
ErrorHandler<void> err("recursive_directory_iterator", ec, &p);
|
||||
|
||||
error_code m_ec;
|
||||
__dir_stream new_s(p, opt, m_ec);
|
||||
if (m_ec)
|
||||
err.report(m_ec);
|
||||
if (m_ec || !new_s.good())
|
||||
return;
|
||||
|
||||
__imp_ = make_shared<__shared_imp>();
|
||||
__imp_->__options_ = opt;
|
||||
__imp_->__stack_.push(move(new_s));
|
||||
}
|
||||
|
||||
void recursive_directory_iterator::__pop(error_code* ec) {
|
||||
_LIBCPP_ASSERT(__imp_, "Popping the end iterator");
|
||||
if (ec)
|
||||
ec->clear();
|
||||
__imp_->__stack_.pop();
|
||||
if (__imp_->__stack_.size() == 0)
|
||||
__imp_.reset();
|
||||
else
|
||||
__advance(ec);
|
||||
}
|
||||
|
||||
directory_options recursive_directory_iterator::options() const {
|
||||
return __imp_->__options_;
|
||||
}
|
||||
|
||||
int recursive_directory_iterator::depth() const {
|
||||
return __imp_->__stack_.size() - 1;
|
||||
}
|
||||
|
||||
const directory_entry& recursive_directory_iterator::__dereference() const {
|
||||
return __imp_->__stack_.top().__entry_;
|
||||
}
|
||||
|
||||
recursive_directory_iterator&
|
||||
recursive_directory_iterator::__increment(error_code* ec) {
|
||||
if (ec)
|
||||
ec->clear();
|
||||
if (recursion_pending()) {
|
||||
if (__try_recursion(ec) || (ec && *ec))
|
||||
return *this;
|
||||
}
|
||||
__rec_ = true;
|
||||
__advance(ec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void recursive_directory_iterator::__advance(error_code* ec) {
|
||||
ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
|
||||
|
||||
const directory_iterator end_it;
|
||||
auto& stack = __imp_->__stack_;
|
||||
error_code m_ec;
|
||||
while (stack.size() > 0) {
|
||||
if (stack.top().advance(m_ec))
|
||||
return;
|
||||
if (m_ec)
|
||||
break;
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
if (m_ec) {
|
||||
path root = move(stack.top().__root_);
|
||||
__imp_.reset();
|
||||
err.report(m_ec, "at root \"%s\"", root);
|
||||
} else {
|
||||
__imp_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool recursive_directory_iterator::__try_recursion(error_code* ec) {
|
||||
ErrorHandler<void> err("recursive_directory_iterator::operator++()", ec);
|
||||
|
||||
bool rec_sym = bool(options() & directory_options::follow_directory_symlink);
|
||||
|
||||
auto& curr_it = __imp_->__stack_.top();
|
||||
|
||||
bool skip_rec = false;
|
||||
error_code m_ec;
|
||||
if (!rec_sym) {
|
||||
file_status st(curr_it.__entry_.__get_sym_ft(&m_ec));
|
||||
if (m_ec && status_known(st))
|
||||
m_ec.clear();
|
||||
if (m_ec || is_symlink(st) || !is_directory(st))
|
||||
skip_rec = true;
|
||||
} else {
|
||||
file_status st(curr_it.__entry_.__get_ft(&m_ec));
|
||||
if (m_ec && status_known(st))
|
||||
m_ec.clear();
|
||||
if (m_ec || !is_directory(st))
|
||||
skip_rec = true;
|
||||
}
|
||||
|
||||
if (!skip_rec) {
|
||||
__dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec);
|
||||
if (new_it.good()) {
|
||||
__imp_->__stack_.push(move(new_it));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (m_ec) {
|
||||
const bool allow_eacess =
|
||||
bool(__imp_->__options_ & directory_options::skip_permission_denied);
|
||||
if (m_ec.value() == EACCES && allow_eacess) {
|
||||
if (ec)
|
||||
ec->clear();
|
||||
} else {
|
||||
path at_ent = move(curr_it.__entry_.__p_);
|
||||
__imp_.reset();
|
||||
err.report(m_ec, "attempting recursion into \"%s\"", at_ent);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_FILESYSTEM
|
||||
435
lib/libcxx/src/filesystem/filesystem_common.h
Normal file
435
lib/libcxx/src/filesystem/filesystem_common.h
Normal file
@@ -0,0 +1,435 @@
|
||||
//===----------------------------------------------------------------------===////
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===////
|
||||
|
||||
#ifndef FILESYSTEM_COMMON_H
|
||||
#define FILESYSTEM_COMMON_H
|
||||
|
||||
#include "__config"
|
||||
#include "filesystem"
|
||||
#include "array"
|
||||
#include "chrono"
|
||||
#include "cstdlib"
|
||||
#include "climits"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/time.h> // for ::utimes as used in __last_write_time
|
||||
#include <fcntl.h> /* values for fchmodat */
|
||||
|
||||
#include "../include/apple_availability.h"
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
// We can use the presence of UTIME_OMIT to detect platforms that provide
|
||||
// utimensat.
|
||||
#if defined(UTIME_OMIT)
|
||||
#define _LIBCPP_USE_UTIMENSAT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM
|
||||
|
||||
namespace detail {
|
||||
namespace {
|
||||
|
||||
static string format_string_imp(const char* msg, ...) {
|
||||
// we might need a second shot at this, so pre-emptivly make a copy
|
||||
struct GuardVAList {
|
||||
va_list& target;
|
||||
bool active = true;
|
||||
GuardVAList(va_list& target) : target(target), active(true) {}
|
||||
void clear() {
|
||||
if (active)
|
||||
va_end(target);
|
||||
active = false;
|
||||
}
|
||||
~GuardVAList() {
|
||||
if (active)
|
||||
va_end(target);
|
||||
}
|
||||
};
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
GuardVAList args_guard(args);
|
||||
|
||||
va_list args_cp;
|
||||
va_copy(args_cp, args);
|
||||
GuardVAList args_copy_guard(args_cp);
|
||||
|
||||
std::string result;
|
||||
|
||||
array<char, 256> local_buff;
|
||||
size_t size_with_null = local_buff.size();
|
||||
auto ret = ::vsnprintf(local_buff.data(), size_with_null, msg, args_cp);
|
||||
|
||||
args_copy_guard.clear();
|
||||
|
||||
// handle empty expansion
|
||||
if (ret == 0)
|
||||
return result;
|
||||
if (static_cast<size_t>(ret) < size_with_null) {
|
||||
result.assign(local_buff.data(), static_cast<size_t>(ret));
|
||||
return result;
|
||||
}
|
||||
|
||||
// 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_with_null = static_cast<size_t>(ret) + 1;
|
||||
result.__resize_default_init(size_with_null - 1);
|
||||
ret = ::vsnprintf(&result[0], size_with_null, msg, args);
|
||||
_LIBCPP_ASSERT(static_cast<size_t>(ret) == (size_with_null - 1), "TODO");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* unwrap(string const& s) { return s.c_str(); }
|
||||
const char* unwrap(path const& p) { return p.native().c_str(); }
|
||||
template <class Arg>
|
||||
Arg const& unwrap(Arg const& a) {
|
||||
static_assert(!is_class<Arg>::value, "cannot pass class here");
|
||||
return a;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
string format_string(const char* fmt, Args const&... args) {
|
||||
return format_string_imp(fmt, unwrap(args)...);
|
||||
}
|
||||
|
||||
error_code capture_errno() {
|
||||
_LIBCPP_ASSERT(errno, "Expected errno to be non-zero");
|
||||
return error_code(errno, generic_category());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T error_value();
|
||||
template <>
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX11 void error_value<void>() {}
|
||||
template <>
|
||||
bool error_value<bool>() {
|
||||
return false;
|
||||
}
|
||||
template <>
|
||||
uintmax_t error_value<uintmax_t>() {
|
||||
return uintmax_t(-1);
|
||||
}
|
||||
template <>
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX11 file_time_type error_value<file_time_type>() {
|
||||
return file_time_type::min();
|
||||
}
|
||||
template <>
|
||||
path error_value<path>() {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct ErrorHandler {
|
||||
const char* func_name;
|
||||
error_code* ec = nullptr;
|
||||
const path* p1 = nullptr;
|
||||
const path* p2 = nullptr;
|
||||
|
||||
ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr,
|
||||
const path* p2 = nullptr)
|
||||
: func_name(fname), ec(ec), p1(p1), p2(p2) {
|
||||
if (ec)
|
||||
ec->clear();
|
||||
}
|
||||
|
||||
T report(const error_code& m_ec) const {
|
||||
if (ec) {
|
||||
*ec = m_ec;
|
||||
return error_value<T>();
|
||||
}
|
||||
string what = string("in ") + func_name;
|
||||
switch (bool(p1) + bool(p2)) {
|
||||
case 0:
|
||||
__throw_filesystem_error(what, m_ec);
|
||||
case 1:
|
||||
__throw_filesystem_error(what, *p1, m_ec);
|
||||
case 2:
|
||||
__throw_filesystem_error(what, *p1, *p2, m_ec);
|
||||
}
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
T report(const error_code& m_ec, const char* msg, Args const&... args) const {
|
||||
if (ec) {
|
||||
*ec = m_ec;
|
||||
return error_value<T>();
|
||||
}
|
||||
string what =
|
||||
string("in ") + func_name + ": " + format_string(msg, args...);
|
||||
switch (bool(p1) + bool(p2)) {
|
||||
case 0:
|
||||
__throw_filesystem_error(what, m_ec);
|
||||
case 1:
|
||||
__throw_filesystem_error(what, *p1, m_ec);
|
||||
case 2:
|
||||
__throw_filesystem_error(what, *p1, *p2, m_ec);
|
||||
}
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
|
||||
T report(errc const& err) const { return report(make_error_code(err)); }
|
||||
|
||||
template <class... Args>
|
||||
T report(errc const& err, const char* msg, Args const&... args) const {
|
||||
return report(make_error_code(err), msg, args...);
|
||||
}
|
||||
|
||||
private:
|
||||
ErrorHandler(ErrorHandler const&) = delete;
|
||||
ErrorHandler& operator=(ErrorHandler const&) = delete;
|
||||
};
|
||||
|
||||
using chrono::duration;
|
||||
using chrono::duration_cast;
|
||||
|
||||
using TimeSpec = struct ::timespec;
|
||||
using StatT = struct ::stat;
|
||||
|
||||
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:
|
||||
#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR)
|
||||
static constexpr 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 constexpr 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");
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class FileTimeT, class TimeT>
|
||||
struct time_util_base<FileTimeT, TimeT, true> {
|
||||
using rep = typename FileTimeT::rep;
|
||||
using fs_duration = typename FileTimeT::duration;
|
||||
using fs_seconds = duration<rep>;
|
||||
using fs_nanoseconds = duration<rep, nano>;
|
||||
using fs_microseconds = duration<rep, micro>;
|
||||
|
||||
static const rep max_seconds;
|
||||
static const rep max_nsec;
|
||||
static const rep min_seconds;
|
||||
static const rep min_nsec_timespec;
|
||||
};
|
||||
|
||||
template <class FileTimeT, class TimeT>
|
||||
const typename FileTimeT::rep
|
||||
time_util_base<FileTimeT, TimeT, true>::max_seconds =
|
||||
duration_cast<fs_seconds>(FileTimeT::duration::max()).count();
|
||||
|
||||
template <class FileTimeT, class TimeT>
|
||||
const typename FileTimeT::rep time_util_base<FileTimeT, TimeT, true>::max_nsec =
|
||||
duration_cast<fs_nanoseconds>(FileTimeT::duration::max() -
|
||||
fs_seconds(max_seconds))
|
||||
.count();
|
||||
|
||||
template <class FileTimeT, class TimeT>
|
||||
const typename FileTimeT::rep
|
||||
time_util_base<FileTimeT, TimeT, true>::min_seconds =
|
||||
duration_cast<fs_seconds>(FileTimeT::duration::min()).count();
|
||||
|
||||
template <class FileTimeT, class TimeT>
|
||||
const typename FileTimeT::rep
|
||||
time_util_base<FileTimeT, TimeT, true>::min_nsec_timespec =
|
||||
duration_cast<fs_nanoseconds>((FileTimeT::duration::min() -
|
||||
fs_seconds(min_seconds)) +
|
||||
fs_seconds(1))
|
||||
.count();
|
||||
|
||||
template <class FileTimeT, class TimeT, class TimeSpecT>
|
||||
struct time_util : time_util_base<FileTimeT, TimeT> {
|
||||
using Base = time_util_base<FileTimeT, TimeT>;
|
||||
using Base::max_nsec;
|
||||
using Base::max_seconds;
|
||||
using Base::min_nsec_timespec;
|
||||
using Base::min_seconds;
|
||||
|
||||
using typename Base::fs_duration;
|
||||
using typename Base::fs_microseconds;
|
||||
using typename Base::fs_nanoseconds;
|
||||
using typename Base::fs_seconds;
|
||||
|
||||
public:
|
||||
template <class CType, class ChronoType>
|
||||
static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool checked_set(CType* out,
|
||||
ChronoType time) {
|
||||
using Lim = numeric_limits<CType>;
|
||||
if (time > Lim::max() || time < Lim::min())
|
||||
return false;
|
||||
*out = static_cast<CType>(time);
|
||||
return true;
|
||||
}
|
||||
|
||||
static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) {
|
||||
if (tm.tv_sec >= 0) {
|
||||
return tm.tv_sec < max_seconds ||
|
||||
(tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec);
|
||||
} else if (tm.tv_sec == (min_seconds - 1)) {
|
||||
return tm.tv_nsec >= min_nsec_timespec;
|
||||
} else {
|
||||
return tm.tv_sec >= min_seconds;
|
||||
}
|
||||
}
|
||||
|
||||
static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) {
|
||||
auto secs = duration_cast<fs_seconds>(tm.time_since_epoch());
|
||||
auto nsecs = duration_cast<fs_nanoseconds>(tm.time_since_epoch() - secs);
|
||||
if (nsecs.count() < 0) {
|
||||
secs = secs + fs_seconds(1);
|
||||
nsecs = nsecs + fs_seconds(1);
|
||||
}
|
||||
using TLim = numeric_limits<TimeT>;
|
||||
if (secs.count() >= 0)
|
||||
return secs.count() <= TLim::max();
|
||||
return secs.count() >= TLim::min();
|
||||
}
|
||||
|
||||
static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT
|
||||
convert_from_timespec(TimeSpecT tm) {
|
||||
if (tm.tv_sec >= 0 || tm.tv_nsec == 0) {
|
||||
return FileTimeT(fs_seconds(tm.tv_sec) +
|
||||
duration_cast<fs_duration>(fs_nanoseconds(tm.tv_nsec)));
|
||||
} else { // tm.tv_sec < 0
|
||||
auto adj_subsec = duration_cast<fs_duration>(fs_seconds(1) -
|
||||
fs_nanoseconds(tm.tv_nsec));
|
||||
auto Dur = fs_seconds(tm.tv_sec + 1) - adj_subsec;
|
||||
return FileTimeT(Dur);
|
||||
}
|
||||
}
|
||||
|
||||
template <class SubSecT>
|
||||
static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool
|
||||
set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) {
|
||||
auto dur = tp.time_since_epoch();
|
||||
auto sec_dur = duration_cast<fs_seconds>(dur);
|
||||
auto subsec_dur = duration_cast<fs_nanoseconds>(dur - sec_dur);
|
||||
// The tv_nsec and tv_usec fields must not be negative so adjust accordingly
|
||||
if (subsec_dur.count() < 0) {
|
||||
if (sec_dur.count() > min_seconds) {
|
||||
sec_dur = sec_dur - fs_seconds(1);
|
||||
subsec_dur = subsec_dur + fs_seconds(1);
|
||||
} else {
|
||||
subsec_dur = fs_nanoseconds::zero();
|
||||
}
|
||||
}
|
||||
return checked_set(sec_out, sec_dur.count()) &&
|
||||
checked_set(subsec_out, subsec_dur.count());
|
||||
}
|
||||
static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool convert_to_timespec(TimeSpecT& dest,
|
||||
FileTimeT tp) {
|
||||
if (!is_representable(tp))
|
||||
return false;
|
||||
return set_times_checked(&dest.tv_sec, &dest.tv_nsec, tp);
|
||||
}
|
||||
};
|
||||
|
||||
using fs_time = time_util<file_time_type, time_t, TimeSpec>;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; }
|
||||
TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; }
|
||||
#else
|
||||
TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; }
|
||||
TimeSpec extract_atime(StatT const& st) { return st.st_atim; }
|
||||
#endif
|
||||
|
||||
// allow the utimes implementation to compile even it we're not going
|
||||
// to use it.
|
||||
|
||||
bool posix_utimes(const path& p, std::array<TimeSpec, 2> const& TS,
|
||||
error_code& ec) {
|
||||
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);
|
||||
};
|
||||
struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)},
|
||||
{TS[1].tv_sec, Convert(TS[1].tv_nsec)}};
|
||||
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
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // end namespace detail
|
||||
|
||||
_LIBCPP_END_NAMESPACE_FILESYSTEM
|
||||
|
||||
#endif // FILESYSTEM_COMMON_H
|
||||
54
lib/libcxx/src/filesystem/int128_builtins.cpp
Normal file
54
lib/libcxx/src/filesystem/int128_builtins.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*===-- int128_builtins.cpp - Implement __muloti4 --------------------------===
|
||||
*
|
||||
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
* See https://llvm.org/LICENSE.txt for license information.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __muloti4, and is stolen from the compiler_rt library.
|
||||
*
|
||||
* FIXME: we steal and re-compile it into filesystem, which uses __int128_t,
|
||||
* and requires this builtin when sanitized. See llvm.org/PR30643
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
#include "__config"
|
||||
#include "climits"
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_INT128)
|
||||
|
||||
extern "C" __attribute__((no_sanitize("undefined"))) _LIBCPP_FUNC_VIS
|
||||
__int128_t __muloti4(__int128_t a, __int128_t b, int* overflow) {
|
||||
const int N = (int)(sizeof(__int128_t) * CHAR_BIT);
|
||||
const __int128_t MIN = (__int128_t)1 << (N - 1);
|
||||
const __int128_t MAX = ~MIN;
|
||||
*overflow = 0;
|
||||
__int128_t result = a * b;
|
||||
if (a == MIN) {
|
||||
if (b != 0 && b != 1)
|
||||
*overflow = 1;
|
||||
return result;
|
||||
}
|
||||
if (b == MIN) {
|
||||
if (a != 0 && a != 1)
|
||||
*overflow = 1;
|
||||
return result;
|
||||
}
|
||||
__int128_t sa = a >> (N - 1);
|
||||
__int128_t abs_a = (a ^ sa) - sa;
|
||||
__int128_t sb = b >> (N - 1);
|
||||
__int128_t abs_b = (b ^ sb) - sb;
|
||||
if (abs_a < 2 || abs_b < 2)
|
||||
return result;
|
||||
if (sa == sb) {
|
||||
if (abs_a > MAX / abs_b)
|
||||
*overflow = 1;
|
||||
} else {
|
||||
if (abs_a > MIN / -abs_b)
|
||||
*overflow = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
1782
lib/libcxx/src/filesystem/operations.cpp
Normal file
1782
lib/libcxx/src/filesystem/operations.cpp
Normal file
File diff suppressed because it is too large
Load Diff
25
lib/libcxx/src/functional.cpp
Normal file
25
lib/libcxx/src/functional.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
//===----------------------- functional.cpp -------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "functional"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifdef _LIBCPP_ABI_BAD_FUNCTION_CALL_KEY_FUNCTION
|
||||
bad_function_call::~bad_function_call() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
bad_function_call::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::bad_function_call";
|
||||
}
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
277
lib/libcxx/src/future.cpp
Normal file
277
lib/libcxx/src/future.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
//===------------------------- future.cpp ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "__config"
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
|
||||
#include "future"
|
||||
#include "string"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
class _LIBCPP_HIDDEN __future_error_category
|
||||
: public __do_message
|
||||
{
|
||||
public:
|
||||
virtual const char* name() const _NOEXCEPT;
|
||||
virtual string message(int ev) const;
|
||||
};
|
||||
|
||||
const char*
|
||||
__future_error_category::name() const _NOEXCEPT
|
||||
{
|
||||
return "future";
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wswitch"
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wswitch"
|
||||
#endif
|
||||
|
||||
string
|
||||
__future_error_category::message(int ev) const
|
||||
{
|
||||
switch (static_cast<future_errc>(ev))
|
||||
{
|
||||
case future_errc(0): // For backwards compatibility with C++11 (LWG 2056)
|
||||
case future_errc::broken_promise:
|
||||
return string("The associated promise has been destructed prior "
|
||||
"to the associated state becoming ready.");
|
||||
case future_errc::future_already_retrieved:
|
||||
return string("The future has already been retrieved from "
|
||||
"the promise or packaged_task.");
|
||||
case future_errc::promise_already_satisfied:
|
||||
return string("The state of the promise has already been set.");
|
||||
case future_errc::no_state:
|
||||
return string("Operation not permitted on an object without "
|
||||
"an associated state.");
|
||||
}
|
||||
return string("unspecified future_errc value\n");
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
const error_category&
|
||||
future_category() _NOEXCEPT
|
||||
{
|
||||
static __future_error_category __f;
|
||||
return __f;
|
||||
}
|
||||
|
||||
future_error::future_error(error_code __ec)
|
||||
: logic_error(__ec.message()),
|
||||
__ec_(__ec)
|
||||
{
|
||||
}
|
||||
|
||||
future_error::~future_error() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
__assoc_sub_state::__on_zero_shared() _NOEXCEPT
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void
|
||||
__assoc_sub_state::set_value()
|
||||
{
|
||||
unique_lock<mutex> __lk(__mut_);
|
||||
if (__has_value())
|
||||
__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_NO_EXCEPTIONS
|
||||
if (!__state_->__has_value() && __state_->use_count() > 1)
|
||||
__state_->set_exception(make_exception_ptr(
|
||||
future_error(make_error_code(future_errc::broken_promise))
|
||||
));
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
__state_->__release_shared();
|
||||
}
|
||||
}
|
||||
|
||||
future<void>
|
||||
promise<void>::get_future()
|
||||
{
|
||||
if (__state_ == nullptr)
|
||||
__throw_future_error(future_errc::no_state);
|
||||
return future<void>(__state_);
|
||||
}
|
||||
|
||||
void
|
||||
promise<void>::set_value()
|
||||
{
|
||||
if (__state_ == nullptr)
|
||||
__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
|
||||
561
lib/libcxx/src/hash.cpp
Normal file
561
lib/libcxx/src/hash.cpp
Normal file
@@ -0,0 +1,561 @@
|
||||
//===-------------------------- hash.cpp ----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "__hash_table"
|
||||
#include "algorithm"
|
||||
#include "stdexcept"
|
||||
#include "type_traits"
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare"
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace {
|
||||
|
||||
// handle all next_prime(i) for i in [1, 210), special case 0
|
||||
const unsigned small_primes[] =
|
||||
{
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
5,
|
||||
7,
|
||||
11,
|
||||
13,
|
||||
17,
|
||||
19,
|
||||
23,
|
||||
29,
|
||||
31,
|
||||
37,
|
||||
41,
|
||||
43,
|
||||
47,
|
||||
53,
|
||||
59,
|
||||
61,
|
||||
67,
|
||||
71,
|
||||
73,
|
||||
79,
|
||||
83,
|
||||
89,
|
||||
97,
|
||||
101,
|
||||
103,
|
||||
107,
|
||||
109,
|
||||
113,
|
||||
127,
|
||||
131,
|
||||
137,
|
||||
139,
|
||||
149,
|
||||
151,
|
||||
157,
|
||||
163,
|
||||
167,
|
||||
173,
|
||||
179,
|
||||
181,
|
||||
191,
|
||||
193,
|
||||
197,
|
||||
199,
|
||||
211
|
||||
};
|
||||
|
||||
// potential primes = 210*k + indices[i], k >= 1
|
||||
// these numbers are not divisible by 2, 3, 5 or 7
|
||||
// (or any integer 2 <= j <= 10 for that matter).
|
||||
const unsigned indices[] =
|
||||
{
|
||||
1,
|
||||
11,
|
||||
13,
|
||||
17,
|
||||
19,
|
||||
23,
|
||||
29,
|
||||
31,
|
||||
37,
|
||||
41,
|
||||
43,
|
||||
47,
|
||||
53,
|
||||
59,
|
||||
61,
|
||||
67,
|
||||
71,
|
||||
73,
|
||||
79,
|
||||
83,
|
||||
89,
|
||||
97,
|
||||
101,
|
||||
103,
|
||||
107,
|
||||
109,
|
||||
113,
|
||||
121,
|
||||
127,
|
||||
131,
|
||||
137,
|
||||
139,
|
||||
143,
|
||||
149,
|
||||
151,
|
||||
157,
|
||||
163,
|
||||
167,
|
||||
169,
|
||||
173,
|
||||
179,
|
||||
181,
|
||||
187,
|
||||
191,
|
||||
193,
|
||||
197,
|
||||
199,
|
||||
209
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// Returns: If n == 0, returns 0. Else returns the lowest prime number that
|
||||
// is greater than or equal to n.
|
||||
//
|
||||
// The algorithm creates a list of small primes, plus an open-ended list of
|
||||
// potential primes. All prime numbers are potential prime numbers. However
|
||||
// some potential prime numbers are not prime. In an ideal world, all potential
|
||||
// prime numbers would be prime. Candidate prime numbers are chosen as the next
|
||||
// highest potential prime. Then this number is tested for prime by dividing it
|
||||
// by all potential prime numbers less than the sqrt of the candidate.
|
||||
//
|
||||
// This implementation defines potential primes as those numbers not divisible
|
||||
// by 2, 3, 5, and 7. Other (common) implementations define potential primes
|
||||
// as those not divisible by 2. A few other implementations define potential
|
||||
// primes as those not divisible by 2 or 3. By raising the number of small
|
||||
// primes which the potential prime is not divisible by, the set of potential
|
||||
// primes more closely approximates the set of prime numbers. And thus there
|
||||
// are fewer potential primes to search, and fewer potential primes to divide
|
||||
// against.
|
||||
|
||||
template <size_t _Sz = sizeof(size_t)>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename enable_if<_Sz == 4, void>::type
|
||||
__check_for_overflow(size_t N)
|
||||
{
|
||||
if (N > 0xFFFFFFFB)
|
||||
__throw_overflow_error("__next_prime overflow");
|
||||
}
|
||||
|
||||
template <size_t _Sz = sizeof(size_t)>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename enable_if<_Sz == 8, void>::type
|
||||
__check_for_overflow(size_t N)
|
||||
{
|
||||
if (N > 0xFFFFFFFFFFFFFFC5ull)
|
||||
__throw_overflow_error("__next_prime overflow");
|
||||
}
|
||||
|
||||
size_t
|
||||
__next_prime(size_t n)
|
||||
{
|
||||
const size_t L = 210;
|
||||
const size_t N = sizeof(small_primes) / sizeof(small_primes[0]);
|
||||
// If n is small enough, search in small_primes
|
||||
if (n <= small_primes[N-1])
|
||||
return *std::lower_bound(small_primes, small_primes + N, n);
|
||||
// Else n > largest small_primes
|
||||
// Check for overflow
|
||||
__check_for_overflow(n);
|
||||
// Start searching list of potential primes: L * k0 + indices[in]
|
||||
const size_t M = sizeof(indices) / sizeof(indices[0]);
|
||||
// Select first potential prime >= n
|
||||
// Known a-priori n >= L
|
||||
size_t k0 = n / L;
|
||||
size_t in = static_cast<size_t>(std::lower_bound(indices, indices + M, n - k0 * L)
|
||||
- indices);
|
||||
n = L * k0 + indices[in];
|
||||
while (true)
|
||||
{
|
||||
// Divide n by all primes or potential primes (i) until:
|
||||
// 1. The division is even, so try next potential prime.
|
||||
// 2. The i > sqrt(n), in which case n is prime.
|
||||
// It is known a-priori that n is not divisible by 2, 3, 5 or 7,
|
||||
// so don't test those (j == 5 -> divide by 11 first). And the
|
||||
// potential primes start with 211, so don't test against the last
|
||||
// small prime.
|
||||
for (size_t j = 5; j < N - 1; ++j)
|
||||
{
|
||||
const std::size_t p = small_primes[j];
|
||||
const std::size_t q = n / p;
|
||||
if (q < p)
|
||||
return n;
|
||||
if (n == q * p)
|
||||
goto next;
|
||||
}
|
||||
// n wasn't divisible by small primes, try potential primes
|
||||
{
|
||||
size_t i = 211;
|
||||
while (true)
|
||||
{
|
||||
std::size_t q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 10;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 8;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 8;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 6;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 4;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 2;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
i += 10;
|
||||
q = n / i;
|
||||
if (q < i)
|
||||
return n;
|
||||
if (n == q * i)
|
||||
break;
|
||||
|
||||
// This will loop i to the next "plane" of potential primes
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
next:
|
||||
// n is not prime. Increment n to next potential prime.
|
||||
if (++in == M)
|
||||
{
|
||||
++k0;
|
||||
in = 0;
|
||||
}
|
||||
n = L * k0 + indices[in];
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
51
lib/libcxx/src/include/apple_availability.h
Normal file
51
lib/libcxx/src/include/apple_availability.h
Normal file
@@ -0,0 +1,51 @@
|
||||
//===------------------------ apple_availability.h ------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef _LIBCPP_SRC_INCLUDE_APPLE_AVAILABILITY_H
|
||||
#define _LIBCPP_SRC_INCLUDE_APPLE_AVAILABILITY_H
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
|
||||
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101300
|
||||
#define _LIBCPP_USE_UTIMENSAT
|
||||
#endif
|
||||
#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__)
|
||||
#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 110000
|
||||
#define _LIBCPP_USE_UTIMENSAT
|
||||
#endif
|
||||
#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__)
|
||||
#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 110000
|
||||
#define _LIBCPP_USE_UTIMENSAT
|
||||
#endif
|
||||
#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__)
|
||||
#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 40000
|
||||
#define _LIBCPP_USE_UTIMENSAT
|
||||
#endif
|
||||
#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__
|
||||
|
||||
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
|
||||
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200
|
||||
#define _LIBCPP_USE_CLOCK_GETTIME
|
||||
#endif
|
||||
#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__)
|
||||
#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 100000
|
||||
#define _LIBCPP_USE_CLOCK_GETTIME
|
||||
#endif
|
||||
#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__)
|
||||
#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 100000
|
||||
#define _LIBCPP_USE_CLOCK_GETTIME
|
||||
#endif
|
||||
#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__)
|
||||
#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 30000
|
||||
#define _LIBCPP_USE_CLOCK_GETTIME
|
||||
#endif
|
||||
#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
#endif // _LIBCPP_SRC_INCLUDE_APPLE_AVAILABILITY_H
|
||||
176
lib/libcxx/src/include/atomic_support.h
Normal file
176
lib/libcxx/src/include/atomic_support.h
Normal file
@@ -0,0 +1,176 @@
|
||||
//===----------------------------------------------------------------------===////
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===////
|
||||
|
||||
#ifndef ATOMIC_SUPPORT_H
|
||||
#define ATOMIC_SUPPORT_H
|
||||
|
||||
#include "__config"
|
||||
#include "memory" // for __libcpp_relaxed_load
|
||||
|
||||
#if defined(__clang__) && __has_builtin(__atomic_load_n) \
|
||||
&& __has_builtin(__atomic_store_n) \
|
||||
&& __has_builtin(__atomic_add_fetch) \
|
||||
&& __has_builtin(__atomic_exchange_n) \
|
||||
&& __has_builtin(__atomic_compare_exchange_n) \
|
||||
&& defined(__ATOMIC_RELAXED) \
|
||||
&& defined(__ATOMIC_CONSUME) \
|
||||
&& defined(__ATOMIC_ACQUIRE) \
|
||||
&& defined(__ATOMIC_RELEASE) \
|
||||
&& defined(__ATOMIC_ACQ_REL) \
|
||||
&& defined(__ATOMIC_SEQ_CST)
|
||||
# define _LIBCPP_HAS_ATOMIC_BUILTINS
|
||||
#elif !defined(__clang__) && defined(_GNUC_VER) && _GNUC_VER >= 407
|
||||
# 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 __order = _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
|
||||
41
lib/libcxx/src/include/config_elast.h
Normal file
41
lib/libcxx/src/include/config_elast.h
Normal file
@@ -0,0 +1,41 @@
|
||||
//===----------------------- config_elast.h -------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP_CONFIG_ELAST
|
||||
#define _LIBCPP_CONFIG_ELAST
|
||||
|
||||
#include <__config>
|
||||
|
||||
#if defined(_LIBCPP_MSVCRT_LIKE)
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if defined(ELAST)
|
||||
#define _LIBCPP_ELAST ELAST
|
||||
#elif defined(_NEWLIB_VERSION)
|
||||
#define _LIBCPP_ELAST __ELASTERROR
|
||||
#elif defined(__Fuchsia__)
|
||||
// No _LIBCPP_ELAST needed on Fuchsia
|
||||
#elif defined(__wasi__)
|
||||
// No _LIBCPP_ELAST needed on WASI
|
||||
#elif defined(__linux__) || defined(_LIBCPP_HAS_MUSL_LIBC)
|
||||
#define _LIBCPP_ELAST 4095
|
||||
#elif defined(__APPLE__)
|
||||
// No _LIBCPP_ELAST needed on Apple
|
||||
#elif defined(__sun__)
|
||||
#define _LIBCPP_ELAST ESTALE
|
||||
#elif defined(_LIBCPP_MSVCRT_LIKE)
|
||||
#define _LIBCPP_ELAST (_sys_nerr - 1)
|
||||
#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
|
||||
127
lib/libcxx/src/include/refstring.h
Normal file
127
lib/libcxx/src/include/refstring.h
Normal file
@@ -0,0 +1,127 @@
|
||||
//===------------------------ __refstring ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP_REFSTRING_H
|
||||
#define _LIBCPP_REFSTRING_H
|
||||
|
||||
#include <__config>
|
||||
#include <stdexcept>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#ifdef __APPLE__
|
||||
#include <dlfcn.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
#include "atomic_support.h"
|
||||
|
||||
_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(__APPLE__)
|
||||
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 {
|
||||
#ifdef __APPLE__
|
||||
return __imp_ != get_gcc_empty_string_storage();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif //_LIBCPP_REFSTRING_H
|
||||
457
lib/libcxx/src/ios.cpp
Normal file
457
lib/libcxx/src/ios.cpp
Normal file
@@ -0,0 +1,457 @@
|
||||
//===-------------------------- ios.cpp -----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "__config"
|
||||
|
||||
#include "ios"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "__locale"
|
||||
#include "algorithm"
|
||||
#include "include/config_elast.h"
|
||||
#include "istream"
|
||||
#include "limits"
|
||||
#include "memory"
|
||||
#include "new"
|
||||
#include "streambuf"
|
||||
#include "string"
|
||||
#include "__undef_macros"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios<wchar_t>;
|
||||
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf<wchar_t>;
|
||||
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream<wchar_t>;
|
||||
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream<wchar_t>;
|
||||
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_iostream<char>;
|
||||
|
||||
class _LIBCPP_HIDDEN __iostream_category
|
||||
: public __do_message
|
||||
{
|
||||
public:
|
||||
virtual const char* name() const _NOEXCEPT;
|
||||
virtual string message(int ev) const;
|
||||
};
|
||||
|
||||
const char*
|
||||
__iostream_category::name() const _NOEXCEPT
|
||||
{
|
||||
return "iostream";
|
||||
}
|
||||
|
||||
string
|
||||
__iostream_category::message(int ev) const
|
||||
{
|
||||
if (ev != static_cast<int>(io_errc::stream)
|
||||
#ifdef _LIBCPP_ELAST
|
||||
&& ev <= _LIBCPP_ELAST
|
||||
#endif // _LIBCPP_ELAST
|
||||
)
|
||||
return __do_message::message(ev);
|
||||
return string("unspecified iostream_category error");
|
||||
}
|
||||
|
||||
const error_category&
|
||||
iostream_category() _NOEXCEPT
|
||||
{
|
||||
static __iostream_category s;
|
||||
return s;
|
||||
}
|
||||
|
||||
// ios_base::failure
|
||||
|
||||
ios_base::failure::failure(const string& msg, const error_code& ec)
|
||||
: system_error(ec, msg)
|
||||
{
|
||||
}
|
||||
|
||||
ios_base::failure::failure(const char* msg, const error_code& ec)
|
||||
: system_error(ec, msg)
|
||||
{
|
||||
}
|
||||
|
||||
ios_base::failure::~failure() throw()
|
||||
{
|
||||
}
|
||||
|
||||
// ios_base locale
|
||||
|
||||
const ios_base::fmtflags ios_base::boolalpha;
|
||||
const ios_base::fmtflags ios_base::dec;
|
||||
const ios_base::fmtflags ios_base::fixed;
|
||||
const ios_base::fmtflags ios_base::hex;
|
||||
const ios_base::fmtflags ios_base::internal;
|
||||
const ios_base::fmtflags ios_base::left;
|
||||
const ios_base::fmtflags ios_base::oct;
|
||||
const ios_base::fmtflags ios_base::right;
|
||||
const ios_base::fmtflags ios_base::scientific;
|
||||
const ios_base::fmtflags ios_base::showbase;
|
||||
const ios_base::fmtflags ios_base::showpoint;
|
||||
const ios_base::fmtflags ios_base::showpos;
|
||||
const ios_base::fmtflags ios_base::skipws;
|
||||
const ios_base::fmtflags ios_base::unitbuf;
|
||||
const ios_base::fmtflags ios_base::uppercase;
|
||||
const ios_base::fmtflags ios_base::adjustfield;
|
||||
const ios_base::fmtflags ios_base::basefield;
|
||||
const ios_base::fmtflags ios_base::floatfield;
|
||||
|
||||
const ios_base::iostate ios_base::badbit;
|
||||
const ios_base::iostate ios_base::eofbit;
|
||||
const ios_base::iostate ios_base::failbit;
|
||||
const ios_base::iostate ios_base::goodbit;
|
||||
|
||||
const ios_base::openmode ios_base::app;
|
||||
const ios_base::openmode ios_base::ate;
|
||||
const ios_base::openmode ios_base::binary;
|
||||
const ios_base::openmode ios_base::in;
|
||||
const ios_base::openmode ios_base::out;
|
||||
const ios_base::openmode ios_base::trunc;
|
||||
|
||||
void
|
||||
ios_base::__call_callbacks(event ev)
|
||||
{
|
||||
for (size_t i = __event_size_; i;)
|
||||
{
|
||||
--i;
|
||||
__fn_[i](ev, *this, __index_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// locale
|
||||
|
||||
locale
|
||||
ios_base::imbue(const locale& newloc)
|
||||
{
|
||||
static_assert(sizeof(locale) == sizeof(__loc_), "");
|
||||
locale& loc_storage = *reinterpret_cast<locale*>(&__loc_);
|
||||
locale oldloc = loc_storage;
|
||||
loc_storage = newloc;
|
||||
__call_callbacks(imbue_event);
|
||||
return oldloc;
|
||||
}
|
||||
|
||||
locale
|
||||
ios_base::getloc() const
|
||||
{
|
||||
const locale& loc_storage = *reinterpret_cast<const locale*>(&__loc_);
|
||||
return loc_storage;
|
||||
}
|
||||
|
||||
// xalloc
|
||||
#if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
atomic<int> ios_base::__xindex_ = ATOMIC_VAR_INIT(0);
|
||||
#else
|
||||
int ios_base::__xindex_ = 0;
|
||||
#endif
|
||||
|
||||
template <typename _Tp>
|
||||
static size_t __ios_new_cap(size_t __req_size, size_t __current_cap)
|
||||
{ // Precondition: __req_size > __current_cap
|
||||
const size_t mx = std::numeric_limits<size_t>::max() / sizeof(_Tp);
|
||||
if (__req_size < mx/2)
|
||||
return _VSTD::max(2 * __current_cap, __req_size);
|
||||
else
|
||||
return mx;
|
||||
}
|
||||
|
||||
int
|
||||
ios_base::xalloc()
|
||||
{
|
||||
return __xindex_++;
|
||||
}
|
||||
|
||||
long&
|
||||
ios_base::iword(int index)
|
||||
{
|
||||
size_t req_size = static_cast<size_t>(index)+1;
|
||||
if (req_size > __iarray_cap_)
|
||||
{
|
||||
size_t newcap = __ios_new_cap<long>(req_size, __iarray_cap_);
|
||||
long* iarray = static_cast<long*>(realloc(__iarray_, newcap * sizeof(long)));
|
||||
if (iarray == 0)
|
||||
{
|
||||
setstate(badbit);
|
||||
static long error;
|
||||
error = 0;
|
||||
return error;
|
||||
}
|
||||
__iarray_ = iarray;
|
||||
for (long* p = __iarray_ + __iarray_size_; p < __iarray_ + newcap; ++p)
|
||||
*p = 0;
|
||||
__iarray_cap_ = newcap;
|
||||
}
|
||||
__iarray_size_ = max<size_t>(__iarray_size_, req_size);
|
||||
return __iarray_[index];
|
||||
}
|
||||
|
||||
void*&
|
||||
ios_base::pword(int index)
|
||||
{
|
||||
size_t req_size = static_cast<size_t>(index)+1;
|
||||
if (req_size > __parray_cap_)
|
||||
{
|
||||
size_t newcap = __ios_new_cap<void *>(req_size, __iarray_cap_);
|
||||
void** parray = static_cast<void**>(realloc(__parray_, newcap * sizeof(void *)));
|
||||
if (parray == 0)
|
||||
{
|
||||
setstate(badbit);
|
||||
static void* error;
|
||||
error = 0;
|
||||
return error;
|
||||
}
|
||||
__parray_ = parray;
|
||||
for (void** p = __parray_ + __parray_size_; p < __parray_ + newcap; ++p)
|
||||
*p = 0;
|
||||
__parray_cap_ = newcap;
|
||||
}
|
||||
__parray_size_ = max<size_t>(__parray_size_, req_size);
|
||||
return __parray_[index];
|
||||
}
|
||||
|
||||
// register_callback
|
||||
|
||||
void
|
||||
ios_base::register_callback(event_callback fn, int index)
|
||||
{
|
||||
size_t req_size = __event_size_ + 1;
|
||||
if (req_size > __event_cap_)
|
||||
{
|
||||
size_t newcap = __ios_new_cap<event_callback>(req_size, __event_cap_);
|
||||
event_callback* fns = static_cast<event_callback*>(realloc(__fn_, newcap * sizeof(event_callback)));
|
||||
if (fns == 0)
|
||||
setstate(badbit);
|
||||
__fn_ = fns;
|
||||
int* indxs = static_cast<int *>(realloc(__index_, newcap * sizeof(int)));
|
||||
if (indxs == 0)
|
||||
setstate(badbit);
|
||||
__index_ = indxs;
|
||||
__event_cap_ = newcap;
|
||||
}
|
||||
__fn_[__event_size_] = fn;
|
||||
__index_[__event_size_] = index;
|
||||
++__event_size_;
|
||||
}
|
||||
|
||||
ios_base::~ios_base()
|
||||
{
|
||||
__call_callbacks(erase_event);
|
||||
locale& loc_storage = *reinterpret_cast<locale*>(&__loc_);
|
||||
loc_storage.~locale();
|
||||
free(__fn_);
|
||||
free(__index_);
|
||||
free(__iarray_);
|
||||
free(__parray_);
|
||||
}
|
||||
|
||||
// iostate
|
||||
|
||||
void
|
||||
ios_base::clear(iostate state)
|
||||
{
|
||||
if (__rdbuf_)
|
||||
__rdstate_ = state;
|
||||
else
|
||||
__rdstate_ = state | badbit;
|
||||
|
||||
if (((state | (__rdbuf_ ? goodbit : badbit)) & __exceptions_) != 0)
|
||||
__throw_failure("ios_base::clear");
|
||||
}
|
||||
|
||||
// init
|
||||
|
||||
void
|
||||
ios_base::init(void* sb)
|
||||
{
|
||||
__rdbuf_ = sb;
|
||||
__rdstate_ = __rdbuf_ ? goodbit : badbit;
|
||||
__exceptions_ = goodbit;
|
||||
__fmtflags_ = skipws | dec;
|
||||
__width_ = 0;
|
||||
__precision_ = 6;
|
||||
__fn_ = 0;
|
||||
__index_ = 0;
|
||||
__event_size_ = 0;
|
||||
__event_cap_ = 0;
|
||||
__iarray_ = 0;
|
||||
__iarray_size_ = 0;
|
||||
__iarray_cap_ = 0;
|
||||
__parray_ = 0;
|
||||
__parray_size_ = 0;
|
||||
__parray_cap_ = 0;
|
||||
::new(&__loc_) locale;
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::copyfmt(const ios_base& rhs)
|
||||
{
|
||||
// If we can't acquire the needed resources, throw bad_alloc (can't set badbit)
|
||||
// Don't alter *this until all needed resources are acquired
|
||||
unique_ptr<event_callback, void (*)(void*)> new_callbacks(0, free);
|
||||
unique_ptr<int, void (*)(void*)> new_ints(0, free);
|
||||
unique_ptr<long, void (*)(void*)> new_longs(0, free);
|
||||
unique_ptr<void*, void (*)(void*)> new_pointers(0, free);
|
||||
if (__event_cap_ < rhs.__event_size_)
|
||||
{
|
||||
size_t newesize = sizeof(event_callback) * rhs.__event_size_;
|
||||
new_callbacks.reset(static_cast<event_callback*>(malloc(newesize)));
|
||||
if (!new_callbacks)
|
||||
__throw_bad_alloc();
|
||||
|
||||
size_t newisize = sizeof(int) * rhs.__event_size_;
|
||||
new_ints.reset(static_cast<int *>(malloc(newisize)));
|
||||
if (!new_ints)
|
||||
__throw_bad_alloc();
|
||||
}
|
||||
if (__iarray_cap_ < rhs.__iarray_size_)
|
||||
{
|
||||
size_t newsize = sizeof(long) * rhs.__iarray_size_;
|
||||
new_longs.reset(static_cast<long*>(malloc(newsize)));
|
||||
if (!new_longs)
|
||||
__throw_bad_alloc();
|
||||
}
|
||||
if (__parray_cap_ < rhs.__parray_size_)
|
||||
{
|
||||
size_t newsize = sizeof(void*) * rhs.__parray_size_;
|
||||
new_pointers.reset(static_cast<void**>(malloc(newsize)));
|
||||
if (!new_pointers)
|
||||
__throw_bad_alloc();
|
||||
}
|
||||
// Got everything we need. Copy everything but __rdstate_, __rdbuf_ and __exceptions_
|
||||
__fmtflags_ = rhs.__fmtflags_;
|
||||
__precision_ = rhs.__precision_;
|
||||
__width_ = rhs.__width_;
|
||||
locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_);
|
||||
const locale& rhs_loc = *reinterpret_cast<const locale*>(&rhs.__loc_);
|
||||
lhs_loc = rhs_loc;
|
||||
if (__event_cap_ < rhs.__event_size_)
|
||||
{
|
||||
free(__fn_);
|
||||
__fn_ = new_callbacks.release();
|
||||
free(__index_);
|
||||
__index_ = new_ints.release();
|
||||
__event_cap_ = rhs.__event_size_;
|
||||
}
|
||||
for (__event_size_ = 0; __event_size_ < rhs.__event_size_; ++__event_size_)
|
||||
{
|
||||
__fn_[__event_size_] = rhs.__fn_[__event_size_];
|
||||
__index_[__event_size_] = rhs.__index_[__event_size_];
|
||||
}
|
||||
if (__iarray_cap_ < rhs.__iarray_size_)
|
||||
{
|
||||
free(__iarray_);
|
||||
__iarray_ = new_longs.release();
|
||||
__iarray_cap_ = rhs.__iarray_size_;
|
||||
}
|
||||
for (__iarray_size_ = 0; __iarray_size_ < rhs.__iarray_size_; ++__iarray_size_)
|
||||
__iarray_[__iarray_size_] = rhs.__iarray_[__iarray_size_];
|
||||
if (__parray_cap_ < rhs.__parray_size_)
|
||||
{
|
||||
free(__parray_);
|
||||
__parray_ = new_pointers.release();
|
||||
__parray_cap_ = rhs.__parray_size_;
|
||||
}
|
||||
for (__parray_size_ = 0; __parray_size_ < rhs.__parray_size_; ++__parray_size_)
|
||||
__parray_[__parray_size_] = rhs.__parray_[__parray_size_];
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::move(ios_base& rhs)
|
||||
{
|
||||
// *this is uninitialized
|
||||
__fmtflags_ = rhs.__fmtflags_;
|
||||
__precision_ = rhs.__precision_;
|
||||
__width_ = rhs.__width_;
|
||||
__rdstate_ = rhs.__rdstate_;
|
||||
__exceptions_ = rhs.__exceptions_;
|
||||
__rdbuf_ = 0;
|
||||
locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_);
|
||||
::new(&__loc_) locale(rhs_loc);
|
||||
__fn_ = rhs.__fn_;
|
||||
rhs.__fn_ = 0;
|
||||
__index_ = rhs.__index_;
|
||||
rhs.__index_ = 0;
|
||||
__event_size_ = rhs.__event_size_;
|
||||
rhs.__event_size_ = 0;
|
||||
__event_cap_ = rhs.__event_cap_;
|
||||
rhs.__event_cap_ = 0;
|
||||
__iarray_ = rhs.__iarray_;
|
||||
rhs.__iarray_ = 0;
|
||||
__iarray_size_ = rhs.__iarray_size_;
|
||||
rhs.__iarray_size_ = 0;
|
||||
__iarray_cap_ = rhs.__iarray_cap_;
|
||||
rhs.__iarray_cap_ = 0;
|
||||
__parray_ = rhs.__parray_;
|
||||
rhs.__parray_ = 0;
|
||||
__parray_size_ = rhs.__parray_size_;
|
||||
rhs.__parray_size_ = 0;
|
||||
__parray_cap_ = rhs.__parray_cap_;
|
||||
rhs.__parray_cap_ = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::swap(ios_base& rhs) _NOEXCEPT
|
||||
{
|
||||
_VSTD::swap(__fmtflags_, rhs.__fmtflags_);
|
||||
_VSTD::swap(__precision_, rhs.__precision_);
|
||||
_VSTD::swap(__width_, rhs.__width_);
|
||||
_VSTD::swap(__rdstate_, rhs.__rdstate_);
|
||||
_VSTD::swap(__exceptions_, rhs.__exceptions_);
|
||||
locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_);
|
||||
locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_);
|
||||
_VSTD::swap(lhs_loc, rhs_loc);
|
||||
_VSTD::swap(__fn_, rhs.__fn_);
|
||||
_VSTD::swap(__index_, rhs.__index_);
|
||||
_VSTD::swap(__event_size_, rhs.__event_size_);
|
||||
_VSTD::swap(__event_cap_, rhs.__event_cap_);
|
||||
_VSTD::swap(__iarray_, rhs.__iarray_);
|
||||
_VSTD::swap(__iarray_size_, rhs.__iarray_size_);
|
||||
_VSTD::swap(__iarray_cap_, rhs.__iarray_cap_);
|
||||
_VSTD::swap(__parray_, rhs.__parray_);
|
||||
_VSTD::swap(__parray_size_, rhs.__parray_size_);
|
||||
_VSTD::swap(__parray_cap_, rhs.__parray_cap_);
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::__set_badbit_and_consider_rethrow()
|
||||
{
|
||||
__rdstate_ |= badbit;
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
if (__exceptions_ & badbit)
|
||||
throw;
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
void
|
||||
ios_base::__set_failbit_and_consider_rethrow()
|
||||
{
|
||||
__rdstate_ |= failbit;
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
if (__exceptions_ & failbit)
|
||||
throw;
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
bool
|
||||
ios_base::sync_with_stdio(bool sync)
|
||||
{
|
||||
static bool previous_state = true;
|
||||
bool r = previous_state;
|
||||
previous_state = sync;
|
||||
return r;
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
159
lib/libcxx/src/iostream.cpp
Normal file
159
lib/libcxx/src/iostream.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
//===------------------------ iostream.cpp --------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "__std_stream"
|
||||
#include "__locale"
|
||||
#include "string"
|
||||
#include "new"
|
||||
|
||||
#define _str(s) #s
|
||||
#define str(s) _str(s)
|
||||
#define _LIBCPP_ABI_NAMESPACE_STR str(_LIBCPP_ABI_NAMESPACE)
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_STDIN
|
||||
_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;
|
||||
_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
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_STDOUT
|
||||
_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;
|
||||
_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
|
||||
|
||||
_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;
|
||||
_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;
|
||||
|
||||
_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
|
||||
;
|
||||
_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
|
||||
;
|
||||
|
||||
_LIBCPP_HIDDEN ios_base::Init __start_std_streams;
|
||||
|
||||
// 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();
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_STDIN
|
||||
istream* cin_ptr = ::new(cin) istream(::new(__cin) __stdinbuf <char>(stdin, &mb_cin));
|
||||
wistream* wcin_ptr = ::new(wcin) wistream(::new(__wcin) __stdinbuf <wchar_t>(stdin, &mb_wcin));
|
||||
#endif
|
||||
#ifndef _LIBCPP_HAS_NO_STDOUT
|
||||
ostream* cout_ptr = ::new(cout) ostream(::new(__cout) __stdoutbuf<char>(stdout, &mb_cout));
|
||||
wostream* wcout_ptr = ::new(wcout) wostream(::new(__wcout) __stdoutbuf<wchar_t>(stdout, &mb_wcout));
|
||||
#endif
|
||||
ostream* cerr_ptr = ::new(cerr) ostream(::new(__cerr) __stdoutbuf<char>(stderr, &mb_cerr));
|
||||
::new(clog) ostream(cerr_ptr->rdbuf());
|
||||
wostream* wcerr_ptr = ::new(wcerr) wostream(::new(__wcerr) __stdoutbuf<wchar_t>(stderr, &mb_wcerr));
|
||||
::new(wclog) wostream(wcerr_ptr->rdbuf());
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_STDIN) && !defined(_LIBCPP_HAS_NO_STDOUT)
|
||||
cin_ptr->tie(cout_ptr);
|
||||
wcin_ptr->tie(wcout_ptr);
|
||||
#endif
|
||||
_VSTD::unitbuf(*cerr_ptr);
|
||||
_VSTD::unitbuf(*wcerr_ptr);
|
||||
#ifndef _LIBCPP_HAS_NO_STDOUT
|
||||
cerr_ptr->tie(cout_ptr);
|
||||
wcerr_ptr->tie(wcout_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
DoIOSInit::~DoIOSInit()
|
||||
{
|
||||
#ifndef _LIBCPP_HAS_NO_STDOUT
|
||||
ostream* cout_ptr = reinterpret_cast<ostream*>(cout);
|
||||
wostream* wcout_ptr = reinterpret_cast<wostream*>(wcout);
|
||||
cout_ptr->flush();
|
||||
wcout_ptr->flush();
|
||||
#endif
|
||||
|
||||
ostream* clog_ptr = reinterpret_cast<ostream*>(clog);
|
||||
wostream* wclog_ptr = reinterpret_cast<wostream*>(wclog);
|
||||
clog_ptr->flush();
|
||||
wclog_ptr->flush();
|
||||
}
|
||||
|
||||
ios_base::Init::Init()
|
||||
{
|
||||
static DoIOSInit init_the_streams; // gets initialized once
|
||||
}
|
||||
|
||||
ios_base::Init::~Init()
|
||||
{
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
6154
lib/libcxx/src/locale.cpp
Normal file
6154
lib/libcxx/src/locale.cpp
Normal file
File diff suppressed because it is too large
Load Diff
237
lib/libcxx/src/memory.cpp
Normal file
237
lib/libcxx/src/memory.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
//===------------------------ memory.cpp ----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "memory"
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
#include "mutex"
|
||||
#include "thread"
|
||||
#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
|
||||
#pragma comment(lib, "pthread")
|
||||
#endif
|
||||
#endif
|
||||
#include "include/atomic_support.h"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
const allocator_arg_t allocator_arg = allocator_arg_t();
|
||||
|
||||
bad_weak_ptr::~bad_weak_ptr() _NOEXCEPT {}
|
||||
|
||||
const char*
|
||||
bad_weak_ptr::what() const _NOEXCEPT
|
||||
{
|
||||
return "bad_weak_ptr";
|
||||
}
|
||||
|
||||
__shared_count::~__shared_count()
|
||||
{
|
||||
}
|
||||
|
||||
__shared_weak_count::~__shared_weak_count()
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
|
||||
void
|
||||
__shared_count::__add_shared() _NOEXCEPT
|
||||
{
|
||||
__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_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
|
||||
|
||||
void
|
||||
__shared_weak_count::__release_weak() _NOEXCEPT
|
||||
{
|
||||
// NOTE: The acquire load here is an optimization of the very
|
||||
// common case where a shared pointer is being destructed while
|
||||
// having no other contended references.
|
||||
//
|
||||
// BENEFIT: We avoid expensive atomic stores like XADD and STREX
|
||||
// in a common case. Those instructions are slow and do nasty
|
||||
// things to caches.
|
||||
//
|
||||
// IS THIS SAFE? Yes. During weak destruction, if we see that we
|
||||
// are the last reference, we know that no-one else is accessing
|
||||
// us. If someone were accessing us, then they would be doing so
|
||||
// while the last shared / weak_ptr was being destructed, and
|
||||
// that's undefined anyway.
|
||||
//
|
||||
// If we see anything other than a 0, then we have possible
|
||||
// contention, and need to use an atomicrmw primitive.
|
||||
// The same arguments don't apply for increment, where it is legal
|
||||
// (though inadvisable) to share shared_ptr references between
|
||||
// threads, and have them all get copied at once. The argument
|
||||
// also doesn't apply for __release_shared, because an outstanding
|
||||
// weak_ptr::lock() could read / modify the shared count.
|
||||
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;
|
||||
}
|
||||
|
||||
#if !defined(_LIBCPP_NO_RTTI) || !defined(_LIBCPP_BUILD_STATIC)
|
||||
|
||||
const void*
|
||||
__shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_NO_RTTI
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
|
||||
|
||||
_LIBCPP_SAFE_STATIC static const std::size_t __sp_mut_count = 16;
|
||||
_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut_back[__sp_mut_count] =
|
||||
{
|
||||
_LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
|
||||
_LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
|
||||
_LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER,
|
||||
_LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER
|
||||
};
|
||||
|
||||
_LIBCPP_CONSTEXPR __sp_mut::__sp_mut(void* p) _NOEXCEPT
|
||||
: __lx(p)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
__sp_mut::lock() _NOEXCEPT
|
||||
{
|
||||
auto m = static_cast<__libcpp_mutex_t*>(__lx);
|
||||
unsigned count = 0;
|
||||
while (!__libcpp_mutex_trylock(m))
|
||||
{
|
||||
if (++count > 16)
|
||||
{
|
||||
__libcpp_mutex_lock(m);
|
||||
break;
|
||||
}
|
||||
this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__sp_mut::unlock() _NOEXCEPT
|
||||
{
|
||||
__libcpp_mutex_unlock(static_cast<__libcpp_mutex_t*>(__lx));
|
||||
}
|
||||
|
||||
__sp_mut&
|
||||
__get_sp_mut(const void* p)
|
||||
{
|
||||
static __sp_mut muts[__sp_mut_count]
|
||||
{
|
||||
&mut_back[ 0], &mut_back[ 1], &mut_back[ 2], &mut_back[ 3],
|
||||
&mut_back[ 4], &mut_back[ 5], &mut_back[ 6], &mut_back[ 7],
|
||||
&mut_back[ 8], &mut_back[ 9], &mut_back[10], &mut_back[11],
|
||||
&mut_back[12], &mut_back[13], &mut_back[14], &mut_back[15]
|
||||
};
|
||||
return muts[hash<const void*>()(p) & (__sp_mut_count-1)];
|
||||
}
|
||||
|
||||
#endif // !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
|
||||
|
||||
void
|
||||
declare_reachable(void*)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
declare_no_pointers(char*, size_t)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
undeclare_no_pointers(char*, size_t)
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE)
|
||||
pointer_safety get_pointer_safety() _NOEXCEPT
|
||||
{
|
||||
return pointer_safety::relaxed;
|
||||
}
|
||||
#endif
|
||||
|
||||
void*
|
||||
__undeclare_reachable(void* p)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
void*
|
||||
align(size_t alignment, size_t size, void*& ptr, size_t& space)
|
||||
{
|
||||
void* r = nullptr;
|
||||
if (size <= space)
|
||||
{
|
||||
char* p1 = static_cast<char*>(ptr);
|
||||
char* p2 = reinterpret_cast<char*>(reinterpret_cast<size_t>(p1 + (alignment - 1)) & -alignment);
|
||||
size_t d = static_cast<size_t>(p2 - p1);
|
||||
if (d <= space - size)
|
||||
{
|
||||
r = p2;
|
||||
ptr = r;
|
||||
space -= d;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
260
lib/libcxx/src/mutex.cpp
Normal file
260
lib/libcxx/src/mutex.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
//===------------------------- mutex.cpp ----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "mutex"
|
||||
#include "limits"
|
||||
#include "system_error"
|
||||
#include "include/atomic_support.h"
|
||||
#include "__undef_macros"
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
|
||||
#pragma comment(lib, "pthread")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
|
||||
const defer_lock_t defer_lock{};
|
||||
const try_to_lock_t try_to_lock{};
|
||||
const adopt_lock_t adopt_lock{};
|
||||
|
||||
// ~mutex is defined elsewhere
|
||||
|
||||
void
|
||||
mutex::lock()
|
||||
{
|
||||
int ec = __libcpp_mutex_lock(&__m_);
|
||||
if (ec)
|
||||
__throw_system_error(ec, "mutex lock failed");
|
||||
}
|
||||
|
||||
bool
|
||||
mutex::try_lock() _NOEXCEPT
|
||||
{
|
||||
return __libcpp_mutex_trylock(&__m_);
|
||||
}
|
||||
|
||||
void
|
||||
mutex::unlock() _NOEXCEPT
|
||||
{
|
||||
int ec = __libcpp_mutex_unlock(&__m_);
|
||||
(void)ec;
|
||||
_LIBCPP_ASSERT(ec == 0, "call to mutex::unlock failed");
|
||||
}
|
||||
|
||||
// recursive_mutex
|
||||
|
||||
recursive_mutex::recursive_mutex()
|
||||
{
|
||||
int ec = __libcpp_recursive_mutex_init(&__m_);
|
||||
if (ec)
|
||||
__throw_system_error(ec, "recursive_mutex constructor failed");
|
||||
}
|
||||
|
||||
recursive_mutex::~recursive_mutex()
|
||||
{
|
||||
int e = __libcpp_recursive_mutex_destroy(&__m_);
|
||||
(void)e;
|
||||
_LIBCPP_ASSERT(e == 0, "call to ~recursive_mutex() failed");
|
||||
}
|
||||
|
||||
void
|
||||
recursive_mutex::lock()
|
||||
{
|
||||
int ec = __libcpp_recursive_mutex_lock(&__m_);
|
||||
if (ec)
|
||||
__throw_system_error(ec, "recursive_mutex lock failed");
|
||||
}
|
||||
|
||||
void
|
||||
recursive_mutex::unlock() _NOEXCEPT
|
||||
{
|
||||
int e = __libcpp_recursive_mutex_unlock(&__m_);
|
||||
(void)e;
|
||||
_LIBCPP_ASSERT(e == 0, "call to recursive_mutex::unlock() failed");
|
||||
}
|
||||
|
||||
bool
|
||||
recursive_mutex::try_lock() _NOEXCEPT
|
||||
{
|
||||
return __libcpp_recursive_mutex_trylock(&__m_);
|
||||
}
|
||||
|
||||
// timed_mutex
|
||||
|
||||
timed_mutex::timed_mutex()
|
||||
: __locked_(false)
|
||||
{
|
||||
}
|
||||
|
||||
timed_mutex::~timed_mutex()
|
||||
{
|
||||
lock_guard<mutex> _(__m_);
|
||||
}
|
||||
|
||||
void
|
||||
timed_mutex::lock()
|
||||
{
|
||||
unique_lock<mutex> lk(__m_);
|
||||
while (__locked_)
|
||||
__cv_.wait(lk);
|
||||
__locked_ = true;
|
||||
}
|
||||
|
||||
bool
|
||||
timed_mutex::try_lock() _NOEXCEPT
|
||||
{
|
||||
unique_lock<mutex> lk(__m_, try_to_lock);
|
||||
if (lk.owns_lock() && !__locked_)
|
||||
{
|
||||
__locked_ = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
timed_mutex::unlock() _NOEXCEPT
|
||||
{
|
||||
lock_guard<mutex> _(__m_);
|
||||
__locked_ = false;
|
||||
__cv_.notify_one();
|
||||
}
|
||||
|
||||
// recursive_timed_mutex
|
||||
|
||||
recursive_timed_mutex::recursive_timed_mutex()
|
||||
: __count_(0),
|
||||
__id_{}
|
||||
{
|
||||
}
|
||||
|
||||
recursive_timed_mutex::~recursive_timed_mutex()
|
||||
{
|
||||
lock_guard<mutex> _(__m_);
|
||||
}
|
||||
|
||||
void
|
||||
recursive_timed_mutex::lock()
|
||||
{
|
||||
__thread_id id = this_thread::get_id();
|
||||
unique_lock<mutex> lk(__m_);
|
||||
if (id ==__id_)
|
||||
{
|
||||
if (__count_ == numeric_limits<size_t>::max())
|
||||
__throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached");
|
||||
++__count_;
|
||||
return;
|
||||
}
|
||||
while (__count_ != 0)
|
||||
__cv_.wait(lk);
|
||||
__count_ = 1;
|
||||
__id_ = id;
|
||||
}
|
||||
|
||||
bool
|
||||
recursive_timed_mutex::try_lock() _NOEXCEPT
|
||||
{
|
||||
__thread_id id = this_thread::get_id();
|
||||
unique_lock<mutex> lk(__m_, try_to_lock);
|
||||
if (lk.owns_lock() && (__count_ == 0 || id == __id_))
|
||||
{
|
||||
if (__count_ == numeric_limits<size_t>::max())
|
||||
return false;
|
||||
++__count_;
|
||||
__id_ = id;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
recursive_timed_mutex::unlock() _NOEXCEPT
|
||||
{
|
||||
unique_lock<mutex> lk(__m_);
|
||||
if (--__count_ == 0)
|
||||
{
|
||||
__id_.__reset();
|
||||
lk.unlock();
|
||||
__cv_.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
|
||||
// If dispatch_once_f ever handles C++ exceptions, and if one can get to it
|
||||
// without illegal macros (unexpected macros not beginning with _UpperCase or
|
||||
// __lowercase), and if it stops spinning waiting threads, then call_once should
|
||||
// call into dispatch_once_f instead of here. Relevant radar this code needs to
|
||||
// keep in sync with: 7741191.
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
_LIBCPP_SAFE_STATIC static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER;
|
||||
_LIBCPP_SAFE_STATIC static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER;
|
||||
#endif
|
||||
|
||||
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_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
flag = 1;
|
||||
func(arg);
|
||||
flag = ~once_flag::_State_type(0);
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
flag = 0;
|
||||
throw;
|
||||
}
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
#else // !_LIBCPP_HAS_NO_THREADS
|
||||
__libcpp_mutex_lock(&mut);
|
||||
while (flag == 1)
|
||||
__libcpp_condvar_wait(&cv, &mut);
|
||||
if (flag == 0)
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
__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_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_NO_EXCEPTIONS
|
||||
}
|
||||
else
|
||||
__libcpp_mutex_unlock(&mut);
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
50
lib/libcxx/src/mutex_destructor.cpp
Normal file
50
lib/libcxx/src/mutex_destructor.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//===--------------------- mutex_destructor.cpp ---------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Define ~mutex.
|
||||
//
|
||||
// On some platforms ~mutex has been made trivial and the definition is only
|
||||
// provided for ABI compatibility.
|
||||
//
|
||||
// In order to avoid ODR violations within libc++ itself, we need to ensure
|
||||
// that *nothing* sees the non-trivial mutex declaration. For this reason
|
||||
// we re-declare the entire class in this file instead of using
|
||||
// _LIBCPP_BUILDING_LIBRARY to change the definition in the headers.
|
||||
|
||||
#include "__config"
|
||||
#include "__threading_support"
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
#if _LIBCPP_ABI_VERSION == 1 || !defined(_LIBCPP_HAS_TRIVIAL_MUTEX_DESTRUCTION)
|
||||
#define NEEDS_MUTEX_DESTRUCTOR
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#ifdef NEEDS_MUTEX_DESTRUCTOR
|
||||
class _LIBCPP_TYPE_VIS mutex
|
||||
{
|
||||
__libcpp_mutex_t __m_ = _LIBCPP_MUTEX_INITIALIZER;
|
||||
|
||||
public:
|
||||
_LIBCPP_ALWAYS_INLINE _LIBCPP_INLINE_VISIBILITY
|
||||
constexpr mutex() = default;
|
||||
mutex(const mutex&) = delete;
|
||||
mutex& operator=(const mutex&) = delete;
|
||||
~mutex() noexcept;
|
||||
};
|
||||
|
||||
|
||||
mutex::~mutex() _NOEXCEPT
|
||||
{
|
||||
__libcpp_mutex_destroy(&__m_);
|
||||
}
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
297
lib/libcxx/src/new.cpp
Normal file
297
lib/libcxx/src/new.cpp
Normal file
@@ -0,0 +1,297 @@
|
||||
//===--------------------------- new.cpp ----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "new"
|
||||
#include "include/atomic_support.h"
|
||||
|
||||
#if defined(_LIBCPP_ABI_MICROSOFT)
|
||||
# if !defined(_LIBCPP_ABI_VCRUNTIME)
|
||||
# include "support/runtime/new_handler_fallback.ipp"
|
||||
# endif
|
||||
#elif defined(LIBCXX_BUILDING_LIBCXXABI)
|
||||
# include <cxxabi.h>
|
||||
#elif defined(LIBCXXRT)
|
||||
# include <cxxabi.h>
|
||||
# include "support/runtime/new_handler_fallback.ipp"
|
||||
#elif defined(__GLIBCXX__)
|
||||
// nothing to do
|
||||
#else
|
||||
# include "support/runtime/new_handler_fallback.ipp"
|
||||
#endif
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
#ifndef __GLIBCXX__
|
||||
const nothrow_t nothrow{};
|
||||
#endif
|
||||
|
||||
#ifndef LIBSTDCXX
|
||||
|
||||
void
|
||||
__throw_bad_alloc()
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
throw bad_alloc();
|
||||
#else
|
||||
_VSTD::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // !LIBSTDCXX
|
||||
|
||||
} // std
|
||||
|
||||
#if !defined(__GLIBCXX__) && \
|
||||
!defined(_LIBCPP_ABI_VCRUNTIME) && \
|
||||
!defined(_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS)
|
||||
|
||||
// Implement all new and delete operators as weak definitions
|
||||
// in this shared library, so that they can be overridden by programs
|
||||
// that define non-weak copies of the functions.
|
||||
|
||||
_LIBCPP_WEAK
|
||||
void *
|
||||
operator new(std::size_t size) _THROW_BAD_ALLOC
|
||||
{
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
void* p;
|
||||
while ((p = ::malloc(size)) == 0)
|
||||
{
|
||||
// If malloc fails and there is a new_handler,
|
||||
// call it to try free up memory.
|
||||
std::new_handler nh = std::get_new_handler();
|
||||
if (nh)
|
||||
nh();
|
||||
else
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
|
||||
{
|
||||
void* p = 0;
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
p = ::operator new(size);
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new[](size_t size) _THROW_BAD_ALLOC
|
||||
{
|
||||
return ::operator new(size);
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
|
||||
{
|
||||
void* p = 0;
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
p = ::operator new[](size);
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete(void* ptr) _NOEXCEPT
|
||||
{
|
||||
::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*));
|
||||
void* p;
|
||||
#if defined(_LIBCPP_MSVCRT_LIKE)
|
||||
while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr)
|
||||
#else
|
||||
while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
|
||||
#endif
|
||||
{
|
||||
// If posix_memalign fails and there is a new_handler,
|
||||
// call it to try free up memory.
|
||||
std::new_handler nh = std::get_new_handler();
|
||||
if (nh)
|
||||
nh();
|
||||
else {
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
p = nullptr; // posix_memalign doesn't initialize 'p' on failure
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
||||
{
|
||||
void* p = 0;
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
p = ::operator new(size, alignment);
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
|
||||
{
|
||||
return ::operator new(size, alignment);
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
void*
|
||||
operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
|
||||
{
|
||||
void* p = 0;
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
p = ::operator new[](size, alignment);
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
return p;
|
||||
}
|
||||
|
||||
_LIBCPP_WEAK
|
||||
void
|
||||
operator delete(void* ptr, std::align_val_t) _NOEXCEPT
|
||||
{
|
||||
#if defined(_LIBCPP_MSVCRT_LIKE)
|
||||
::_aligned_free(ptr);
|
||||
#else
|
||||
::free(ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
_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
|
||||
41
lib/libcxx/src/optional.cpp
Normal file
41
lib/libcxx/src/optional.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
//===------------------------ optional.cpp --------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "optional"
|
||||
|
||||
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
|
||||
178
lib/libcxx/src/random.cpp
Normal file
178
lib/libcxx/src/random.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
//===-------------------------- random.cpp --------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <__config>
|
||||
|
||||
#if defined(_LIBCPP_USING_WIN32_RANDOM)
|
||||
// Must be defined before including stdlib.h to enable rand_s().
|
||||
#define _CRT_RAND_S
|
||||
#endif // defined(_LIBCPP_USING_WIN32_RANDOM)
|
||||
|
||||
#include "random"
|
||||
#include "system_error"
|
||||
|
||||
#if defined(__sun__)
|
||||
#define rename solaris_headers_are_broken
|
||||
#endif // defined(__sun__)
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(_LIBCPP_USING_GETENTROPY)
|
||||
#include <sys/random.h>
|
||||
#elif defined(_LIBCPP_USING_DEV_RANDOM)
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#elif defined(_LIBCPP_USING_NACL_RANDOM)
|
||||
#include <nacl/nacl_random.h>
|
||||
#endif
|
||||
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if defined(_LIBCPP_USING_GETENTROPY)
|
||||
|
||||
random_device::random_device(const string& __token)
|
||||
{
|
||||
if (__token != "/dev/urandom")
|
||||
__throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
|
||||
}
|
||||
|
||||
random_device::~random_device()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned
|
||||
random_device::operator()()
|
||||
{
|
||||
unsigned r;
|
||||
size_t n = sizeof(r);
|
||||
int err = getentropy(&r, n);
|
||||
if (err)
|
||||
__throw_system_error(errno, "random_device getentropy failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
#elif defined(_LIBCPP_USING_ARC4_RANDOM)
|
||||
|
||||
random_device::random_device(const string& __token)
|
||||
{
|
||||
if (__token != "/dev/urandom")
|
||||
__throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
|
||||
}
|
||||
|
||||
random_device::~random_device()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned
|
||||
random_device::operator()()
|
||||
{
|
||||
return arc4random();
|
||||
}
|
||||
|
||||
#elif defined(_LIBCPP_USING_DEV_RANDOM)
|
||||
|
||||
random_device::random_device(const string& __token)
|
||||
: __f_(open(__token.c_str(), O_RDONLY))
|
||||
{
|
||||
if (__f_ < 0)
|
||||
__throw_system_error(errno, ("random_device failed to open " + __token).c_str());
|
||||
}
|
||||
|
||||
random_device::~random_device()
|
||||
{
|
||||
close(__f_);
|
||||
}
|
||||
|
||||
unsigned
|
||||
random_device::operator()()
|
||||
{
|
||||
unsigned r;
|
||||
size_t n = sizeof(r);
|
||||
char* p = reinterpret_cast<char*>(&r);
|
||||
while (n > 0)
|
||||
{
|
||||
ssize_t s = read(__f_, p, n);
|
||||
if (s == 0)
|
||||
__throw_system_error(ENODATA, "random_device got EOF");
|
||||
if (s == -1)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
__throw_system_error(errno, "random_device got an unexpected error");
|
||||
continue;
|
||||
}
|
||||
n -= static_cast<size_t>(s);
|
||||
p += static_cast<size_t>(s);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#elif defined(_LIBCPP_USING_NACL_RANDOM)
|
||||
|
||||
random_device::random_device(const string& __token)
|
||||
{
|
||||
if (__token != "/dev/urandom")
|
||||
__throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
|
||||
int error = nacl_secure_random_init();
|
||||
if (error)
|
||||
__throw_system_error(error, ("random device failed to open " + __token).c_str());
|
||||
}
|
||||
|
||||
random_device::~random_device()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned
|
||||
random_device::operator()()
|
||||
{
|
||||
unsigned r;
|
||||
size_t n = sizeof(r);
|
||||
size_t bytes_written;
|
||||
int error = nacl_secure_random(&r, n, &bytes_written);
|
||||
if (error != 0)
|
||||
__throw_system_error(error, "random_device failed getting bytes");
|
||||
else if (bytes_written != n)
|
||||
__throw_runtime_error("random_device failed to obtain enough bytes");
|
||||
return r;
|
||||
}
|
||||
|
||||
#elif defined(_LIBCPP_USING_WIN32_RANDOM)
|
||||
|
||||
random_device::random_device(const string& __token)
|
||||
{
|
||||
if (__token != "/dev/urandom")
|
||||
__throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
|
||||
}
|
||||
|
||||
random_device::~random_device()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned
|
||||
random_device::operator()()
|
||||
{
|
||||
unsigned r;
|
||||
errno_t err = rand_s(&r);
|
||||
if (err)
|
||||
__throw_system_error(err, "random_device rand_s failed.");
|
||||
return r;
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Random device not implemented for this architecture"
|
||||
#endif
|
||||
|
||||
double
|
||||
random_device::entropy() const _NOEXCEPT
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
316
lib/libcxx/src/regex.cpp
Normal file
316
lib/libcxx/src/regex.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
//===-------------------------- regex.cpp ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "regex"
|
||||
#include "algorithm"
|
||||
#include "iterator"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
static
|
||||
const char*
|
||||
make_error_type_string(regex_constants::error_type ecode)
|
||||
{
|
||||
switch (ecode)
|
||||
{
|
||||
case regex_constants::error_collate:
|
||||
return "The expression contained an invalid collating element name.";
|
||||
case regex_constants::error_ctype:
|
||||
return "The expression contained an invalid character class name.";
|
||||
case regex_constants::error_escape:
|
||||
return "The expression contained an invalid escaped character, or a "
|
||||
"trailing escape.";
|
||||
case regex_constants::error_backref:
|
||||
return "The expression contained an invalid back reference.";
|
||||
case regex_constants::error_brack:
|
||||
return "The expression contained mismatched [ and ].";
|
||||
case regex_constants::error_paren:
|
||||
return "The expression contained mismatched ( and ).";
|
||||
case regex_constants::error_brace:
|
||||
return "The expression contained mismatched { and }.";
|
||||
case regex_constants::error_badbrace:
|
||||
return "The expression contained an invalid range in a {} expression.";
|
||||
case regex_constants::error_range:
|
||||
return "The expression contained an invalid character range, "
|
||||
"such as [b-a] in most encodings.";
|
||||
case regex_constants::error_space:
|
||||
return "There was insufficient memory to convert the expression into "
|
||||
"a finite state machine.";
|
||||
case regex_constants::error_badrepeat:
|
||||
return "One of *?+{ was not preceded by a valid regular expression.";
|
||||
case regex_constants::error_complexity:
|
||||
return "The complexity of an attempted match against a regular "
|
||||
"expression exceeded a pre-set level.";
|
||||
case regex_constants::error_stack:
|
||||
return "There was insufficient memory to determine whether the regular "
|
||||
"expression could match the specified character sequence.";
|
||||
case regex_constants::__re_err_grammar:
|
||||
return "An invalid regex grammar has been requested.";
|
||||
case regex_constants::__re_err_empty:
|
||||
return "An empty regex is not allowed in the POSIX grammar.";
|
||||
case regex_constants::__re_err_parse:
|
||||
return "The parser did not consume the entire regular expression.";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return "Unknown error type";
|
||||
}
|
||||
|
||||
regex_error::regex_error(regex_constants::error_type ecode)
|
||||
: runtime_error(make_error_type_string(ecode)),
|
||||
__code_(ecode)
|
||||
{}
|
||||
|
||||
regex_error::~regex_error() throw() {}
|
||||
|
||||
namespace {
|
||||
|
||||
struct collationnames
|
||||
{
|
||||
const char* elem_;
|
||||
char char_;
|
||||
};
|
||||
|
||||
const collationnames collatenames[] =
|
||||
{
|
||||
{"A", 0x41},
|
||||
{"B", 0x42},
|
||||
{"C", 0x43},
|
||||
{"D", 0x44},
|
||||
{"E", 0x45},
|
||||
{"F", 0x46},
|
||||
{"G", 0x47},
|
||||
{"H", 0x48},
|
||||
{"I", 0x49},
|
||||
{"J", 0x4a},
|
||||
{"K", 0x4b},
|
||||
{"L", 0x4c},
|
||||
{"M", 0x4d},
|
||||
{"N", 0x4e},
|
||||
{"NUL", 0x00},
|
||||
{"O", 0x4f},
|
||||
{"P", 0x50},
|
||||
{"Q", 0x51},
|
||||
{"R", 0x52},
|
||||
{"S", 0x53},
|
||||
{"T", 0x54},
|
||||
{"U", 0x55},
|
||||
{"V", 0x56},
|
||||
{"W", 0x57},
|
||||
{"X", 0x58},
|
||||
{"Y", 0x59},
|
||||
{"Z", 0x5a},
|
||||
{"a", 0x61},
|
||||
{"alert", 0x07},
|
||||
{"ampersand", 0x26},
|
||||
{"apostrophe", 0x27},
|
||||
{"asterisk", 0x2a},
|
||||
{"b", 0x62},
|
||||
{"backslash", 0x5c},
|
||||
{"backspace", 0x08},
|
||||
{"c", 0x63},
|
||||
{"carriage-return", 0x0d},
|
||||
{"circumflex", 0x5e},
|
||||
{"circumflex-accent", 0x5e},
|
||||
{"colon", 0x3a},
|
||||
{"comma", 0x2c},
|
||||
{"commercial-at", 0x40},
|
||||
{"d", 0x64},
|
||||
{"dollar-sign", 0x24},
|
||||
{"e", 0x65},
|
||||
{"eight", 0x38},
|
||||
{"equals-sign", 0x3d},
|
||||
{"exclamation-mark", 0x21},
|
||||
{"f", 0x66},
|
||||
{"five", 0x35},
|
||||
{"form-feed", 0x0c},
|
||||
{"four", 0x34},
|
||||
{"full-stop", 0x2e},
|
||||
{"g", 0x67},
|
||||
{"grave-accent", 0x60},
|
||||
{"greater-than-sign", 0x3e},
|
||||
{"h", 0x68},
|
||||
{"hyphen", 0x2d},
|
||||
{"hyphen-minus", 0x2d},
|
||||
{"i", 0x69},
|
||||
{"j", 0x6a},
|
||||
{"k", 0x6b},
|
||||
{"l", 0x6c},
|
||||
{"left-brace", 0x7b},
|
||||
{"left-curly-bracket", 0x7b},
|
||||
{"left-parenthesis", 0x28},
|
||||
{"left-square-bracket", 0x5b},
|
||||
{"less-than-sign", 0x3c},
|
||||
{"low-line", 0x5f},
|
||||
{"m", 0x6d},
|
||||
{"n", 0x6e},
|
||||
{"newline", 0x0a},
|
||||
{"nine", 0x39},
|
||||
{"number-sign", 0x23},
|
||||
{"o", 0x6f},
|
||||
{"one", 0x31},
|
||||
{"p", 0x70},
|
||||
{"percent-sign", 0x25},
|
||||
{"period", 0x2e},
|
||||
{"plus-sign", 0x2b},
|
||||
{"q", 0x71},
|
||||
{"question-mark", 0x3f},
|
||||
{"quotation-mark", 0x22},
|
||||
{"r", 0x72},
|
||||
{"reverse-solidus", 0x5c},
|
||||
{"right-brace", 0x7d},
|
||||
{"right-curly-bracket", 0x7d},
|
||||
{"right-parenthesis", 0x29},
|
||||
{"right-square-bracket", 0x5d},
|
||||
{"s", 0x73},
|
||||
{"semicolon", 0x3b},
|
||||
{"seven", 0x37},
|
||||
{"six", 0x36},
|
||||
{"slash", 0x2f},
|
||||
{"solidus", 0x2f},
|
||||
{"space", 0x20},
|
||||
{"t", 0x74},
|
||||
{"tab", 0x09},
|
||||
{"three", 0x33},
|
||||
{"tilde", 0x7e},
|
||||
{"two", 0x32},
|
||||
{"u", 0x75},
|
||||
{"underscore", 0x5f},
|
||||
{"v", 0x76},
|
||||
{"vertical-line", 0x7c},
|
||||
{"vertical-tab", 0x0b},
|
||||
{"w", 0x77},
|
||||
{"x", 0x78},
|
||||
{"y", 0x79},
|
||||
{"z", 0x7a},
|
||||
{"zero", 0x30}
|
||||
};
|
||||
|
||||
struct classnames
|
||||
{
|
||||
const char* elem_;
|
||||
regex_traits<char>::char_class_type mask_;
|
||||
};
|
||||
|
||||
const classnames ClassNames[] =
|
||||
{
|
||||
{"alnum", ctype_base::alnum},
|
||||
{"alpha", ctype_base::alpha},
|
||||
{"blank", ctype_base::blank},
|
||||
{"cntrl", ctype_base::cntrl},
|
||||
{"d", ctype_base::digit},
|
||||
{"digit", ctype_base::digit},
|
||||
{"graph", ctype_base::graph},
|
||||
{"lower", ctype_base::lower},
|
||||
{"print", ctype_base::print},
|
||||
{"punct", ctype_base::punct},
|
||||
{"s", ctype_base::space},
|
||||
{"space", ctype_base::space},
|
||||
{"upper", ctype_base::upper},
|
||||
{"w", regex_traits<char>::__regex_word},
|
||||
{"xdigit", ctype_base::xdigit}
|
||||
};
|
||||
|
||||
struct use_strcmp
|
||||
{
|
||||
bool operator()(const collationnames& x, const char* y)
|
||||
{return strcmp(x.elem_, y) < 0;}
|
||||
bool operator()(const classnames& x, const char* y)
|
||||
{return strcmp(x.elem_, y) < 0;}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
string
|
||||
__get_collation_name(const char* s)
|
||||
{
|
||||
const collationnames* i =
|
||||
_VSTD::lower_bound(begin(collatenames), end(collatenames), s, use_strcmp());
|
||||
string r;
|
||||
if (i != end(collatenames) && strcmp(s, i->elem_) == 0)
|
||||
r = char(i->char_);
|
||||
return r;
|
||||
}
|
||||
|
||||
regex_traits<char>::char_class_type
|
||||
__get_classname(const char* s, bool __icase)
|
||||
{
|
||||
const classnames* i =
|
||||
_VSTD::lower_bound(begin(ClassNames), end(ClassNames), s, use_strcmp());
|
||||
regex_traits<char>::char_class_type r = 0;
|
||||
if (i != end(ClassNames) && strcmp(s, i->elem_) == 0)
|
||||
{
|
||||
r = i->mask_;
|
||||
if (r == regex_traits<char>::__regex_word)
|
||||
r |= ctype_base::alnum | ctype_base::upper | ctype_base::lower;
|
||||
else if (__icase)
|
||||
{
|
||||
if (r & (ctype_base::lower | ctype_base::upper))
|
||||
r |= ctype_base::alpha;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
__match_any_but_newline<char>::__exec(__state& __s) const
|
||||
{
|
||||
if (__s.__current_ != __s.__last_)
|
||||
{
|
||||
switch (*__s.__current_)
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
__s.__do_ = __state::__reject;
|
||||
__s.__node_ = nullptr;
|
||||
break;
|
||||
default:
|
||||
__s.__do_ = __state::__accept_and_consume;
|
||||
++__s.__current_;
|
||||
__s.__node_ = this->first();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__s.__do_ = __state::__reject;
|
||||
__s.__node_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
__match_any_but_newline<wchar_t>::__exec(__state& __s) const
|
||||
{
|
||||
if (__s.__current_ != __s.__last_)
|
||||
{
|
||||
switch (*__s.__current_)
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
case 0x2028:
|
||||
case 0x2029:
|
||||
__s.__do_ = __state::__reject;
|
||||
__s.__node_ = nullptr;
|
||||
break;
|
||||
default:
|
||||
__s.__do_ = __state::__accept_and_consume;
|
||||
++__s.__current_;
|
||||
__s.__node_ = this->first();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__s.__do_ = __state::__reject;
|
||||
__s.__node_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
118
lib/libcxx/src/shared_mutex.cpp
Normal file
118
lib/libcxx/src/shared_mutex.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
//===---------------------- shared_mutex.cpp ------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "__config"
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
|
||||
#include "shared_mutex"
|
||||
#if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
|
||||
#pragma comment(lib, "pthread")
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// Shared Mutex Base
|
||||
__shared_mutex_base::__shared_mutex_base()
|
||||
: __state_(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Exclusive ownership
|
||||
|
||||
void
|
||||
__shared_mutex_base::lock()
|
||||
{
|
||||
unique_lock<mutex> lk(__mut_);
|
||||
while (__state_ & __write_entered_)
|
||||
__gate1_.wait(lk);
|
||||
__state_ |= __write_entered_;
|
||||
while (__state_ & __n_readers_)
|
||||
__gate2_.wait(lk);
|
||||
}
|
||||
|
||||
bool
|
||||
__shared_mutex_base::try_lock()
|
||||
{
|
||||
unique_lock<mutex> lk(__mut_);
|
||||
if (__state_ == 0)
|
||||
{
|
||||
__state_ = __write_entered_;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
__shared_mutex_base::unlock()
|
||||
{
|
||||
lock_guard<mutex> _(__mut_);
|
||||
__state_ = 0;
|
||||
__gate1_.notify_all();
|
||||
}
|
||||
|
||||
// Shared ownership
|
||||
|
||||
void
|
||||
__shared_mutex_base::lock_shared()
|
||||
{
|
||||
unique_lock<mutex> lk(__mut_);
|
||||
while ((__state_ & __write_entered_) || (__state_ & __n_readers_) == __n_readers_)
|
||||
__gate1_.wait(lk);
|
||||
unsigned num_readers = (__state_ & __n_readers_) + 1;
|
||||
__state_ &= ~__n_readers_;
|
||||
__state_ |= num_readers;
|
||||
}
|
||||
|
||||
bool
|
||||
__shared_mutex_base::try_lock_shared()
|
||||
{
|
||||
unique_lock<mutex> lk(__mut_);
|
||||
unsigned num_readers = __state_ & __n_readers_;
|
||||
if (!(__state_ & __write_entered_) && num_readers != __n_readers_)
|
||||
{
|
||||
++num_readers;
|
||||
__state_ &= ~__n_readers_;
|
||||
__state_ |= num_readers;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
__shared_mutex_base::unlock_shared()
|
||||
{
|
||||
lock_guard<mutex> _(__mut_);
|
||||
unsigned num_readers = (__state_ & __n_readers_) - 1;
|
||||
__state_ &= ~__n_readers_;
|
||||
__state_ |= num_readers;
|
||||
if (__state_ & __write_entered_)
|
||||
{
|
||||
if (num_readers == 0)
|
||||
__gate2_.notify_one();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num_readers == __n_readers_ - 1)
|
||||
__gate1_.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Shared Timed Mutex
|
||||
// These routines are here for ABI stability
|
||||
shared_timed_mutex::shared_timed_mutex() : __base() {}
|
||||
void shared_timed_mutex::lock() { return __base.lock(); }
|
||||
bool shared_timed_mutex::try_lock() { return __base.try_lock(); }
|
||||
void shared_timed_mutex::unlock() { return __base.unlock(); }
|
||||
void shared_timed_mutex::lock_shared() { return __base.lock_shared(); }
|
||||
bool shared_timed_mutex::try_lock_shared() { return __base.try_lock_shared(); }
|
||||
void shared_timed_mutex::unlock_shared() { return __base.unlock_shared(); }
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
19
lib/libcxx/src/stdexcept.cpp
Normal file
19
lib/libcxx/src/stdexcept.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
//===------------------------ stdexcept.cpp -------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "stdexcept"
|
||||
#include "new"
|
||||
#include "string"
|
||||
#include "system_error"
|
||||
|
||||
|
||||
#ifdef _LIBCPP_ABI_VCRUNTIME
|
||||
#include "support/runtime/stdexcept_vcruntime.ipp"
|
||||
#else
|
||||
#include "support/runtime/stdexcept_default.ipp"
|
||||
#endif
|
||||
458
lib/libcxx/src/string.cpp
Normal file
458
lib/libcxx/src/string.cpp
Normal file
@@ -0,0 +1,458 @@
|
||||
//===------------------------- string.cpp ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "string"
|
||||
#include "charconv"
|
||||
#include "cstdlib"
|
||||
#include "cwchar"
|
||||
#include "cerrno"
|
||||
#include "limits"
|
||||
#include "stdexcept"
|
||||
#include <stdio.h>
|
||||
#include "__debug"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>;
|
||||
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>;
|
||||
|
||||
template
|
||||
string
|
||||
operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
inline
|
||||
void throw_helper( const string& msg )
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
throw T( msg );
|
||||
#else
|
||||
fprintf(stderr, "%s\n", msg.c_str());
|
||||
_VSTD::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
void throw_from_string_out_of_range( const string& func )
|
||||
{
|
||||
throw_helper<out_of_range>(func + ": out of range");
|
||||
}
|
||||
|
||||
inline
|
||||
void throw_from_string_invalid_arg( const string& func )
|
||||
{
|
||||
throw_helper<invalid_argument>(func + ": no conversion");
|
||||
}
|
||||
|
||||
// as_integer
|
||||
|
||||
template<typename V, typename S, typename F>
|
||||
inline
|
||||
V
|
||||
as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f)
|
||||
{
|
||||
typename S::value_type* ptr = nullptr;
|
||||
const typename S::value_type* const p = str.c_str();
|
||||
typename remove_reference<decltype(errno)>::type errno_save = errno;
|
||||
errno = 0;
|
||||
V r = f(p, &ptr, base);
|
||||
swap(errno, errno_save);
|
||||
if (errno_save == ERANGE)
|
||||
throw_from_string_out_of_range(func);
|
||||
if (ptr == p)
|
||||
throw_from_string_invalid_arg(func);
|
||||
if (idx)
|
||||
*idx = static_cast<size_t>(ptr - p);
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename V, typename S>
|
||||
inline
|
||||
V
|
||||
as_integer(const string& func, const S& s, size_t* idx, int base);
|
||||
|
||||
// string
|
||||
template<>
|
||||
inline
|
||||
int
|
||||
as_integer(const string& func, const string& s, size_t* idx, int base )
|
||||
{
|
||||
// Use long as no Standard string to integer exists.
|
||||
long r = as_integer_helper<long>( func, s, idx, base, strtol );
|
||||
if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
|
||||
throw_from_string_out_of_range(func);
|
||||
return static_cast<int>(r);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
long
|
||||
as_integer(const string& func, const string& s, size_t* idx, int base )
|
||||
{
|
||||
return as_integer_helper<long>( func, s, idx, base, strtol );
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
unsigned long
|
||||
as_integer( const string& func, const string& s, size_t* idx, int base )
|
||||
{
|
||||
return as_integer_helper<unsigned long>( func, s, idx, base, strtoul );
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
long long
|
||||
as_integer( const string& func, const string& s, size_t* idx, int base )
|
||||
{
|
||||
return as_integer_helper<long long>( func, s, idx, base, strtoll );
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
unsigned long long
|
||||
as_integer( const string& func, const string& s, size_t* idx, int base )
|
||||
{
|
||||
return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
|
||||
}
|
||||
|
||||
// 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 );
|
||||
}
|
||||
|
||||
// as_float
|
||||
|
||||
template<typename V, typename S, typename F>
|
||||
inline
|
||||
V
|
||||
as_float_helper(const string& func, const S& str, size_t* idx, F f )
|
||||
{
|
||||
typename S::value_type* ptr = nullptr;
|
||||
const typename S::value_type* const p = str.c_str();
|
||||
typename remove_reference<decltype(errno)>::type errno_save = errno;
|
||||
errno = 0;
|
||||
V r = f(p, &ptr);
|
||||
swap(errno, errno_save);
|
||||
if (errno_save == ERANGE)
|
||||
throw_from_string_out_of_range(func);
|
||||
if (ptr == p)
|
||||
throw_from_string_invalid_arg(func);
|
||||
if (idx)
|
||||
*idx = static_cast<size_t>(ptr - p);
|
||||
return r;
|
||||
}
|
||||
|
||||
template<typename V, typename S>
|
||||
inline
|
||||
V as_float( const string& func, const S& s, size_t* idx = nullptr );
|
||||
|
||||
template<>
|
||||
inline
|
||||
float
|
||||
as_float( const string& func, const string& s, size_t* idx )
|
||||
{
|
||||
return as_float_helper<float>( func, s, idx, strtof );
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
double
|
||||
as_float(const string& func, const string& s, size_t* idx )
|
||||
{
|
||||
return as_float_helper<double>( func, s, idx, strtod );
|
||||
}
|
||||
|
||||
template<>
|
||||
inline
|
||||
long double
|
||||
as_float( const string& func, const string& s, size_t* idx )
|
||||
{
|
||||
return as_float_helper<long double>( func, s, idx, strtold );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
int
|
||||
stoi(const string& str, size_t* idx, int base)
|
||||
{
|
||||
return as_integer<int>( "stoi", str, idx, base );
|
||||
}
|
||||
|
||||
int
|
||||
stoi(const wstring& 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 );
|
||||
}
|
||||
|
||||
long
|
||||
stol(const wstring& 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 );
|
||||
}
|
||||
|
||||
unsigned long
|
||||
stoul(const wstring& 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 );
|
||||
}
|
||||
|
||||
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 string& str, size_t* idx, int base)
|
||||
{
|
||||
return as_integer<unsigned long long>( "stoull", 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 string& str, size_t* idx)
|
||||
{
|
||||
return as_float<float>( "stof", str, idx );
|
||||
}
|
||||
|
||||
float
|
||||
stof(const wstring& 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 );
|
||||
}
|
||||
|
||||
double
|
||||
stod(const wstring& 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 );
|
||||
}
|
||||
|
||||
long double
|
||||
stold(const wstring& str, size_t* idx)
|
||||
{
|
||||
return as_float<long double>( "stold", str, idx );
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
template <typename S, typename V>
|
||||
S i_to_string(const 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); }
|
||||
|
||||
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); }
|
||||
|
||||
|
||||
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); }
|
||||
|
||||
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); }
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
335
lib/libcxx/src/strstream.cpp
Normal file
335
lib/libcxx/src/strstream.cpp
Normal file
@@ -0,0 +1,335 @@
|
||||
//===------------------------ strstream.cpp -------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "strstream"
|
||||
#include "algorithm"
|
||||
#include "climits"
|
||||
#include "cstring"
|
||||
#include "cstdlib"
|
||||
#include "__debug"
|
||||
#include "__undef_macros"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
strstreambuf::strstreambuf(streamsize __alsize)
|
||||
: __strmode_(__dynamic),
|
||||
__alsize_(__alsize),
|
||||
__palloc_(nullptr),
|
||||
__pfree_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
|
||||
: __strmode_(__dynamic),
|
||||
__alsize_(__default_alsize),
|
||||
__palloc_(__palloc),
|
||||
__pfree_(__pfree)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg)
|
||||
{
|
||||
if (__n == 0)
|
||||
__n = static_cast<streamsize>(strlen(__gnext));
|
||||
else if (__n < 0)
|
||||
__n = INT_MAX;
|
||||
if (__pbeg == nullptr)
|
||||
setg(__gnext, __gnext, __gnext + __n);
|
||||
else
|
||||
{
|
||||
setg(__gnext, __gnext, __pbeg);
|
||||
setp(__pbeg, __pbeg + __n);
|
||||
}
|
||||
}
|
||||
|
||||
strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
|
||||
: __strmode_(),
|
||||
__alsize_(__default_alsize),
|
||||
__palloc_(nullptr),
|
||||
__pfree_(nullptr)
|
||||
{
|
||||
__init(__gnext, __n, __pbeg);
|
||||
}
|
||||
|
||||
strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
|
||||
: __strmode_(__constant),
|
||||
__alsize_(__default_alsize),
|
||||
__palloc_(nullptr),
|
||||
__pfree_(nullptr)
|
||||
{
|
||||
__init(const_cast<char *>(__gnext), __n, nullptr);
|
||||
}
|
||||
|
||||
strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
|
||||
: __strmode_(),
|
||||
__alsize_(__default_alsize),
|
||||
__palloc_(nullptr),
|
||||
__pfree_(nullptr)
|
||||
{
|
||||
__init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
|
||||
}
|
||||
|
||||
strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
|
||||
: __strmode_(__constant),
|
||||
__alsize_(__default_alsize),
|
||||
__palloc_(nullptr),
|
||||
__pfree_(nullptr)
|
||||
{
|
||||
__init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
|
||||
}
|
||||
|
||||
strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
|
||||
: __strmode_(),
|
||||
__alsize_(__default_alsize),
|
||||
__palloc_(nullptr),
|
||||
__pfree_(nullptr)
|
||||
{
|
||||
__init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, reinterpret_cast<char*>(__pbeg));
|
||||
}
|
||||
|
||||
strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
|
||||
: __strmode_(__constant),
|
||||
__alsize_(__default_alsize),
|
||||
__palloc_(nullptr),
|
||||
__pfree_(nullptr)
|
||||
{
|
||||
__init(const_cast<char *>(reinterpret_cast<const char*>(__gnext)), __n, nullptr);
|
||||
}
|
||||
|
||||
strstreambuf::~strstreambuf()
|
||||
{
|
||||
if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0)
|
||||
{
|
||||
if (__pfree_)
|
||||
__pfree_(eback());
|
||||
else
|
||||
delete [] eback();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
strstreambuf::swap(strstreambuf& __rhs)
|
||||
{
|
||||
streambuf::swap(__rhs);
|
||||
_VSTD::swap(__strmode_, __rhs.__strmode_);
|
||||
_VSTD::swap(__alsize_, __rhs.__alsize_);
|
||||
_VSTD::swap(__palloc_, __rhs.__palloc_);
|
||||
_VSTD::swap(__pfree_, __rhs.__pfree_);
|
||||
}
|
||||
|
||||
void
|
||||
strstreambuf::freeze(bool __freezefl)
|
||||
{
|
||||
if (__strmode_ & __dynamic)
|
||||
{
|
||||
if (__freezefl)
|
||||
__strmode_ |= __frozen;
|
||||
else
|
||||
__strmode_ &= ~__frozen;
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
strstreambuf::str()
|
||||
{
|
||||
if (__strmode_ & __dynamic)
|
||||
__strmode_ |= __frozen;
|
||||
return eback();
|
||||
}
|
||||
|
||||
int
|
||||
strstreambuf::pcount() const
|
||||
{
|
||||
return static_cast<int>(pptr() - pbase());
|
||||
}
|
||||
|
||||
strstreambuf::int_type
|
||||
strstreambuf::overflow(int_type __c)
|
||||
{
|
||||
if (__c == EOF)
|
||||
return int_type(0);
|
||||
if (pptr() == epptr())
|
||||
{
|
||||
if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
|
||||
return int_type(EOF);
|
||||
size_t old_size = static_cast<size_t> ((epptr() ? epptr() : egptr()) - eback());
|
||||
size_t new_size = max<size_t>(static_cast<size_t>(__alsize_), 2*old_size);
|
||||
if (new_size == 0)
|
||||
new_size = __default_alsize;
|
||||
char* buf = nullptr;
|
||||
if (__palloc_)
|
||||
buf = static_cast<char*>(__palloc_(new_size));
|
||||
else
|
||||
buf = new char[new_size];
|
||||
if (buf == nullptr)
|
||||
return int_type(EOF);
|
||||
if (old_size != 0) {
|
||||
_LIBCPP_ASSERT(eback(), "overflow copying from NULL");
|
||||
memcpy(buf, eback(), static_cast<size_t>(old_size));
|
||||
}
|
||||
ptrdiff_t ninp = gptr() - eback();
|
||||
ptrdiff_t einp = egptr() - eback();
|
||||
ptrdiff_t nout = pptr() - pbase();
|
||||
if (__strmode_ & __allocated)
|
||||
{
|
||||
if (__pfree_)
|
||||
__pfree_(eback());
|
||||
else
|
||||
delete [] eback();
|
||||
}
|
||||
setg(buf, buf + ninp, buf + einp);
|
||||
setp(buf + einp, buf + new_size);
|
||||
__pbump(nout);
|
||||
__strmode_ |= __allocated;
|
||||
}
|
||||
*pptr() = static_cast<char>(__c);
|
||||
pbump(1);
|
||||
return int_type(static_cast<unsigned char>(__c));
|
||||
}
|
||||
|
||||
strstreambuf::int_type
|
||||
strstreambuf::pbackfail(int_type __c)
|
||||
{
|
||||
if (eback() == gptr())
|
||||
return EOF;
|
||||
if (__c == EOF)
|
||||
{
|
||||
gbump(-1);
|
||||
return int_type(0);
|
||||
}
|
||||
if (__strmode_ & __constant)
|
||||
{
|
||||
if (gptr()[-1] == static_cast<char>(__c))
|
||||
{
|
||||
gbump(-1);
|
||||
return __c;
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
gbump(-1);
|
||||
*gptr() = static_cast<char>(__c);
|
||||
return __c;
|
||||
}
|
||||
|
||||
strstreambuf::int_type
|
||||
strstreambuf::underflow()
|
||||
{
|
||||
if (gptr() == egptr())
|
||||
{
|
||||
if (egptr() >= pptr())
|
||||
return EOF;
|
||||
setg(eback(), gptr(), pptr());
|
||||
}
|
||||
return int_type(static_cast<unsigned char>(*gptr()));
|
||||
}
|
||||
|
||||
strstreambuf::pos_type
|
||||
strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which)
|
||||
{
|
||||
off_type __p(-1);
|
||||
bool pos_in = (__which & ios::in) != 0;
|
||||
bool pos_out = (__which & ios::out) != 0;
|
||||
bool legal = false;
|
||||
switch (__way)
|
||||
{
|
||||
case ios::beg:
|
||||
case ios::end:
|
||||
if (pos_in || pos_out)
|
||||
legal = true;
|
||||
break;
|
||||
case ios::cur:
|
||||
if (pos_in != pos_out)
|
||||
legal = true;
|
||||
break;
|
||||
}
|
||||
if (pos_in && gptr() == nullptr)
|
||||
legal = false;
|
||||
if (pos_out && pptr() == nullptr)
|
||||
legal = false;
|
||||
if (legal)
|
||||
{
|
||||
off_type newoff;
|
||||
char* seekhigh = epptr() ? epptr() : egptr();
|
||||
switch (__way)
|
||||
{
|
||||
case ios::beg:
|
||||
newoff = 0;
|
||||
break;
|
||||
case ios::cur:
|
||||
newoff = (pos_in ? gptr() : pptr()) - eback();
|
||||
break;
|
||||
case ios::end:
|
||||
newoff = seekhigh - eback();
|
||||
break;
|
||||
default:
|
||||
_LIBCPP_UNREACHABLE();
|
||||
}
|
||||
newoff += __off;
|
||||
if (0 <= newoff && newoff <= seekhigh - eback())
|
||||
{
|
||||
char* newpos = eback() + newoff;
|
||||
if (pos_in)
|
||||
setg(eback(), newpos, _VSTD::max(newpos, egptr()));
|
||||
if (pos_out)
|
||||
{
|
||||
// min(pbase, newpos), newpos, epptr()
|
||||
__off = epptr() - newpos;
|
||||
setp(min(pbase(), newpos), epptr());
|
||||
__pbump((epptr() - pbase()) - __off);
|
||||
}
|
||||
__p = newoff;
|
||||
}
|
||||
}
|
||||
return pos_type(__p);
|
||||
}
|
||||
|
||||
strstreambuf::pos_type
|
||||
strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which)
|
||||
{
|
||||
off_type __p(-1);
|
||||
bool pos_in = (__which & ios::in) != 0;
|
||||
bool pos_out = (__which & ios::out) != 0;
|
||||
if (pos_in || pos_out)
|
||||
{
|
||||
if (!((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr)))
|
||||
{
|
||||
off_type newoff = __sp;
|
||||
char* seekhigh = epptr() ? epptr() : egptr();
|
||||
if (0 <= newoff && newoff <= seekhigh - eback())
|
||||
{
|
||||
char* newpos = eback() + newoff;
|
||||
if (pos_in)
|
||||
setg(eback(), newpos, _VSTD::max(newpos, egptr()));
|
||||
if (pos_out)
|
||||
{
|
||||
// min(pbase, newpos), newpos, epptr()
|
||||
off_type temp = epptr() - newpos;
|
||||
setp(min(pbase(), newpos), epptr());
|
||||
__pbump((epptr() - pbase()) - temp);
|
||||
}
|
||||
__p = newoff;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pos_type(__p);
|
||||
}
|
||||
|
||||
istrstream::~istrstream()
|
||||
{
|
||||
}
|
||||
|
||||
ostrstream::~ostrstream()
|
||||
{
|
||||
}
|
||||
|
||||
strstream::~strstream()
|
||||
{
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
164
lib/libcxx/src/support/runtime/exception_fallback.ipp
Normal file
164
lib/libcxx/src/support/runtime/exception_fallback.ipp
Normal file
@@ -0,0 +1,164 @@
|
||||
// -*- 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 {
|
||||
|
||||
_LIBCPP_SAFE_STATIC static std::terminate_handler __terminate_handler;
|
||||
_LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler;
|
||||
|
||||
|
||||
// libcxxrt provides implementations of these functions itself.
|
||||
unexpected_handler
|
||||
set_unexpected(unexpected_handler func) _NOEXCEPT
|
||||
{
|
||||
return __libcpp_atomic_exchange(&__unexpected_handler, func);
|
||||
}
|
||||
|
||||
unexpected_handler
|
||||
get_unexpected() _NOEXCEPT
|
||||
{
|
||||
return __libcpp_atomic_load(&__unexpected_handler);
|
||||
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void unexpected()
|
||||
{
|
||||
(*get_unexpected())();
|
||||
// unexpected handler should not return
|
||||
terminate();
|
||||
}
|
||||
|
||||
terminate_handler
|
||||
set_terminate(terminate_handler func) _NOEXCEPT
|
||||
{
|
||||
return __libcpp_atomic_exchange(&__terminate_handler, func);
|
||||
}
|
||||
|
||||
terminate_handler
|
||||
get_terminate() _NOEXCEPT
|
||||
{
|
||||
return __libcpp_atomic_load(&__terminate_handler);
|
||||
}
|
||||
|
||||
#ifndef __EMSCRIPTEN__ // We provide this in JS
|
||||
_LIBCPP_NORETURN
|
||||
void
|
||||
terminate() _NOEXCEPT
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
(*get_terminate())();
|
||||
// handler should not return
|
||||
fprintf(stderr, "terminate_handler unexpectedly returned\n");
|
||||
::abort();
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// handler should not throw exception
|
||||
fprintf(stderr, "terminate_handler unexpectedly threw an exception\n");
|
||||
::abort();
|
||||
}
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
#endif // !__EMSCRIPTEN__
|
||||
|
||||
#if !defined(__EMSCRIPTEN__)
|
||||
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();
|
||||
}
|
||||
#endif // !__EMSCRIPTEN__
|
||||
|
||||
|
||||
exception::~exception() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char* exception::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::exception";
|
||||
}
|
||||
|
||||
bad_exception::~bad_exception() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char* bad_exception::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::bad_exception";
|
||||
}
|
||||
|
||||
|
||||
bad_alloc::bad_alloc() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
bad_alloc::~bad_alloc() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
bad_alloc::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::bad_alloc";
|
||||
}
|
||||
|
||||
bad_array_new_length::bad_array_new_length() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
bad_array_new_length::~bad_array_new_length() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
bad_array_new_length::what() const _NOEXCEPT
|
||||
{
|
||||
return "bad_array_new_length";
|
||||
}
|
||||
|
||||
bad_cast::bad_cast() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
bad_typeid::bad_typeid() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
bad_cast::~bad_cast() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
bad_cast::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::bad_cast";
|
||||
}
|
||||
|
||||
bad_typeid::~bad_typeid() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
bad_typeid::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::bad_typeid";
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
32
lib/libcxx/src/support/runtime/exception_glibcxx.ipp
Normal file
32
lib/libcxx/src/support/runtime/exception_glibcxx.ipp
Normal file
@@ -0,0 +1,32 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __GLIBCXX__
|
||||
#error header can only be used when targeting libstdc++ or libsupc++
|
||||
#endif
|
||||
|
||||
namespace std {
|
||||
|
||||
bad_alloc::bad_alloc() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
bad_array_new_length::bad_array_new_length() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
bad_cast::bad_cast() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
bad_typeid::bad_typeid() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
27
lib/libcxx/src/support/runtime/exception_libcxxabi.ipp
Normal file
27
lib/libcxx/src/support/runtime/exception_libcxxabi.ipp
Normal file
@@ -0,0 +1,27 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPPABI_VERSION
|
||||
#error this header can only be used with libc++abi
|
||||
#endif
|
||||
|
||||
namespace std {
|
||||
|
||||
bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; }
|
||||
|
||||
int uncaught_exceptions() _NOEXCEPT
|
||||
{
|
||||
# if _LIBCPPABI_VERSION > 1001
|
||||
return __cxa_uncaught_exceptions();
|
||||
# else
|
||||
return __cxa_uncaught_exception() ? 1 : 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
25
lib/libcxx/src/support/runtime/exception_libcxxrt.ipp
Normal file
25
lib/libcxx/src/support/runtime/exception_libcxxrt.ipp
Normal file
@@ -0,0 +1,25 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LIBCXXRT
|
||||
#error this header may only be used when targeting libcxxrt
|
||||
#endif
|
||||
|
||||
namespace std {
|
||||
|
||||
bad_exception::~bad_exception() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char* bad_exception::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::bad_exception";
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
163
lib/libcxx/src/support/runtime/exception_msvc.ipp
Normal file
163
lib/libcxx/src/support/runtime/exception_msvc.ipp
Normal file
@@ -0,0 +1,163 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP_ABI_MICROSOFT
|
||||
#error this header can only be used when targeting the MSVC ABI
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
extern "C" {
|
||||
typedef void (__cdecl* terminate_handler)();
|
||||
_LIBCPP_CRT_FUNC terminate_handler __cdecl set_terminate(
|
||||
terminate_handler _NewTerminateHandler) throw();
|
||||
_LIBCPP_CRT_FUNC terminate_handler __cdecl _get_terminate();
|
||||
|
||||
typedef void (__cdecl* unexpected_handler)();
|
||||
unexpected_handler __cdecl set_unexpected(
|
||||
unexpected_handler _NewUnexpectedHandler) throw();
|
||||
unexpected_handler __cdecl _get_unexpected();
|
||||
|
||||
int __cdecl __uncaught_exceptions();
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
||||
unexpected_handler
|
||||
set_unexpected(unexpected_handler func) _NOEXCEPT {
|
||||
return ::set_unexpected(func);
|
||||
}
|
||||
|
||||
unexpected_handler get_unexpected() _NOEXCEPT {
|
||||
return ::_get_unexpected();
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void unexpected() {
|
||||
(*get_unexpected())();
|
||||
// unexpected handler should not return
|
||||
terminate();
|
||||
}
|
||||
|
||||
terminate_handler set_terminate(terminate_handler func) _NOEXCEPT {
|
||||
return ::set_terminate(func);
|
||||
}
|
||||
|
||||
terminate_handler get_terminate() _NOEXCEPT {
|
||||
return ::_get_terminate();
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void terminate() _NOEXCEPT
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
(*get_terminate())();
|
||||
// handler should not return
|
||||
fprintf(stderr, "terminate_handler unexpectedly returned\n");
|
||||
::abort();
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// handler should not throw exception
|
||||
fprintf(stderr, "terminate_handler unexpectedly threw an exception\n");
|
||||
::abort();
|
||||
}
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
|
||||
bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; }
|
||||
|
||||
int uncaught_exceptions() _NOEXCEPT {
|
||||
return __uncaught_exceptions();
|
||||
}
|
||||
|
||||
#if !defined(_LIBCPP_ABI_VCRUNTIME)
|
||||
bad_cast::bad_cast() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
bad_cast::~bad_cast() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char *
|
||||
bad_cast::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::bad_cast";
|
||||
}
|
||||
|
||||
bad_typeid::bad_typeid() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
bad_typeid::~bad_typeid() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char *
|
||||
bad_typeid::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::bad_typeid";
|
||||
}
|
||||
|
||||
exception::~exception() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char* exception::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::exception";
|
||||
}
|
||||
|
||||
|
||||
bad_exception::~bad_exception() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char* bad_exception::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::bad_exception";
|
||||
}
|
||||
|
||||
|
||||
bad_alloc::bad_alloc() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
bad_alloc::~bad_alloc() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
bad_alloc::what() const _NOEXCEPT
|
||||
{
|
||||
return "std::bad_alloc";
|
||||
}
|
||||
|
||||
bad_array_new_length::bad_array_new_length() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
bad_array_new_length::~bad_array_new_length() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
bad_array_new_length::what() const _NOEXCEPT
|
||||
{
|
||||
return "bad_array_new_length";
|
||||
}
|
||||
#endif // !_LIBCPP_ABI_VCRUNTIME
|
||||
|
||||
} // namespace std
|
||||
73
lib/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp
Normal file
73
lib/libcxx/src/support/runtime/exception_pointer_cxxabi.ipp
Normal file
@@ -0,0 +1,73 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef HAVE_DEPENDENT_EH_ABI
|
||||
#error this header may only be used with libc++abi or libcxxrt
|
||||
#endif
|
||||
|
||||
namespace std {
|
||||
|
||||
exception_ptr::~exception_ptr() _NOEXCEPT {
|
||||
__cxa_decrement_exception_refcount(__ptr_);
|
||||
}
|
||||
|
||||
exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
|
||||
: __ptr_(other.__ptr_)
|
||||
{
|
||||
__cxa_increment_exception_refcount(__ptr_);
|
||||
}
|
||||
|
||||
exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
|
||||
{
|
||||
if (__ptr_ != other.__ptr_)
|
||||
{
|
||||
__cxa_increment_exception_refcount(other.__ptr_);
|
||||
__cxa_decrement_exception_refcount(__ptr_);
|
||||
__ptr_ = other.__ptr_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
nested_exception::nested_exception() _NOEXCEPT
|
||||
: __ptr_(current_exception())
|
||||
{
|
||||
}
|
||||
|
||||
nested_exception::~nested_exception() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void
|
||||
nested_exception::rethrow_nested() const
|
||||
{
|
||||
if (__ptr_ == nullptr)
|
||||
terminate();
|
||||
rethrow_exception(__ptr_);
|
||||
}
|
||||
|
||||
exception_ptr current_exception() _NOEXCEPT
|
||||
{
|
||||
// be nicer if there was a constructor that took a ptr, then
|
||||
// this whole function would be just:
|
||||
// return exception_ptr(__cxa_current_primary_exception());
|
||||
exception_ptr ptr;
|
||||
ptr.__ptr_ = __cxa_current_primary_exception();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void rethrow_exception(exception_ptr p)
|
||||
{
|
||||
__cxa_rethrow_primary_exception(p.__ptr_);
|
||||
// if p.__ptr_ is NULL, above returns so we terminate
|
||||
terminate();
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
77
lib/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp
Normal file
77
lib/libcxx/src/support/runtime/exception_pointer_glibcxx.ipp
Normal file
@@ -0,0 +1,77 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// libsupc++ does not implement the dependent EH ABI and the functionality
|
||||
// it uses to implement std::exception_ptr (which it declares as an alias of
|
||||
// std::__exception_ptr::exception_ptr) is not directly exported to clients. So
|
||||
// we have little choice but to hijack std::__exception_ptr::exception_ptr's
|
||||
// (which fortunately has the same layout as our std::exception_ptr) copy
|
||||
// constructor, assignment operator and destructor (which are part of its
|
||||
// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr)
|
||||
// function.
|
||||
|
||||
namespace std {
|
||||
|
||||
namespace __exception_ptr
|
||||
{
|
||||
|
||||
struct exception_ptr
|
||||
{
|
||||
void* __ptr_;
|
||||
|
||||
exception_ptr(const exception_ptr&) _NOEXCEPT;
|
||||
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
|
||||
~exception_ptr() _NOEXCEPT;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr);
|
||||
|
||||
exception_ptr::~exception_ptr() _NOEXCEPT
|
||||
{
|
||||
reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr();
|
||||
}
|
||||
|
||||
exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
|
||||
: __ptr_(other.__ptr_)
|
||||
{
|
||||
new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr(
|
||||
reinterpret_cast<const __exception_ptr::exception_ptr&>(other));
|
||||
}
|
||||
|
||||
exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
|
||||
{
|
||||
*reinterpret_cast<__exception_ptr::exception_ptr*>(this) =
|
||||
reinterpret_cast<const __exception_ptr::exception_ptr&>(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
nested_exception::nested_exception() _NOEXCEPT
|
||||
: __ptr_(current_exception())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void
|
||||
nested_exception::rethrow_nested() const
|
||||
{
|
||||
if (__ptr_ == nullptr)
|
||||
terminate();
|
||||
rethrow_exception(__ptr_);
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void rethrow_exception(exception_ptr p)
|
||||
{
|
||||
rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p));
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
86
lib/libcxx/src/support/runtime/exception_pointer_msvc.ipp
Normal file
86
lib/libcxx/src/support/runtime/exception_pointer_msvc.ipp
Normal file
@@ -0,0 +1,86 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrCreate(void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrDestroy(void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrCopy(void*, const void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrAssign(void*, const void*);
|
||||
_LIBCPP_CRT_FUNC bool __cdecl __ExceptionPtrCompare(const void*, const void*);
|
||||
_LIBCPP_CRT_FUNC bool __cdecl __ExceptionPtrToBool(const void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrSwap(void*, void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrCurrentException(void*);
|
||||
[[noreturn]] _LIBCPP_CRT_FUNC void __cdecl __ExceptionPtrRethrow(const void*);
|
||||
_LIBCPP_CRT_FUNC void __cdecl
|
||||
__ExceptionPtrCopyException(void*, const void*, const void*);
|
||||
|
||||
namespace std {
|
||||
|
||||
exception_ptr::exception_ptr() _NOEXCEPT { __ExceptionPtrCreate(this); }
|
||||
exception_ptr::exception_ptr(nullptr_t) _NOEXCEPT { __ExceptionPtrCreate(this); }
|
||||
|
||||
exception_ptr::exception_ptr(const exception_ptr& __other) _NOEXCEPT {
|
||||
__ExceptionPtrCopy(this, &__other);
|
||||
}
|
||||
exception_ptr& exception_ptr::operator=(const exception_ptr& __other) _NOEXCEPT {
|
||||
__ExceptionPtrAssign(this, &__other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
exception_ptr& exception_ptr::operator=(nullptr_t) _NOEXCEPT {
|
||||
exception_ptr dummy;
|
||||
__ExceptionPtrAssign(this, &dummy);
|
||||
return *this;
|
||||
}
|
||||
|
||||
exception_ptr::~exception_ptr() _NOEXCEPT { __ExceptionPtrDestroy(this); }
|
||||
|
||||
exception_ptr::operator bool() const _NOEXCEPT {
|
||||
return __ExceptionPtrToBool(this);
|
||||
}
|
||||
|
||||
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT {
|
||||
return __ExceptionPtrCompare(&__x, &__y);
|
||||
}
|
||||
|
||||
|
||||
void swap(exception_ptr& lhs, exception_ptr& rhs) _NOEXCEPT {
|
||||
__ExceptionPtrSwap(&rhs, &lhs);
|
||||
}
|
||||
|
||||
exception_ptr __copy_exception_ptr(void* __except, const void* __ptr) {
|
||||
exception_ptr __ret = nullptr;
|
||||
if (__ptr)
|
||||
__ExceptionPtrCopyException(&__ret, __except, __ptr);
|
||||
return __ret;
|
||||
}
|
||||
|
||||
exception_ptr current_exception() _NOEXCEPT {
|
||||
exception_ptr __ret;
|
||||
__ExceptionPtrCurrentException(&__ret);
|
||||
return __ret;
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void rethrow_exception(exception_ptr p) { __ExceptionPtrRethrow(&p); }
|
||||
|
||||
nested_exception::nested_exception() _NOEXCEPT : __ptr_(current_exception()) {}
|
||||
|
||||
nested_exception::~nested_exception() _NOEXCEPT {}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void nested_exception::rethrow_nested() const {
|
||||
if (__ptr_ == nullptr)
|
||||
terminate();
|
||||
rethrow_exception(__ptr_);
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
@@ -0,0 +1,79 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace std {
|
||||
|
||||
exception_ptr::~exception_ptr() _NOEXCEPT
|
||||
{
|
||||
# warning exception_ptr not yet implemented
|
||||
fprintf(stderr, "exception_ptr not yet implemented\n");
|
||||
::abort();
|
||||
}
|
||||
|
||||
exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
|
||||
: __ptr_(other.__ptr_)
|
||||
{
|
||||
# warning exception_ptr not yet implemented
|
||||
fprintf(stderr, "exception_ptr not yet implemented\n");
|
||||
::abort();
|
||||
}
|
||||
|
||||
exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
|
||||
{
|
||||
# warning exception_ptr not yet implemented
|
||||
fprintf(stderr, "exception_ptr not yet implemented\n");
|
||||
::abort();
|
||||
}
|
||||
|
||||
nested_exception::nested_exception() _NOEXCEPT
|
||||
: __ptr_(current_exception())
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined(__GLIBCXX__)
|
||||
|
||||
nested_exception::~nested_exception() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void
|
||||
nested_exception::rethrow_nested() const
|
||||
{
|
||||
# warning exception_ptr not yet implemented
|
||||
fprintf(stderr, "exception_ptr not yet implemented\n");
|
||||
::abort();
|
||||
#if 0
|
||||
if (__ptr_ == nullptr)
|
||||
terminate();
|
||||
rethrow_exception(__ptr_);
|
||||
#endif // FIXME
|
||||
}
|
||||
|
||||
exception_ptr current_exception() _NOEXCEPT
|
||||
{
|
||||
# warning exception_ptr not yet implemented
|
||||
fprintf(stderr, "exception_ptr not yet implemented\n");
|
||||
::abort();
|
||||
}
|
||||
|
||||
_LIBCPP_NORETURN
|
||||
void rethrow_exception(exception_ptr p)
|
||||
{
|
||||
# warning exception_ptr not yet implemented
|
||||
fprintf(stderr, "exception_ptr not yet implemented\n");
|
||||
::abort();
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
26
lib/libcxx/src/support/runtime/new_handler_fallback.ipp
Normal file
26
lib/libcxx/src/support/runtime/new_handler_fallback.ipp
Normal file
@@ -0,0 +1,26 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace std {
|
||||
|
||||
_LIBCPP_SAFE_STATIC static std::new_handler __new_handler;
|
||||
|
||||
new_handler
|
||||
set_new_handler(new_handler handler) _NOEXCEPT
|
||||
{
|
||||
return __libcpp_atomic_exchange(&__new_handler, handler);
|
||||
}
|
||||
|
||||
new_handler
|
||||
get_new_handler() _NOEXCEPT
|
||||
{
|
||||
return __libcpp_atomic_load(&__new_handler);
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
64
lib/libcxx/src/support/runtime/stdexcept_default.ipp
Normal file
64
lib/libcxx/src/support/runtime/stdexcept_default.ipp
Normal file
@@ -0,0 +1,64 @@
|
||||
//===--------------------- stdexcept_default.ipp --------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../../include/refstring.h"
|
||||
|
||||
/* For _LIBCPPABI_VERSION */
|
||||
#if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \
|
||||
(defined(LIBCXX_BUILDING_LIBCXXABI) || defined(LIBCXXRT))
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char*), "");
|
||||
|
||||
namespace std // purposefully not using versioning namespace
|
||||
{
|
||||
|
||||
logic_error::logic_error(const string& msg) : __imp_(msg.c_str()) {}
|
||||
|
||||
logic_error::logic_error(const char* msg) : __imp_(msg) {}
|
||||
|
||||
logic_error::logic_error(const logic_error& le) _NOEXCEPT : __imp_(le.__imp_) {}
|
||||
|
||||
logic_error& logic_error::operator=(const logic_error& le) _NOEXCEPT {
|
||||
__imp_ = le.__imp_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
runtime_error::runtime_error(const string& msg) : __imp_(msg.c_str()) {}
|
||||
|
||||
runtime_error::runtime_error(const char* msg) : __imp_(msg) {}
|
||||
|
||||
runtime_error::runtime_error(const runtime_error& re) _NOEXCEPT
|
||||
: __imp_(re.__imp_) {}
|
||||
|
||||
runtime_error& runtime_error::operator=(const runtime_error& re) _NOEXCEPT {
|
||||
__imp_ = re.__imp_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX)
|
||||
|
||||
const char* logic_error::what() const _NOEXCEPT { return __imp_.c_str(); }
|
||||
|
||||
const char* runtime_error::what() const _NOEXCEPT { return __imp_.c_str(); }
|
||||
|
||||
logic_error::~logic_error() _NOEXCEPT {}
|
||||
domain_error::~domain_error() _NOEXCEPT {}
|
||||
invalid_argument::~invalid_argument() _NOEXCEPT {}
|
||||
length_error::~length_error() _NOEXCEPT {}
|
||||
out_of_range::~out_of_range() _NOEXCEPT {}
|
||||
|
||||
runtime_error::~runtime_error() _NOEXCEPT {}
|
||||
range_error::~range_error() _NOEXCEPT {}
|
||||
overflow_error::~overflow_error() _NOEXCEPT {}
|
||||
underflow_error::~underflow_error() _NOEXCEPT {}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace std
|
||||
16
lib/libcxx/src/support/runtime/stdexcept_vcruntime.ipp
Normal file
16
lib/libcxx/src/support/runtime/stdexcept_vcruntime.ipp
Normal file
@@ -0,0 +1,16 @@
|
||||
//===------------------- stdexcept_vcruntime.ipp --------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP_ABI_VCRUNTIME
|
||||
#error This file may only be used when defering to vcruntime
|
||||
#endif
|
||||
|
||||
namespace std {
|
||||
logic_error::logic_error(std::string const& s) : exception(s.c_str()) {}
|
||||
runtime_error::runtime_error(std::string const& s) : exception(s.c_str()) {}
|
||||
} // namespace std
|
||||
4
lib/libcxx/src/support/solaris/README
Normal file
4
lib/libcxx/src/support/solaris/README
Normal file
@@ -0,0 +1,4 @@
|
||||
This directory contains a partial implementation of the xlocale APIs for
|
||||
Solaris. Some portions are lifted from FreeBSD libc, and so are covered by a
|
||||
2-clause BSD license instead of the MIT/UUIC license that the rest of libc++ is
|
||||
distributed under.
|
||||
76
lib/libcxx/src/support/solaris/mbsnrtowcs.inc
Normal file
76
lib/libcxx/src/support/solaris/mbsnrtowcs.inc
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
|
||||
/*-
|
||||
* As noted in the source, some portions of this implementation are copied from
|
||||
* FreeBSD libc. These are covered by the following copyright:
|
||||
*
|
||||
* Copyright (c) 2002-2004 Tim J. Robbins.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
size_t
|
||||
mbsnrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src,
|
||||
size_t nms, size_t len, mbstate_t * __restrict ps, locale_t loc)
|
||||
{
|
||||
const char *s;
|
||||
size_t nchr;
|
||||
wchar_t wc;
|
||||
size_t nb;
|
||||
FIX_LOCALE(loc);
|
||||
|
||||
s = *src;
|
||||
nchr = 0;
|
||||
|
||||
if (dst == NULL) {
|
||||
for (;;) {
|
||||
if ((nb = mbrtowc_l(&wc, s, nms, ps, loc)) == (size_t)-1)
|
||||
/* Invalid sequence - mbrtowc() sets errno. */
|
||||
return ((size_t)-1);
|
||||
else if (nb == 0 || nb == (size_t)-2)
|
||||
return (nchr);
|
||||
s += nb;
|
||||
nms -= nb;
|
||||
nchr++;
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
while (len-- > 0) {
|
||||
if ((nb = mbrtowc_l(dst, s, nms, ps, loc)) == (size_t)-1) {
|
||||
*src = s;
|
||||
return ((size_t)-1);
|
||||
} else if (nb == (size_t)-2) {
|
||||
*src = s + nms;
|
||||
return (nchr);
|
||||
} else if (nb == 0) {
|
||||
*src = NULL;
|
||||
return (nchr);
|
||||
}
|
||||
s += nb;
|
||||
nms -= nb;
|
||||
nchr++;
|
||||
dst++;
|
||||
}
|
||||
*src = s;
|
||||
return (nchr);
|
||||
}
|
||||
92
lib/libcxx/src/support/solaris/wcsnrtombs.inc
Normal file
92
lib/libcxx/src/support/solaris/wcsnrtombs.inc
Normal file
@@ -0,0 +1,92 @@
|
||||
/*-
|
||||
* Copyright (c) 2002-2004 Tim J. Robbins.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
size_t
|
||||
wcsnrtombs_l(char * __restrict dst, const wchar_t ** __restrict src,
|
||||
size_t nwc, size_t len, mbstate_t * __restrict ps, locale_t loc)
|
||||
{
|
||||
FIX_LOCALE(loc);
|
||||
mbstate_t mbsbak;
|
||||
char buf[MB_CUR_MAX_L(loc)];
|
||||
const wchar_t *s;
|
||||
size_t nbytes;
|
||||
size_t nb;
|
||||
|
||||
s = *src;
|
||||
nbytes = 0;
|
||||
|
||||
if (dst == NULL) {
|
||||
while (nwc-- > 0) {
|
||||
if ((nb = wcrtomb_l(buf, *s, ps, loc)) == (size_t)-1)
|
||||
/* Invalid character - wcrtomb() sets errno. */
|
||||
return ((size_t)-1);
|
||||
else if (*s == L'\0')
|
||||
return (nbytes + nb - 1);
|
||||
s++;
|
||||
nbytes += nb;
|
||||
}
|
||||
return (nbytes);
|
||||
}
|
||||
|
||||
while (len > 0 && nwc-- > 0) {
|
||||
if (len > (size_t)MB_CUR_MAX_L(loc)) {
|
||||
/* Enough space to translate in-place. */
|
||||
if ((nb = wcrtomb_l(dst, *s, ps, loc)) == (size_t)-1) {
|
||||
*src = s;
|
||||
return ((size_t)-1);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* May not be enough space; use temp. buffer.
|
||||
*
|
||||
* We need to save a copy of the conversion state
|
||||
* here so we can restore it if the multibyte
|
||||
* character is too long for the buffer.
|
||||
*/
|
||||
mbsbak = *ps;
|
||||
if ((nb = wcrtomb_l(buf, *s, ps, loc)) == (size_t)-1) {
|
||||
*src = s;
|
||||
return ((size_t)-1);
|
||||
}
|
||||
if (nb > (int)len) {
|
||||
/* MB sequence for character won't fit. */
|
||||
*ps = mbsbak;
|
||||
break;
|
||||
}
|
||||
memcpy(dst, buf, nb);
|
||||
}
|
||||
if (*s == L'\0') {
|
||||
*src = NULL;
|
||||
return (nbytes + nb - 1);
|
||||
}
|
||||
s++;
|
||||
dst += nb;
|
||||
len -= nb;
|
||||
nbytes += nb;
|
||||
}
|
||||
*src = s;
|
||||
return (nbytes);
|
||||
}
|
||||
68
lib/libcxx/src/support/solaris/xlocale.cpp
Normal file
68
lib/libcxx/src/support/solaris/xlocale.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifdef __sun__
|
||||
|
||||
#include "support/solaris/xlocale.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/localedef.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
int isxdigit_l(int __c, locale_t __l) {
|
||||
return isxdigit(__c);
|
||||
}
|
||||
|
||||
int iswxdigit_l(wint_t __c, locale_t __l) {
|
||||
return isxdigit(__c);
|
||||
}
|
||||
|
||||
// FIXME: This disregards the locale, which is Very Wrong
|
||||
#define vsnprintf_l(__s, __n, __l, __format, __va) \
|
||||
vsnprintf(__s, __n, __format, __va)
|
||||
|
||||
int snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...)
|
||||
{
|
||||
va_list __va;
|
||||
va_start(__va, __format);
|
||||
int __res = vsnprintf_l(__s, __n , __l, __format, __va);
|
||||
va_end(__va);
|
||||
return __res;
|
||||
}
|
||||
|
||||
int asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
|
||||
va_list __va;
|
||||
va_start(__va, __format);
|
||||
// FIXME:
|
||||
int __res = vasprintf(__s, __format, __va);
|
||||
va_end(__va);
|
||||
return __res;
|
||||
}
|
||||
|
||||
int sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
|
||||
va_list __va;
|
||||
va_start(__va, __format);
|
||||
// FIXME:
|
||||
int __res = vsscanf(__s, __format, __va);
|
||||
va_end(__va);
|
||||
return __res;
|
||||
}
|
||||
|
||||
size_t mbrtowc_l(wchar_t *__pwc, const char *__pmb,
|
||||
size_t __max, mbstate_t *__ps, locale_t __loc) {
|
||||
return mbrtowc(__pwc, __pmb, __max, __ps);
|
||||
}
|
||||
|
||||
struct lconv *localeconv_l(locale_t __l) {
|
||||
return localeconv();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // __sun__
|
||||
139
lib/libcxx/src/support/win32/locale_win32.cpp
Normal file
139
lib/libcxx/src/support/win32/locale_win32.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
// -*- C++ -*-
|
||||
//===-------------------- support/win32/locale_win32.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 <locale>
|
||||
#include <cstdarg> // va_start, va_end
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
int __libcpp_vasprintf(char **sptr, const char *__restrict fmt, va_list ap);
|
||||
|
||||
using std::__libcpp_locale_guard;
|
||||
|
||||
// FIXME: base currently unused. Needs manual work to construct the new locale
|
||||
locale_t newlocale( int mask, const char * locale, locale_t /*base*/ )
|
||||
{
|
||||
return {_create_locale( LC_ALL, locale ), locale};
|
||||
}
|
||||
|
||||
decltype(MB_CUR_MAX) MB_CUR_MAX_L( locale_t __l )
|
||||
{
|
||||
#if defined(_LIBCPP_MSVCRT)
|
||||
return ___mb_cur_max_l_func(__l);
|
||||
#else
|
||||
__libcpp_locale_guard __current(__l);
|
||||
return MB_CUR_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
lconv *localeconv_l( locale_t &loc )
|
||||
{
|
||||
__libcpp_locale_guard __current(loc);
|
||||
lconv *lc = localeconv();
|
||||
if (!lc)
|
||||
return lc;
|
||||
return loc.__store_lconv(lc);
|
||||
}
|
||||
size_t mbrlen_l( const char *__restrict s, size_t n,
|
||||
mbstate_t *__restrict ps, locale_t loc )
|
||||
{
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return mbrlen( s, n, ps );
|
||||
}
|
||||
size_t mbsrtowcs_l( wchar_t *__restrict dst, const char **__restrict src,
|
||||
size_t len, mbstate_t *__restrict ps, locale_t loc )
|
||||
{
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return mbsrtowcs( dst, src, len, ps );
|
||||
}
|
||||
size_t wcrtomb_l( char *__restrict s, wchar_t wc, mbstate_t *__restrict ps,
|
||||
locale_t loc )
|
||||
{
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return wcrtomb( s, wc, ps );
|
||||
}
|
||||
size_t mbrtowc_l( wchar_t *__restrict pwc, const char *__restrict s,
|
||||
size_t n, mbstate_t *__restrict ps, locale_t loc )
|
||||
{
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return mbrtowc( pwc, s, n, ps );
|
||||
}
|
||||
size_t mbsnrtowcs_l( wchar_t *__restrict dst, const char **__restrict src,
|
||||
size_t nms, size_t len, mbstate_t *__restrict ps, locale_t loc )
|
||||
{
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return mbsnrtowcs( dst, src, nms, len, ps );
|
||||
}
|
||||
size_t wcsnrtombs_l( char *__restrict dst, const wchar_t **__restrict src,
|
||||
size_t nwc, size_t len, mbstate_t *__restrict ps, locale_t loc )
|
||||
{
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return wcsnrtombs( dst, src, nwc, len, ps );
|
||||
}
|
||||
wint_t btowc_l( int c, locale_t loc )
|
||||
{
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return btowc( c );
|
||||
}
|
||||
int wctob_l( wint_t c, locale_t loc )
|
||||
{
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return wctob( c );
|
||||
}
|
||||
|
||||
int snprintf_l(char *ret, size_t n, locale_t loc, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, format );
|
||||
#if defined(_LIBCPP_MSVCRT)
|
||||
// FIXME: Remove usage of internal CRT function and globals.
|
||||
int result = __stdio_common_vsprintf(
|
||||
_CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR,
|
||||
ret, n, format, loc, ap);
|
||||
#else
|
||||
__libcpp_locale_guard __current(loc);
|
||||
int result = vsnprintf( ret, n, format, ap );
|
||||
#endif
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
||||
|
||||
int asprintf_l( char **ret, locale_t loc, const char *format, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, format );
|
||||
int result = vasprintf_l( ret, loc, format, ap );
|
||||
va_end(ap);
|
||||
return result;
|
||||
}
|
||||
int vasprintf_l( char **ret, locale_t loc, const char *format, va_list ap )
|
||||
{
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return __libcpp_vasprintf( ret, format, ap );
|
||||
}
|
||||
|
||||
#if !defined(_LIBCPP_MSVCRT)
|
||||
float strtof_l(const char* nptr, char** endptr, locale_t loc) {
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return strtof(nptr, endptr);
|
||||
}
|
||||
|
||||
long double strtold_l(const char* nptr, char** endptr, locale_t loc) {
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return strtold(nptr, endptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800
|
||||
size_t strftime_l(char *ret, size_t n, const char *format, const struct tm *tm,
|
||||
locale_t loc) {
|
||||
__libcpp_locale_guard __current(loc);
|
||||
return strftime(ret, n, format, tm);
|
||||
}
|
||||
#endif
|
||||
164
lib/libcxx/src/support/win32/support.cpp
Normal file
164
lib/libcxx/src/support/win32/support.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------- support/win32/support.h ----------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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.
|
||||
int count = _vsnprintf( NULL, 0, format, ap );
|
||||
if (count < 0)
|
||||
return count;
|
||||
size_t buffer_size = static_cast<size_t>(count) + 1;
|
||||
char* p = static_cast<char*>(malloc(buffer_size));
|
||||
if ( ! p )
|
||||
return -1;
|
||||
// If we haven't used exactly what was required, something is wrong.
|
||||
// Maybe bug in vsnprintf. Report the error and return.
|
||||
if (_vsnprintf(p, buffer_size, format, ap) != count) {
|
||||
free(p);
|
||||
return -1;
|
||||
}
|
||||
// All good. This is returning memory to the caller not freeing it.
|
||||
*sptr = p;
|
||||
return count;
|
||||
}
|
||||
|
||||
// Returns >= 0: the number of wide characters found in the
|
||||
// multi byte sequence src (of src_size_bytes), that fit in the buffer dst
|
||||
// (of max_dest_chars elements size). The count returned excludes the
|
||||
// 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;
|
||||
}
|
||||
275
lib/libcxx/src/support/win32/thread_win32.cpp
Normal file
275
lib/libcxx/src/support/win32/thread_win32.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
// -*- C++ -*-
|
||||
//===-------------------- support/win32/thread_win32.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 <__threading_support>
|
||||
#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)
|
||||
{
|
||||
using namespace chrono;
|
||||
// round-up to the nearest milisecond
|
||||
milliseconds __ms =
|
||||
duration_cast<milliseconds>(__ns + chrono::nanoseconds(999999));
|
||||
// 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
|
||||
295
lib/libcxx/src/system_error.cpp
Normal file
295
lib/libcxx/src/system_error.cpp
Normal file
@@ -0,0 +1,295 @@
|
||||
//===---------------------- system_error.cpp ------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "__config"
|
||||
|
||||
#include "system_error"
|
||||
|
||||
#include "include/config_elast.h"
|
||||
#include "cerrno"
|
||||
#include "cstring"
|
||||
#include "cstdio"
|
||||
#include "cstdlib"
|
||||
#include "string"
|
||||
#include "string.h"
|
||||
#include "__debug"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/api-level.h>
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// class error_category
|
||||
|
||||
#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
|
||||
error_category::error_category() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
error_category::~error_category() _NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
error_condition
|
||||
error_category::default_error_condition(int ev) const _NOEXCEPT
|
||||
{
|
||||
return error_condition(ev, *this);
|
||||
}
|
||||
|
||||
bool
|
||||
error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
|
||||
{
|
||||
return default_error_condition(code) == condition;
|
||||
}
|
||||
|
||||
bool
|
||||
error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
|
||||
{
|
||||
return *this == code.category() && code.value() == condition;
|
||||
}
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_THREADS)
|
||||
namespace {
|
||||
|
||||
// GLIBC also uses 1024 as the maximum buffer size internally.
|
||||
constexpr size_t strerror_buff_size = 1024;
|
||||
|
||||
string do_strerror_r(int ev);
|
||||
|
||||
#if defined(_LIBCPP_MSVCRT_LIKE)
|
||||
string do_strerror_r(int ev) {
|
||||
char buffer[strerror_buff_size];
|
||||
if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
|
||||
return string(buffer);
|
||||
std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
|
||||
return string(buffer);
|
||||
}
|
||||
#else
|
||||
|
||||
// Only one of the two following functions will be used, depending on
|
||||
// the return type of strerror_r:
|
||||
|
||||
// For the GNU variant, a char* return value:
|
||||
__attribute__((unused)) const char *
|
||||
handle_strerror_r_return(char *strerror_return, char *buffer) {
|
||||
// GNU always returns a string pointer in its return value. The
|
||||
// string might point to either the input buffer, or a static
|
||||
// buffer, but we don't care which.
|
||||
return strerror_return;
|
||||
}
|
||||
|
||||
// For the POSIX variant: an int return value.
|
||||
__attribute__((unused)) const char *
|
||||
handle_strerror_r_return(int strerror_return, char *buffer) {
|
||||
// The POSIX variant either:
|
||||
// - fills in the provided buffer and returns 0
|
||||
// - returns a positive error value, or
|
||||
// - 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_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
|
||||
225
lib/libcxx/src/thread.cpp
Normal file
225
lib/libcxx/src/thread.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
//===------------------------- thread.cpp----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "__config"
|
||||
#ifndef _LIBCPP_HAS_NO_THREADS
|
||||
|
||||
#include "thread"
|
||||
#include "exception"
|
||||
#include "vector"
|
||||
#include "future"
|
||||
#include "limits"
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||
# include <sys/param.h>
|
||||
# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
||||
# include <sys/sysctl.h>
|
||||
# endif
|
||||
#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__CloudABI__) || defined(__Fuchsia__) || defined(__wasi__)
|
||||
# include <unistd.h>
|
||||
#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__CloudABI__) || defined(__Fuchsia__) || defined(__wasi__)
|
||||
|
||||
#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(CTL_HW) && defined(HW_NCPU)
|
||||
unsigned n;
|
||||
int mib[2] = {CTL_HW, HW_NCPU};
|
||||
std::size_t s = sizeof(n);
|
||||
sysctl(mib, 2, &n, &s, 0, 0);
|
||||
return n;
|
||||
#elif defined(_SC_NPROCESSORS_ONLN)
|
||||
long result = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
// sysconf returns -1 if the name is invalid, the option does not exist or
|
||||
// does not have a definite limit.
|
||||
// if sysconf returns some other negative number, we have no idea
|
||||
// what is going on. Default to something safe.
|
||||
if (result < 0)
|
||||
return 0;
|
||||
return static_cast<unsigned>(result);
|
||||
#elif defined(_LIBCPP_WIN32API)
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
return info.dwNumberOfProcessors;
|
||||
#else // defined(CTL_HW) && defined(HW_NCPU)
|
||||
// TODO: grovel through /proc or check cpuid on x86 and similar
|
||||
// instructions on other architectures.
|
||||
# if defined(_LIBCPP_WARNING)
|
||||
_LIBCPP_WARNING("hardware_concurrency not yet implemented")
|
||||
# else
|
||||
# warning hardware_concurrency not yet implemented
|
||||
# endif
|
||||
return 0; // Means not computable [thread.thread.static]
|
||||
#endif // defined(CTL_HW) && defined(HW_NCPU)
|
||||
}
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
|
||||
void
|
||||
sleep_for(const chrono::nanoseconds& ns)
|
||||
{
|
||||
if (ns > chrono::nanoseconds::zero())
|
||||
{
|
||||
__libcpp_thread_sleep_for(ns);
|
||||
}
|
||||
}
|
||||
|
||||
} // this_thread
|
||||
|
||||
__thread_specific_ptr<__thread_struct>&
|
||||
__thread_local_data()
|
||||
{
|
||||
static __thread_specific_ptr<__thread_struct> __p;
|
||||
return __p;
|
||||
}
|
||||
|
||||
// __thread_struct_imp
|
||||
|
||||
template <class T>
|
||||
class _LIBCPP_HIDDEN __hidden_allocator
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
T* allocate(size_t __n)
|
||||
{return static_cast<T*>(::operator new(__n * sizeof(T)));}
|
||||
void deallocate(T* __p, size_t) {::operator delete(static_cast<void*>(__p));}
|
||||
|
||||
size_t max_size() const {return size_t(~0) / sizeof(T);}
|
||||
};
|
||||
|
||||
class _LIBCPP_HIDDEN __thread_struct_imp
|
||||
{
|
||||
typedef vector<__assoc_sub_state*,
|
||||
__hidden_allocator<__assoc_sub_state*> > _AsyncStates;
|
||||
typedef vector<pair<condition_variable*, mutex*>,
|
||||
__hidden_allocator<pair<condition_variable*, mutex*> > > _Notify;
|
||||
|
||||
_AsyncStates async_states_;
|
||||
_Notify notify_;
|
||||
|
||||
__thread_struct_imp(const __thread_struct_imp&);
|
||||
__thread_struct_imp& operator=(const __thread_struct_imp&);
|
||||
public:
|
||||
__thread_struct_imp() {}
|
||||
~__thread_struct_imp();
|
||||
|
||||
void notify_all_at_thread_exit(condition_variable* cv, mutex* m);
|
||||
void __make_ready_at_thread_exit(__assoc_sub_state* __s);
|
||||
};
|
||||
|
||||
__thread_struct_imp::~__thread_struct_imp()
|
||||
{
|
||||
for (_Notify::iterator i = notify_.begin(), e = notify_.end();
|
||||
i != e; ++i)
|
||||
{
|
||||
i->second->unlock();
|
||||
i->first->notify_all();
|
||||
}
|
||||
for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end();
|
||||
i != e; ++i)
|
||||
{
|
||||
(*i)->__make_ready();
|
||||
(*i)->__release_shared();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
|
||||
{
|
||||
notify_.push_back(pair<condition_variable*, mutex*>(cv, m));
|
||||
}
|
||||
|
||||
void
|
||||
__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s)
|
||||
{
|
||||
async_states_.push_back(__s);
|
||||
__s->__add_shared();
|
||||
}
|
||||
|
||||
// __thread_struct
|
||||
|
||||
__thread_struct::__thread_struct()
|
||||
: __p_(new __thread_struct_imp)
|
||||
{
|
||||
}
|
||||
|
||||
__thread_struct::~__thread_struct()
|
||||
{
|
||||
delete __p_;
|
||||
}
|
||||
|
||||
void
|
||||
__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m)
|
||||
{
|
||||
__p_->notify_all_at_thread_exit(cv, m);
|
||||
}
|
||||
|
||||
void
|
||||
__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s)
|
||||
{
|
||||
__p_->__make_ready_at_thread_exit(__s);
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // !_LIBCPP_HAS_NO_THREADS
|
||||
57
lib/libcxx/src/typeinfo.cpp
Normal file
57
lib/libcxx/src/typeinfo.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
//===------------------------- typeinfo.cpp -------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "typeinfo"
|
||||
|
||||
#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_ABI_VCRUNTIME)
|
||||
#include <string.h>
|
||||
|
||||
int std::type_info::__compare(const type_info &__rhs) const _NOEXCEPT {
|
||||
if (&__data == &__rhs.__data)
|
||||
return 0;
|
||||
return strcmp(&__data.__decorated_name[1], &__rhs.__data.__decorated_name[1]);
|
||||
}
|
||||
|
||||
const char *std::type_info::name() const _NOEXCEPT {
|
||||
// TODO(compnerd) cache demangled &__data.__decorated_name[1]
|
||||
return &__data.__decorated_name[1];
|
||||
}
|
||||
|
||||
size_t std::type_info::hash_code() const _NOEXCEPT {
|
||||
#if defined(_WIN64)
|
||||
constexpr size_t fnv_offset_basis = 14695981039346656037ull;
|
||||
constexpr size_t fnv_prime = 10995116282110ull;
|
||||
#else
|
||||
constexpr size_t fnv_offset_basis = 2166136261ull;
|
||||
constexpr size_t fnv_prime = 16777619ull;
|
||||
#endif
|
||||
|
||||
size_t value = fnv_offset_basis;
|
||||
for (const char* c = &__data.__decorated_name[1]; *c; ++c) {
|
||||
value ^= static_cast<size_t>(static_cast<unsigned char>(*c));
|
||||
value *= fnv_prime;
|
||||
}
|
||||
|
||||
#if defined(_WIN64)
|
||||
value ^= value >> 32;
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
#endif // _LIBCPP_ABI_MICROSOFT
|
||||
|
||||
// FIXME: Remove the _LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY configuration.
|
||||
#if (!defined(LIBCXX_BUILDING_LIBCXXABI) && \
|
||||
!defined(LIBCXXRT) && \
|
||||
!defined(__GLIBCXX__) && \
|
||||
!defined(_LIBCPP_ABI_VCRUNTIME)) || \
|
||||
defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
|
||||
std::type_info::~type_info()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
15
lib/libcxx/src/utility.cpp
Normal file
15
lib/libcxx/src/utility.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
//===------------------------ utility.cpp ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "utility"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
const piecewise_construct_t piecewise_construct{};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
57
lib/libcxx/src/valarray.cpp
Normal file
57
lib/libcxx/src/valarray.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
//===------------------------ valarray.cpp --------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "valarray"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// These two symbols are part of the v1 ABI but not part of the >=v2 ABI.
|
||||
#if _LIBCPP_ABI_VERSION == 1
|
||||
template _LIBCPP_FUNC_VIS valarray<size_t>::valarray(size_t);
|
||||
template _LIBCPP_FUNC_VIS valarray<size_t>::~valarray();
|
||||
#endif
|
||||
|
||||
template void valarray<size_t>::resize(size_t, size_t);
|
||||
|
||||
void
|
||||
gslice::__init(size_t __start)
|
||||
{
|
||||
valarray<size_t> __indices(__size_.size());
|
||||
size_t __k = __size_.size() != 0;
|
||||
for (size_t __i = 0; __i < __size_.size(); ++__i)
|
||||
__k *= __size_[__i];
|
||||
__1d_.resize(__k);
|
||||
if (__1d_.size())
|
||||
{
|
||||
__k = 0;
|
||||
__1d_[__k] = __start;
|
||||
while (true)
|
||||
{
|
||||
size_t __i = __indices.size() - 1;
|
||||
while (true)
|
||||
{
|
||||
if (++__indices[__i] < __size_[__i])
|
||||
{
|
||||
++__k;
|
||||
__1d_[__k] = __1d_[__k-1] + __stride_[__i];
|
||||
for (size_t __j = __i + 1; __j != __indices.size(); ++__j)
|
||||
__1d_[__k] -= __stride_[__j] * (__size_[__j] - 1);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (__i == 0)
|
||||
return;
|
||||
__indices[__i--] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
17
lib/libcxx/src/variant.cpp
Normal file
17
lib/libcxx/src/variant.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
//===------------------------ variant.cpp ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "variant"
|
||||
|
||||
namespace std {
|
||||
|
||||
const char* bad_variant_access::what() const noexcept {
|
||||
return "bad_variant_access";
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
15
lib/libcxx/src/vector.cpp
Normal file
15
lib/libcxx/src/vector.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
//===------------------------- vector.cpp ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "vector"
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
Reference in New Issue
Block a user