diff options
Diffstat (limited to 'libcxx/src')
-rw-r--r-- | libcxx/src/algorithm.cpp | 48 | ||||
-rw-r--r-- | libcxx/src/bind.cpp | 31 | ||||
-rw-r--r-- | libcxx/src/chrono.cpp | 101 | ||||
-rw-r--r-- | libcxx/src/condition_variable.cpp | 64 | ||||
-rw-r--r-- | libcxx/src/hash.cpp | 485 | ||||
-rw-r--r-- | libcxx/src/ios.cpp | 492 | ||||
-rw-r--r-- | libcxx/src/iostream.cpp | 53 | ||||
-rw-r--r-- | libcxx/src/locale.cpp | 3680 | ||||
-rw-r--r-- | libcxx/src/memory.cpp | 201 | ||||
-rw-r--r-- | libcxx/src/mutex.cpp | 246 | ||||
-rw-r--r-- | libcxx/src/new.cpp | 31 | ||||
-rw-r--r-- | libcxx/src/random.cpp | 46 | ||||
-rw-r--r-- | libcxx/src/stdexcept.cpp | 179 | ||||
-rw-r--r-- | libcxx/src/strstream.cpp | 363 | ||||
-rw-r--r-- | libcxx/src/system_error.cpp | 193 | ||||
-rw-r--r-- | libcxx/src/thread.cpp | 73 | ||||
-rw-r--r-- | libcxx/src/utility.cpp | 16 | ||||
-rw-r--r-- | libcxx/src/valarray.cpp | 54 |
18 files changed, 6356 insertions, 0 deletions
diff --git a/libcxx/src/algorithm.cpp b/libcxx/src/algorithm.cpp new file mode 100644 index 00000000000..09b64d62b1f --- /dev/null +++ b/libcxx/src/algorithm.cpp @@ -0,0 +1,48 @@ +//===----------------------- algorithm.cpp --------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "algorithm" + +_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>&); + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/bind.cpp b/libcxx/src/bind.cpp new file mode 100644 index 00000000000..7b4e3454c2c --- /dev/null +++ b/libcxx/src/bind.cpp @@ -0,0 +1,31 @@ +//===-------------------------- bind.cpp ----------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "functional" + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace placeholders +{ + +__ph<1> _1; +__ph<2> _2; +__ph<3> _3; +__ph<4> _4; +__ph<5> _5; +__ph<6> _6; +__ph<7> _7; +__ph<8> _8; +__ph<9> _9; +__ph<10> _10; + +} // placeholders + + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/chrono.cpp b/libcxx/src/chrono.cpp new file mode 100644 index 00000000000..0130bd2ee15 --- /dev/null +++ b/libcxx/src/chrono.cpp @@ -0,0 +1,101 @@ +//===------------------------- chrono.cpp ---------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "chrono" +#include <sys/time.h> //for gettimeofday and timeval +#include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +// system_clock + +system_clock::time_point +system_clock::now() +{ + timeval tv; + gettimeofday(&tv, 0); + return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); +} + +time_t +system_clock::to_time_t(const time_point& t) +{ + return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); +} + +system_clock::time_point +system_clock::from_time_t(time_t t) +{ + return system_clock::time_point(seconds(t)); +} + +// monotonic_clock + +// 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. + +#pragma GCC visibility push(hidden) + +static +monotonic_clock::rep +monotonic_simplified() +{ + return mach_absolute_time(); +} + +static +double +compute_monotonic_factor() +{ + mach_timebase_info_data_t MachInfo; + mach_timebase_info(&MachInfo); + return static_cast<double>(MachInfo.numer) / MachInfo.denom; +} + +static +monotonic_clock::rep +monotonic_full() +{ + static const double factor = compute_monotonic_factor(); + return static_cast<monotonic_clock::rep>(mach_absolute_time() * factor); +} + +typedef monotonic_clock::rep (*FP)(); + +static +FP +init_monotonic_clock() +{ + mach_timebase_info_data_t MachInfo; + mach_timebase_info(&MachInfo); + if (MachInfo.numer == MachInfo.denom) + return &monotonic_simplified; + return &monotonic_full; +} + +#pragma GCC visiblity pop + +monotonic_clock::time_point +monotonic_clock::now() +{ + static FP fp = init_monotonic_clock(); + return time_point(duration(fp())); +} + +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/condition_variable.cpp b/libcxx/src/condition_variable.cpp new file mode 100644 index 00000000000..14a6d27c373 --- /dev/null +++ b/libcxx/src/condition_variable.cpp @@ -0,0 +1,64 @@ +//===-------------------- condition_variable.cpp --------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "condition_variable" +#include "thread" +#include "system_error" +#include "cassert" + +_LIBCPP_BEGIN_NAMESPACE_STD + +condition_variable::~condition_variable() +{ + int e = pthread_cond_destroy(&__cv_); +// assert(e == 0); +} + +void +condition_variable::notify_one() +{ + pthread_cond_signal(&__cv_); +} + +void +condition_variable::notify_all() +{ + pthread_cond_broadcast(&__cv_); +} + +void +condition_variable::wait(unique_lock<mutex>& lk) +{ + if (!lk.owns_lock()) + __throw_system_error(EPERM, + "condition_variable::wait: mutex not locked"); + int ec = pthread_cond_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) +{ + using namespace chrono; + if (!lk.owns_lock()) + __throw_system_error(EPERM, + "condition_variable::timed wait: mutex not locked"); + nanoseconds d = tp.time_since_epoch(); + timespec ts; + seconds s = duration_cast<seconds>(d); + ts.tv_sec = static_cast<decltype(ts.tv_sec)>(s.count()); + ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).count()); + int ec = pthread_cond_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); + if (ec != 0 && ec != ETIMEDOUT) + __throw_system_error(ec, "condition_variable timed_wait failed"); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/hash.cpp b/libcxx/src/hash.cpp new file mode 100644 index 00000000000..a6bd311ef28 --- /dev/null +++ b/libcxx/src/hash.cpp @@ -0,0 +1,485 @@ +//===-------------------------- hash.cpp ----------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "__hash_table" +#include "algorithm" + +_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. Candiate 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. + +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 + // 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 = std::lower_bound(indices, indices + M, n % 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) + { + if (n % small_primes[j] == 0) + goto next; + if (n / small_primes[j] < small_primes[j]) + return n; + } + // n wasn't divisible by small primes, try potential primes + { + size_t i = 211; + while (true) + { + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 10; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 8; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 8; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 6; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 4; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 2; + if (n % i == 0) + break; + if (n / i < i) + return n; + + i += 10; + if (n % i == 0) + break; + if (n / i < i) + return n; + + // This will loop i to the next "plane" of potential primes + i += 2; + } + } +next: + // n is not prime. Increment n to next potential prime. + if (++in == M) + { + ++k0; + in = 0; + } + n = L * k0 + indices[in]; + } +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/ios.cpp b/libcxx/src/ios.cpp new file mode 100644 index 00000000000..7d2489dc4b7 --- /dev/null +++ b/libcxx/src/ios.cpp @@ -0,0 +1,492 @@ +//===-------------------------- ios.cpp -----------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ios" +#include "streambuf" +#include "istream" +#include "string" +#include "__locale" +#include "algorithm" +#include "memory" +#include "new" +#include "limits" +#include <stdlib.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +template class __basic_string_common<true>; + +template class basic_string<char>; +template class basic_string<wchar_t>; + +template enable_if<__is_forward_iterator<char const*>::value, void>::type + basic_string<char, char_traits<char>, allocator<char> > + ::__init<char const*>(char const*, char const*); + +template enable_if<__is_forward_iterator<wchar_t const*>::value, void>::type + basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > + ::__init<wchar_t const*>(wchar_t const*, wchar_t const*); + +template + enable_if<__is_forward_iterator<char*>::value, + basic_string<char, char_traits<char>, allocator<char> >&>::type + basic_string<char, char_traits<char>, allocator<char> >:: + append<char*>(char*, char*); + +template + enable_if<__is_forward_iterator<wchar_t*>::value, + basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >&>::type + basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >:: + append<wchar_t*>(wchar_t*, wchar_t*); + +template + enable_if<__is_forward_iterator<char const*>::value, + string::iterator>::type + string:: + insert<char const*>(string::const_iterator, char const*, char const*); + +template + enable_if<__is_forward_iterator<wchar_t const*>::value, + wstring::iterator>::type + wstring:: + insert<wchar_t const*>(wstring::const_iterator, wchar_t const*, wchar_t const*); + +template + enable_if<__is_input_iterator<char const*>::value, string&>::type + string:: + replace<char const*>(string::iterator, string::iterator, char const*, char const*); + +template + enable_if<__is_input_iterator<wchar_t const*>::value, wstring&>::type + wstring:: + replace<wchar_t const*>(wstring::iterator, wstring::iterator, wchar_t const*, wchar_t const*); + +template + enable_if<__is_forward_iterator<wchar_t*>::value, wstring&>::type + wstring::assign<wchar_t*>(wchar_t*, wchar_t*); + +template + string + operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); + +template class basic_ios<char>; +template class basic_ios<wchar_t>; + +template class basic_streambuf<char>; +template class basic_streambuf<wchar_t>; + +template class basic_istream<char>; +template class basic_istream<wchar_t>; + +template class basic_ostream<char>; +template class basic_ostream<wchar_t>; + +template class basic_iostream<char>; + +class _LIBCPP_HIDDEN __iostream_category + : public __do_message +{ +public: + virtual const char* name() const; + virtual string message(int ev) const; +}; + +const char* +__iostream_category::name() const +{ + return "iostream"; +} + +string +__iostream_category::message(int ev) const +{ + if (ev != static_cast<int>(io_errc::stream) && ev <= ELAST) + return __do_message::message(ev); + return string("unspecified iostream_category error"); +} + +const error_category& +iostream_category() +{ + 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 = *(locale*)&__loc_; + locale oldloc = loc_storage; + loc_storage = newloc; + __call_callbacks(imbue_event); + return oldloc; +} + +locale +ios_base::getloc() const +{ + const locale& loc_storage = *(locale*)&__loc_; + return loc_storage; +} + +// xalloc + +int ios_base::__xindex_ = 0; + +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; + const size_t mx = std::numeric_limits<size_t>::max(); + if (req_size < mx/2) + newcap = max(2 * __iarray_cap_, req_size); + else + newcap = mx; + long* iarray = (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_; __iarray_cap_ < newcap; ++__iarray_cap_, ++p) + *p = 0; + } + __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; + const size_t mx = std::numeric_limits<size_t>::max(); + if (req_size < mx/2) + newcap = max(2 * __parray_cap_, req_size); + else + newcap = mx; + void** parray = (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_; __parray_cap_ < newcap; ++__parray_cap_, ++p) + *p = 0; + } + __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; + const size_t mx = std::numeric_limits<size_t>::max(); + if (req_size < mx/2) + newcap = max(2 * __event_cap_, req_size); + else + newcap = mx; + event_callback* fns = (event_callback*)realloc(__fn_, newcap * sizeof(event_callback)); + if (fns == 0) + setstate(badbit); + __fn_ = fns; + int* indxs = (int*)realloc(__index_, newcap * sizeof(int)); + if (indxs == 0) + setstate(badbit); + __index_ = indxs; + } + __fn_[__event_size_] = fn; + __index_[__event_size_] = index; + ++__event_size_; +} + +ios_base::~ios_base() +{ + __call_callbacks(erase_event); + locale& loc_storage = *(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 aquired + 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_) + { + new_callbacks.reset((event_callback*)malloc(sizeof(event_callback) * rhs.__event_size_)); + if (!new_callbacks) + throw bad_alloc(); + new_ints.reset((int*)malloc(sizeof(int) * rhs.__event_size_)); + if (!new_ints) + throw bad_alloc(); + } + if (__iarray_cap_ < rhs.__iarray_size_) + { + new_longs.reset((long*)malloc(sizeof(long) * rhs.__iarray_size_)); + if (!new_longs) + throw bad_alloc(); + } + if (__parray_cap_ < rhs.__parray_size_) + { + new_pointers.reset((void**)malloc(sizeof(void*) * rhs.__parray_size_)); + 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 = *(locale*)&__loc_; + locale& rhs_loc = *(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 = *(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) +{ + _STD::swap(__fmtflags_, rhs.__fmtflags_); + _STD::swap(__precision_, rhs.__precision_); + _STD::swap(__width_, rhs.__width_); + _STD::swap(__rdstate_, rhs.__rdstate_); + _STD::swap(__exceptions_, rhs.__exceptions_); + locale& lhs_loc = *(locale*)&__loc_; + locale& rhs_loc = *(locale*)&rhs.__loc_; + _STD::swap(lhs_loc, rhs_loc); + _STD::swap(__fn_, rhs.__fn_); + _STD::swap(__index_, rhs.__index_); + _STD::swap(__event_size_, rhs.__event_size_); + _STD::swap(__event_cap_, rhs.__event_cap_); + _STD::swap(__iarray_, rhs.__iarray_); + _STD::swap(__iarray_size_, rhs.__iarray_size_); + _STD::swap(__iarray_cap_, rhs.__iarray_cap_); + _STD::swap(__parray_, rhs.__parray_); + _STD::swap(__parray_size_, rhs.__parray_size_); + _STD::swap(__parray_cap_, rhs.__parray_cap_); +} + +void +ios_base::__set_badbit_and_consider_rethrow() +{ + __rdstate_ |= badbit; + if (__exceptions_ & badbit) + throw; +} + +void +ios_base::__set_failbit_and_consider_rethrow() +{ + __rdstate_ |= failbit; + if (__exceptions_ & failbit) + throw; +} + +bool +ios_base::sync_with_stdio(bool sync) +{ + static bool previous_state = true; + bool r = previous_state; + previous_state = sync; + return r; +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/iostream.cpp b/libcxx/src/iostream.cpp new file mode 100644 index 00000000000..43be5877121 --- /dev/null +++ b/libcxx/src/iostream.cpp @@ -0,0 +1,53 @@ +//===------------------------ iostream.cpp --------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "__std_stream" +#include "string" + +_LIBCPP_BEGIN_NAMESPACE_STD + +static __stdinbuf<char> __cin(stdin); +static __stdoutbuf<char> __cout(stdout); +static __stdoutbuf<char> __cerr(stderr); +static __stdinbuf<wchar_t> __wcin(stdin); +static __stdoutbuf<wchar_t> __wcout(stdout); +static __stdoutbuf<wchar_t> __wcerr(stderr); + +istream cin(&__cin); +ostream cout(&__cout); +ostream cerr(&__cerr); +ostream clog(&__cerr); +wistream wcin(&__wcin); +wostream wcout(&__wcout); +wostream wcerr(&__wcerr); +wostream wclog(&__wcerr); + +ios_base::Init __start_std_streams; + +ios_base::Init::Init() +{ + cin.tie(&cout); + _STD::unitbuf(cerr); + cerr.tie(&cout); + + wcin.tie(&wcout); + _STD::unitbuf(wcerr); + wcerr.tie(&wcout); +} + +ios_base::Init::~Init() +{ + cout.flush(); + clog.flush(); + + wcout.flush(); + wclog.flush(); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp new file mode 100644 index 00000000000..758ec142d37 --- /dev/null +++ b/libcxx/src/locale.cpp @@ -0,0 +1,3680 @@ +//===------------------------- locale.cpp ---------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "string" +#include "locale" +#include "vector" +#include "algorithm" +#include "algorithm" +#include "typeinfo" +#include "clocale" +#include "cstring" +#include "cwctype" +#include "__sso_allocator" +#include <libkern/OSAtomic.h> +#include <langinfo.h> +#include <stdlib.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace { + +struct release +{ + void operator()(locale::facet* p) {p->__release_shared();} +}; + +template <class T, class A0> +inline +T& +make(A0 a0) +{ + static typename aligned_storage<sizeof(T)>::type buf; + ::new (&buf) T(a0); + return *(T*)&buf; +} + +template <class T, class A0, class A1> +inline +T& +make(A0 a0, A1 a1) +{ + static typename aligned_storage<sizeof(T)>::type buf; + ::new (&buf) T(a0, a1); + return *(T*)&buf; +} + +template <class T, class A0, class A1, class A2> +inline +T& +make(A0 a0, A1 a1, A2 a2) +{ + static typename aligned_storage<sizeof(T)>::type buf; + ::new (&buf) T(a0, a1, a2); + return *(T*)&buf; +} + +} + +class _LIBCPP_HIDDEN locale::__imp + : public facet +{ + enum {N = 28}; + string name_; + vector<facet*, __sso_allocator<facet*, N> > facets_; +public: + explicit __imp(size_t refs = 0); + explicit __imp(const string& name, size_t refs = 0); + __imp(const __imp&); + __imp(const __imp&, const string&, locale::category c); + __imp(const __imp& other, const __imp& one, locale::category c); + __imp(const __imp&, facet* f, long id); + ~__imp(); + + const string& name() const {return name_;} + bool has_facet(long id) const {return id < facets_.size() && facets_[id];} + const locale::facet* use_facet(long id) const; + + static const locale& make_classic(); + static locale& make_global(); +private: + void install(facet* f, long id); + template <class F> void install(F* f) {install(f, f->id.__get());} + template <class F> void install_from(const __imp& other); +}; + +locale::__imp::__imp(size_t refs) + : facet(refs), + name_("C"), + facets_(N) +{ + facets_.clear(); + install(&make<_STD::collate<char> >(1)); + install(&make<_STD::collate<wchar_t> >(1)); + install(&make<_STD::ctype<char> >((ctype_base::mask*)0, false, 1)); + install(&make<_STD::ctype<wchar_t> >(1)); + install(&make<codecvt<char, char, mbstate_t> >(1)); + install(&make<codecvt<wchar_t, char, mbstate_t> >(1)); + install(&make<codecvt<char16_t, char, mbstate_t> >(1)); + install(&make<codecvt<char32_t, char, mbstate_t> >(1)); + install(&make<numpunct<char> >(1)); + install(&make<numpunct<wchar_t> >(1)); + install(&make<num_get<char> >(1)); + install(&make<num_get<wchar_t> >(1)); + install(&make<num_put<char> >(1)); + install(&make<num_put<wchar_t> >(1)); + install(&make<moneypunct<char, false> >(1)); + install(&make<moneypunct<char, true> >(1)); + install(&make<moneypunct<wchar_t, false> >(1)); + install(&make<moneypunct<wchar_t, true> >(1)); + install(&make<money_get<char> >(1)); + install(&make<money_get<wchar_t> >(1)); + install(&make<money_put<char> >(1)); + install(&make<money_put<wchar_t> >(1)); + install(&make<time_get<char> >(1)); + install(&make<time_get<wchar_t> >(1)); + install(&make<time_put<char> >(1)); + install(&make<time_put<wchar_t> >(1)); + install(&make<_STD::messages<char> >(1)); + install(&make<_STD::messages<wchar_t> >(1)); +} + +locale::__imp::__imp(const string& name, size_t refs) + : facet(refs), + name_(name), + facets_(N) +{ + try + { + facets_ = locale::classic().__locale_->facets_; + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__add_shared(); + install(new collate_byname<char>(name_)); + install(new collate_byname<wchar_t>(name_)); + install(new ctype_byname<char>(name_)); + install(new ctype_byname<wchar_t>(name_)); + install(new codecvt_byname<char, char, mbstate_t>(name_)); + install(new codecvt_byname<wchar_t, char, mbstate_t>(name_)); + install(new codecvt_byname<char16_t, char, mbstate_t>(name_)); + install(new codecvt_byname<char32_t, char, mbstate_t>(name_)); + install(new numpunct_byname<char>(name_)); + install(new numpunct_byname<wchar_t>(name_)); + install(new moneypunct_byname<char, false>(name_)); + install(new moneypunct_byname<char, true>(name_)); + install(new moneypunct_byname<wchar_t, false>(name_)); + install(new moneypunct_byname<wchar_t, true>(name_)); + install(new time_get_byname<char>(name_)); + install(new time_get_byname<wchar_t>(name_)); + install(new time_put_byname<char>(name_)); + install(new time_put_byname<wchar_t>(name_)); + install(new messages_byname<char>(name_)); + install(new messages_byname<wchar_t>(name_)); + } + catch (...) + { + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__release_shared(); + throw; + } +} + +locale::__imp::__imp(const __imp& other) + : name_(other.name_), + facets_(max<size_t>(N, other.facets_.size())) +{ + facets_ = other.facets_; + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__add_shared(); +} + +locale::__imp::__imp(const __imp& other, const string& name, locale::category c) + : name_("*"), + facets_(N) +{ + facets_ = other.facets_; + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__add_shared(); + try + { + if (c & locale::collate) + { + install(new collate_byname<char>(name)); + install(new collate_byname<wchar_t>(name)); + } + if (c & locale::ctype) + { + install(new ctype_byname<char>(name)); + install(new ctype_byname<wchar_t>(name)); + install(new codecvt_byname<char, char, mbstate_t>(name)); + install(new codecvt_byname<wchar_t, char, mbstate_t>(name)); + install(new codecvt_byname<char16_t, char, mbstate_t>(name)); + install(new codecvt_byname<char32_t, char, mbstate_t>(name)); + } + if (c & locale::monetary) + { + install(new moneypunct_byname<char, false>(name)); + install(new moneypunct_byname<char, true>(name)); + install(new moneypunct_byname<wchar_t, false>(name)); + install(new moneypunct_byname<wchar_t, true>(name)); + } + if (c & locale::numeric) + { + install(new numpunct_byname<char>(name)); + install(new numpunct_byname<wchar_t>(name)); + } + if (c & locale::time) + { + install(new time_get_byname<char>(name)); + install(new time_get_byname<wchar_t>(name)); + install(new time_put_byname<char>(name)); + install(new time_put_byname<wchar_t>(name)); + } + if (c & locale::messages) + { + install(new messages_byname<char>(name)); + install(new messages_byname<wchar_t>(name)); + } + } + catch (...) + { + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__release_shared(); + throw; + } +} + +template<class F> +inline +void +locale::__imp::install_from(const locale::__imp& one) +{ + long id = F::id.__get(); + install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id); +} + +locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c) + : name_("*"), + facets_(N) +{ + facets_ = other.facets_; + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__add_shared(); + try + { + if (c & locale::collate) + { + install_from<_STD::collate<char> >(one); + install_from<_STD::collate<wchar_t> >(one); + } + if (c & locale::ctype) + { + install_from<_STD::ctype<char> >(one); + install_from<_STD::ctype<wchar_t> >(one); + install_from<_STD::codecvt<char, char, mbstate_t> >(one); + install_from<_STD::codecvt<char16_t, char, mbstate_t> >(one); + install_from<_STD::codecvt<char32_t, char, mbstate_t> >(one); + install_from<_STD::codecvt<wchar_t, char, mbstate_t> >(one); + } + if (c & locale::monetary) + { + install_from<moneypunct<char, false> >(one); + install_from<moneypunct<char, true> >(one); + install_from<moneypunct<wchar_t, false> >(one); + install_from<moneypunct<wchar_t, true> >(one); + install_from<money_get<char> >(one); + install_from<money_get<wchar_t> >(one); + install_from<money_put<char> >(one); + install_from<money_put<wchar_t> >(one); + } + if (c & locale::numeric) + { + install_from<numpunct<char> >(one); + install_from<numpunct<wchar_t> >(one); + install_from<num_get<char> >(one); + install_from<num_get<wchar_t> >(one); + install_from<num_put<char> >(one); + install_from<num_put<wchar_t> >(one); + } + if (c & locale::time) + { + install_from<time_get<char> >(one); + install_from<time_get<wchar_t> >(one); + install_from<time_put<char> >(one); + install_from<time_put<wchar_t> >(one); + } + if (c & locale::messages) + { + install_from<_STD::messages<char> >(one); + install_from<_STD::messages<wchar_t> >(one); + } + } + catch (...) + { + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__release_shared(); + throw; + } +} + +locale::__imp::__imp(const __imp& other, facet* f, long id) + : name_("*"), + facets_(max<size_t>(N, other.facets_.size()+1)) +{ + f->__add_shared(); + unique_ptr<facet, release> hold(f); + facets_ = other.facets_; + for (unsigned i = 0; i < other.facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__add_shared(); + install(hold.get(), id); +} + +locale::__imp::~__imp() +{ + for (unsigned i = 0; i < facets_.size(); ++i) + if (facets_[i]) + facets_[i]->__release_shared(); +} + +void +locale::__imp::install(facet* f, long id) +{ + f->__add_shared(); + unique_ptr<facet, release> hold(f); + if (id >= facets_.size()) + facets_.resize(id+1); + if (facets_[id]) + facets_[id]->__release_shared(); + facets_[id] = hold.release(); +} + +const locale::facet* +locale::__imp::use_facet(long id) const +{ + if (!has_facet(id)) + throw bad_cast(); + return facets_[id]; +} + +// locale + +const locale& +locale::__imp::make_classic() +{ + // only one thread can get in here and it only gets in once + static aligned_storage<sizeof(locale)>::type buf; + locale* c = (locale*)&buf; + c->__locale_ = &make<__imp>(1); + return *c; +} + +const locale& +locale::classic() +{ + static const locale& c = __imp::make_classic(); + return c; +} + +locale& +locale::__imp::make_global() +{ + // only one thread can get in here and it only gets in once + static aligned_storage<sizeof(locale)>::type buf; + locale* g = (locale*)&buf; + ::new (&buf) locale(locale::classic()); + return *(locale*)&buf; +} + +locale& +locale::__global() +{ + static locale& g = __imp::make_global(); + return g; +} + +locale::locale() throw() + : __locale_(__global().__locale_) +{ + __locale_->__add_shared(); +} + +locale::locale(const locale& l) throw() + : __locale_(l.__locale_) +{ + __locale_->__add_shared(); +} + +locale::~locale() throw() +{ + __locale_->__release_shared(); +} + +const locale& +locale::operator=(const locale& other) throw() +{ + other.__locale_->__add_shared(); + __locale_->__release_shared(); + __locale_ = other.__locale_; + return *this; +} + +locale::locale(const char* name) + : __locale_(name ? new __imp(name) + : throw runtime_error("locale constructed with null")) +{ + __locale_->__add_shared(); +} + +locale::locale(const string& name) + : __locale_(new __imp(name)) +{ + __locale_->__add_shared(); +} + +locale::locale(const locale& other, const char* name, category c) + : __locale_(name ? new __imp(*other.__locale_, name, c) + : throw runtime_error("locale constructed with null")) +{ + __locale_->__add_shared(); +} + +locale::locale(const locale& other, const string& name, category c) + : __locale_(new __imp(*other.__locale_, name, c)) +{ + __locale_->__add_shared(); +} + +locale::locale(const locale& other, const locale& one, category c) + : __locale_(new __imp(*other.__locale_, *one.__locale_, c)) +{ + __locale_->__add_shared(); +} + +string +locale::name() const +{ + return __locale_->name(); +} + +void +locale::__install_ctor(const locale& other, facet* f, long id) +{ + if (f) + __locale_ = new __imp(*other.__locale_, f, id); + else + __locale_ = other.__locale_; + __locale_->__add_shared(); +} + +locale +locale::global(const locale& loc) +{ + locale& g = __global(); + locale r = g; + g = loc; + if (g.name() != "*") + setlocale(LC_ALL, g.name().c_str()); + return r; +} + +bool +locale::has_facet(id& x) const +{ + return __locale_->has_facet(x.__get()); +} + +const locale::facet* +locale::use_facet(id& x) const +{ + return __locale_->use_facet(x.__get()); +} + +bool +locale::operator==(const locale& y) const +{ + return (__locale_ == y.__locale_) + || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name()); +} + +// locale::facet + +locale::facet::~facet() +{ +} + +void +locale::facet::__on_zero_shared() +{ + delete this; +} + +// locale::id + +int32_t locale::id::__next_id = 0; + +namespace +{ + +class __fake_bind +{ + locale::id* id_; + void (locale::id::* pmf_)(); +public: + __fake_bind(void (locale::id::* pmf)(), locale::id* id) + : id_(id), pmf_(pmf) {} + + void operator()() const + { + (id_->*pmf_)(); + } +}; + +} + +long +locale::id::__get() +{ + call_once(__flag_, __fake_bind(&locale::id::__init, this)); + return __id_ - 1; +} + +void +locale::id::__init() +{ + __id_ = OSAtomicIncrement32Barrier(&__next_id); +} + +// template <> class collate_byname<char> + +collate_byname<char>::collate_byname(const char* n, size_t refs) + : collate<char>(refs), + __l(newlocale(LC_ALL_MASK, n, 0)) +{ + if (__l == 0) + throw runtime_error("collate_byname<char>::collate_byname" + " failed to construct for " + string(n)); +} + +collate_byname<char>::collate_byname(const string& name, size_t refs) + : collate<char>(refs), + __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) +{ + if (__l == 0) + throw runtime_error("collate_byname<char>::collate_byname" + " failed to construct for " + name); +} + +collate_byname<char>::~collate_byname() +{ + freelocale(__l); +} + +int +collate_byname<char>::do_compare(const char_type* __lo1, const char_type* __hi1, + const char_type* __lo2, const char_type* __hi2) const +{ + string_type lhs(__lo1, __hi1); + string_type rhs(__lo2, __hi2); + int r = strcoll_l(lhs.c_str(), rhs.c_str(), __l); + if (r < 0) + return -1; + if (r > 0) + return 1; + return r; +} + +collate_byname<char>::string_type +collate_byname<char>::do_transform(const char_type* lo, const char_type* hi) const +{ + const string_type in(lo, hi); + string_type out(strxfrm_l(0, in.c_str(), 0, __l), char()); + strxfrm_l(const_cast<char*>(out.c_str()), in.c_str(), out.size()+1, __l); + return out; +} + +// template <> class collate_byname<wchar_t> + +collate_byname<wchar_t>::collate_byname(const char* n, size_t refs) + : collate<wchar_t>(refs), + __l(newlocale(LC_ALL_MASK, n, 0)) +{ + if (__l == 0) + throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" + " failed to construct for " + string(n)); +} + +collate_byname<wchar_t>::collate_byname(const string& name, size_t refs) + : collate<wchar_t>(refs), + __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) +{ + if (__l == 0) + throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" + " failed to construct for " + name); +} + +collate_byname<wchar_t>::~collate_byname() +{ + freelocale(__l); +} + +int +collate_byname<wchar_t>::do_compare(const char_type* __lo1, const char_type* __hi1, + const char_type* __lo2, const char_type* __hi2) const +{ + string_type lhs(__lo1, __hi1); + string_type rhs(__lo2, __hi2); + int r = wcscoll_l(lhs.c_str(), rhs.c_str(), __l); + if (r < 0) + return -1; + if (r > 0) + return 1; + return r; +} + +collate_byname<wchar_t>::string_type +collate_byname<wchar_t>::do_transform(const char_type* lo, const char_type* hi) const +{ + const string_type in(lo, hi); + string_type out(wcsxfrm_l(0, in.c_str(), 0, __l), wchar_t()); + wcsxfrm_l(const_cast<wchar_t*>(out.c_str()), in.c_str(), out.size()+1, __l); + return out; +} + +// template <> class ctype<wchar_t>; + +locale::id ctype<wchar_t>::id; + +ctype<wchar_t>::~ctype() +{ +} + +bool +ctype<wchar_t>::do_is(mask m, char_type c) const +{ + return isascii(c) ? _DefaultRuneLocale.__runetype[c] & m : false; +} + +const wchar_t* +ctype<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const +{ + for (; low != high; ++low, ++vec) + *vec = static_cast<mask>(isascii(*low) ? _DefaultRuneLocale.__runetype[*low] : 0); + return low; +} + +const wchar_t* +ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + if (isascii(*low) && (_DefaultRuneLocale.__runetype[*low] & m)) + break; + return low; +} + +const wchar_t* +ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + if (!(isascii(*low) && (_DefaultRuneLocale.__runetype[*low] & m))) + break; + return low; +} + +wchar_t +ctype<wchar_t>::do_toupper(char_type c) const +{ + return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c; +} + +const wchar_t* +ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low; + return low; +} + +wchar_t +ctype<wchar_t>::do_tolower(char_type c) const +{ + return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c; +} + +const wchar_t* +ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low; + return low; +} + +wchar_t +ctype<wchar_t>::do_widen(char c) const +{ + return c; +} + +const char* +ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const +{ + for (; low != high; ++low, ++dest) + *dest = *low; + return low; +} + +char +ctype<wchar_t>::do_narrow(char_type c, char dfault) const +{ + if (isascii(c)) + return static_cast<char>(c); + return dfault; +} + +const wchar_t* +ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const +{ + for (; low != high; ++low, ++dest) + if (isascii(*low)) + *dest = *low; + else + *dest = dfault; + return low; +} + +// template <> class ctype<char>; + +locale::id ctype<char>::id; + +ctype<char>::ctype(const mask* tab, bool del, size_t refs) + : locale::facet(refs), + __tab_(tab), + __del_(del) +{ + if (__tab_ == 0) + __tab_ = _DefaultRuneLocale.__runetype; +} + +ctype<char>::~ctype() +{ + if (__tab_ && __del_) + delete [] __tab_; +} + +char +ctype<char>::do_toupper(char_type c) const +{ + return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c; +} + +const char* +ctype<char>::do_toupper(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low; + return low; +} + +char +ctype<char>::do_tolower(char_type c) const +{ + return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c; +} + +const char* +ctype<char>::do_tolower(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low; + return low; +} + +char +ctype<char>::do_widen(char c) const +{ + return c; +} + +const char* +ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const +{ + for (; low != high; ++low, ++dest) + *dest = *low; + return low; +} + +char +ctype<char>::do_narrow(char_type c, char dfault) const +{ + if (isascii(c)) + return static_cast<char>(c); + return dfault; +} + +const char* +ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const +{ + for (; low != high; ++low, ++dest) + if (isascii(*low)) + *dest = *low; + else + *dest = dfault; + return low; +} + +const ctype<char>::mask* +ctype<char>::classic_table() throw() +{ + return _DefaultRuneLocale.__runetype; +} + +// template <> class ctype_byname<char> + +ctype_byname<char>::ctype_byname(const char* name, size_t refs) + : ctype<char>(0, false, refs), + __l(newlocale(LC_ALL_MASK, name, 0)) +{ + if (__l == 0) + throw runtime_error("ctype_byname<char>::ctype_byname" + " failed to construct for " + string(name)); +} + +ctype_byname<char>::ctype_byname(const string& name, size_t refs) + : ctype<char>(0, false, refs), + __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) +{ + if (__l == 0) + throw runtime_error("ctype_byname<char>::ctype_byname" + " failed to construct for " + name); +} + +ctype_byname<char>::~ctype_byname() +{ + freelocale(__l); +} + +char +ctype_byname<char>::do_toupper(char_type c) const +{ + return toupper_l(c, __l); +} + +const char* +ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = toupper_l(*low, __l); + return low; +} + +char +ctype_byname<char>::do_tolower(char_type c) const +{ + return tolower_l(c, __l); +} + +const char* +ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = tolower_l(*low, __l); + return low; +} + +// template <> class ctype_byname<wchar_t> + +ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs) + : ctype<wchar_t>(refs), + __l(newlocale(LC_ALL_MASK, name, 0)) +{ + if (__l == 0) + throw runtime_error("ctype_byname<wchar_t>::ctype_byname" + " failed to construct for " + string(name)); +} + +ctype_byname<wchar_t>::ctype_byname(const string& name, size_t refs) + : ctype<wchar_t>(refs), + __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) +{ + if (__l == 0) + throw runtime_error("ctype_byname<wchar_t>::ctype_byname" + " failed to construct for " + name); +} + +ctype_byname<wchar_t>::~ctype_byname() +{ + freelocale(__l); +} + +bool +ctype_byname<wchar_t>::do_is(mask m, char_type c) const +{ + return static_cast<bool>(iswctype_l(c, m, __l)); +} + +const wchar_t* +ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const +{ + for (; low != high; ++low, ++vec) + { + if (isascii(*low)) + *vec = static_cast<mask>(_DefaultRuneLocale.__runetype[*low]); + else + { + *vec = 0; + if (iswspace_l(*low, __l)) + *vec |= space; + if (iswprint_l(*low, __l)) + *vec |= print; + if (iswcntrl_l(*low, __l)) + *vec |= cntrl; + if (iswupper_l(*low, __l)) + *vec |= upper; + if (iswlower_l(*low, __l)) + *vec |= lower; + if (iswalpha_l(*low, __l)) + *vec |= alpha; + if (iswdigit_l(*low, __l)) + *vec |= digit; + if (iswpunct_l(*low, __l)) + *vec |= punct; + if (iswxdigit_l(*low, __l)) + *vec |= xdigit; + } + } + return low; +} + +const wchar_t* +ctype_byname<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + if (iswctype_l(*low, m, __l)) + break; + return low; +} + +const wchar_t* +ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + if (!iswctype_l(*low, m, __l)) + break; + return low; +} + +wchar_t +ctype_byname<wchar_t>::do_toupper(char_type c) const +{ + return towupper_l(c, __l); +} + +const wchar_t* +ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = towupper_l(*low, __l); + return low; +} + +wchar_t +ctype_byname<wchar_t>::do_tolower(char_type c) const +{ + return towlower_l(c, __l); +} + +const wchar_t* +ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const +{ + for (; low != high; ++low) + *low = towlower_l(*low, __l); + return low; +} + +wchar_t +ctype_byname<wchar_t>::do_widen(char c) const +{ + return btowc_l(c, __l); +} + +const char* +ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const +{ + for (; low != high; ++low, ++dest) + *dest = btowc_l(*low, __l); + return low; +} + +char +ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const +{ + int r = wctob_l(c, __l); + return r != WEOF ? static_cast<char>(r) : dfault; +} + +const wchar_t* +ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const +{ + for (; low != high; ++low, ++dest) + { + int r = wctob_l(*low, __l); + *dest = r != WEOF ? static_cast<char>(r) : dfault; + } + return low; +} + +// template <> class codecvt<char, char, mbstate_t> + +locale::id codecvt<char, char, mbstate_t>::id; + +codecvt<char, char, mbstate_t>::~codecvt() +{ +} + +codecvt<char, char, mbstate_t>::result +codecvt<char, char, mbstate_t>::do_out(state_type&, + const intern_type* frm, const intern_type*, const intern_type*& frm_nxt, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + frm_nxt = frm; + to_nxt = to; + return noconv; +} + +codecvt<char, char, mbstate_t>::result +codecvt<char, char, mbstate_t>::do_in(state_type&, + const extern_type* frm, const extern_type*, const extern_type*& frm_nxt, + intern_type* to, intern_type*, intern_type*& to_nxt) const +{ + frm_nxt = frm; + to_nxt = to; + return noconv; +} + +codecvt<char, char, mbstate_t>::result +codecvt<char, char, mbstate_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +codecvt<char, char, mbstate_t>::do_encoding() const throw() +{ + return 1; +} + +bool +codecvt<char, char, mbstate_t>::do_always_noconv() const throw() +{ + return true; +} + +int +codecvt<char, char, mbstate_t>::do_length(state_type&, + const extern_type* frm, const extern_type* end, size_t mx) const +{ + return static_cast<int>(min<size_t>(mx, end-frm)); +} + +int +codecvt<char, char, mbstate_t>::do_max_length() const throw() +{ + return 1; +} + +// template <> class codecvt<wchar_t, char, mbstate_t> + +locale::id codecvt<wchar_t, char, mbstate_t>::id; + +codecvt<wchar_t, char, mbstate_t>::codecvt(size_t refs) + : locale::facet(refs), + __l(0) +{ +} + +codecvt<wchar_t, char, mbstate_t>::codecvt(const char* nm, size_t refs) + : locale::facet(refs), + __l(newlocale(LC_ALL_MASK, nm, 0)) +{ + if (__l == 0) + throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname" + " failed to construct for " + string(nm)); +} + +codecvt<wchar_t, char, mbstate_t>::~codecvt() +{ + if (__l != 0) + freelocale(__l); +} + +codecvt<wchar_t, char, mbstate_t>::result +codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + // look for first internal null in frm + const intern_type* fend = frm; + for (; fend != frm_end; ++fend) + if (*fend == 0) + break; + // loop over all null-terminated sequences in frm + to_nxt = to; + for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) + { + // save state in case needed to reover to_nxt on error + mbstate_t save_state = st; + size_t n = wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l); + if (n == size_t(-1)) + { + // need to recover to_nxt + for (to_nxt = to; frm != frm_nxt; ++frm) + { + n = wcrtomb_l(to_nxt, *frm, &save_state, __l); + if (n == size_t(-1)) + break; + to_nxt += n; + } + frm_nxt = frm; + return error; + } + if (n == 0) + return partial; + to_nxt += n; + if (to_nxt == to_end) + break; + if (fend != frm_end) // set up next null terminated sequence + { + // Try to write the terminating null + extern_type tmp[MB_LEN_MAX]; + n = wcrtomb_l(tmp, intern_type(), &st, __l); + if (n == size_t(-1)) // on error + return error; + if (n > to_end-to_nxt) // is there room? + return partial; + for (extern_type* p = tmp; n; --n) // write it + *to_nxt++ = *p++; + ++frm_nxt; + // look for next null in frm + for (fend = frm_nxt; fend != frm_end; ++fend) + if (*fend == 0) + break; + } + } + return frm_nxt == frm_end ? ok : partial; +} + +codecvt<wchar_t, char, mbstate_t>::result +codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + // look for first internal null in frm + const extern_type* fend = frm; + for (; fend != frm_end; ++fend) + if (*fend == 0) + break; + // loop over all null-terminated sequences in frm + to_nxt = to; + for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) + { + // save state in case needed to reover to_nxt on error + mbstate_t save_state = st; + size_t n = mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l); + if (n == size_t(-1)) + { + // need to recover to_nxt + for (to_nxt = to; frm != frm_nxt; ++to_nxt) + { + n = mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l); + switch (n) + { + case 0: + ++frm; + break; + case -1: + frm_nxt = frm; + return error; + case -2: + frm_nxt = frm; + return partial; + default: + frm += n; + break; + } + } + frm_nxt = frm; + return frm_nxt == frm_end ? ok : partial; + } + if (n == 0) + return error; + to_nxt += n; + if (to_nxt == to_end) + break; + if (fend != frm_end) // set up next null terminated sequence + { + // Try to write the terminating null + n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l); + if (n != 0) // on error + return error; + ++to_nxt; + ++frm_nxt; + // look for next null in frm + for (fend = frm_nxt; fend != frm_end; ++fend) + if (*fend == 0) + break; + } + } + return frm_nxt == frm_end ? ok : partial; +} + +codecvt<wchar_t, char, mbstate_t>::result +codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + to_nxt = to; + extern_type tmp[MB_LEN_MAX]; + size_t n = wcrtomb_l(tmp, intern_type(), &st, __l); + if (n == size_t(-1) || n == 0) // on error + return error; + --n; + if (n > to_end-to_nxt) // is there room? + return partial; + for (extern_type* p = tmp; n; --n) // write it + *to_nxt++ = *p++; + return ok; +} + +int +codecvt<wchar_t, char, mbstate_t>::do_encoding() const throw() +{ + if (mbtowc_l(0, 0, MB_LEN_MAX, __l) == 0) + { + // stateless encoding + if (__l == 0 || MB_CUR_MAX_L(__l) == 1) // there are no known constant length encodings + return 1; // which take more than 1 char to form a wchar_t + return 0; + } + return -1; +} + +bool +codecvt<wchar_t, char, mbstate_t>::do_always_noconv() const throw() +{ + return false; +} + +int +codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + int nbytes = 0; + for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t) + { + size_t n = mbrlen_l(frm, frm_end-frm, &st, __l); + switch (n) + { + case 0: + ++nbytes; + ++frm; + break; + case -1: + case -2: + return nbytes; + default: + nbytes += n; + frm += n; + break; + } + } + return nbytes; +} + +int +codecvt<wchar_t, char, mbstate_t>::do_max_length() const throw() +{ + return __l == 0 ? 1 : MB_CUR_MAX_L(__l); +} + +// Valid UTF ranges +// UTF-32 UTF-16 UTF-8 # of code points +// first second first second third fourth +// 000000 - 00007F 0000 - 007F 00 - 7F 127 +// 000080 - 0007FF 0080 - 07FF C2 - DF, 80 - BF 1920 +// 000800 - 000FFF 0800 - 0FFF E0 - E0, A0 - BF, 80 - BF 2048 +// 001000 - 00CFFF 1000 - CFFF E1 - EC, 80 - BF, 80 - BF 49152 +// 00D000 - 00D7FF D000 - D7FF ED - ED, 80 - 9F, 80 - BF 2048 +// 00D800 - 00DFFF invalid +// 00E000 - 00FFFF E000 - FFFF EE - EF, 80 - BF, 80 - BF 8192 +// 010000 - 03FFFF D800 - D8BF, DC00 - DFFF F0 - F0, 90 - BF, 80 - BF, 80 - BF 196608 +// 040000 - 0FFFFF D8C0 - DBBF, DC00 - DFFF F1 - F3, 80 - BF, 80 - BF, 80 - BF 786432 +// 100000 - 10FFFF DBC0 - DBFF, DC00 - DFFF F4 - F4, 80 - 8F, 80 - BF, 80 - BF 65536 + +// template <> class codecvt<char16_t, char, mbstate_t> + +locale::id codecvt<char16_t, char, mbstate_t>::id; + +codecvt<char16_t, char, mbstate_t>::~codecvt() +{ +} + +codecvt<char16_t, char, mbstate_t>::result +codecvt<char16_t, char, mbstate_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end; ++frm_nxt) + { + intern_type wc1 = *frm_nxt; + if (wc1 < 0x0080) + { + if (to_end-to_nxt < 1) + return partial; + *to_nxt++ = static_cast<extern_type>(wc1); + } + else if (wc1 < 0x0800) + { + if (to_end-to_nxt < 2) + return partial; + *to_nxt++ = static_cast<extern_type>(0xC0 | (wc1 >> 6)); + *to_nxt++ = static_cast<extern_type>(0x80 | (wc1 & 0x03F)); + } + else if (wc1 < 0xD800) + { + if (to_end-to_nxt < 3) + return partial; + *to_nxt++ = static_cast<extern_type>(0xE0 | (wc1 >> 12)); + *to_nxt++ = static_cast<extern_type>(0x80 | ((wc1 & 0x0FC0) >> 6)); + *to_nxt++ = static_cast<extern_type>(0x80 | (wc1 & 0x003F)); + } + else if (wc1 < 0xDC00) + { + if (frm_end-frm_nxt < 2) + return partial; + intern_type wc2 = frm_nxt[1]; + if ((wc2 & 0xFC00) != 0xDC00) + return error; + if (to_end-to_nxt < 4) + return partial; + ++frm_nxt; + unsigned char z = ((wc1 & 0x03C0) >> 6) + 1; + *to_nxt++ = static_cast<extern_type>(0xF0 | (z >> 2)); + *to_nxt++ = static_cast<extern_type>(0x80 | ((z & 0x03) << 4) | ((wc1 & 0x003C) >> 2)); + *to_nxt++ = static_cast<extern_type>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); + *to_nxt++ = static_cast<extern_type>(0x80 | (wc2 & 0x003F)); + } + else if (wc1 < 0xE000) + { + return error; + } + else + { + if (to_end-to_nxt < 3) + return partial; + *to_nxt++ = static_cast<extern_type>(0xE0 | (wc1 >> 12)); + *to_nxt++ = static_cast<extern_type>(0x80 | ((wc1 & 0x0FC0) >> 6)); + *to_nxt++ = static_cast<extern_type>(0x80 | (wc1 & 0x003F)); + } + } + return ok; +} + +codecvt<char16_t, char, mbstate_t>::result +codecvt<char16_t, char, mbstate_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) + { + unsigned char c1 = static_cast<unsigned char>(*frm_nxt); + if (c1 < 0x80) + { + *to_nxt = static_cast<intern_type>(c1); + ++frm_nxt; + } + else if (c1 < 0xC2) + { + return error; + } + else if (c1 < 0xE0) + { + if (frm_end-frm_nxt < 2) + return partial; + unsigned char c2 = frm_nxt[1]; + if ((c2 & 0xC0) != 0x80) + return error; + *to_nxt = static_cast<intern_type>(((c1 & 0x1F) << 6) + | (c2 & 0x3F)); + frm_nxt += 2; + } + else if (c1 < 0xF0) + { + if (frm_end-frm_nxt < 3) + return partial; + unsigned char c2 = frm_nxt[1]; + unsigned char c3 = frm_nxt[2]; + switch (c1) + { + case 0xE0: + if ((c2 & 0xE0) != 0xA0) + return error; + break; + case 0xED: + if ((c2 & 0xE0) != 0x80) + return error; + break; + default: + if ((c2 & 0xC0) != 0x80) + return error; + break; + } + if ((c3 & 0xC0) != 0x80) + return error; + *to_nxt = static_cast<intern_type>(((c1 & 0x0F) << 12) + | ((c2 & 0x3F) << 6) + | (c3 & 0x3F)); + frm_nxt += 3; + } + else if (c1 < 0xF5) + { + if (frm_end-frm_nxt < 4) + return partial; + unsigned char c2 = frm_nxt[1]; + unsigned char c3 = frm_nxt[2]; + unsigned char c4 = frm_nxt[3]; + switch (c1) + { + case 0xF0: + if (!(0x90 <= c2 && c2 <= 0xBF)) + return error; + break; + case 0xF4: + if ((c2 & 0xF0) != 0x80) + return error; + break; + default: + if ((c2 & 0xC0) != 0x80) + return error; + break; + } + if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) + return error; + if (to_end-to_nxt < 2) + return partial; + *to_nxt = static_cast<intern_type>( + 0xD800 + | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) + | ((c2 & 0x0F) << 2) + | ((c3 & 0x30) >> 4)); + *++to_nxt = static_cast<intern_type>( + 0xDC00 + | ((c3 & 0x0F) << 6) + | (c4 & 0x3F)); + frm_nxt += 4; + } + else + { + return error; + } + } + return frm_nxt < frm_end ? partial : ok; +} + +codecvt<char16_t, char, mbstate_t>::result +codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +codecvt<char16_t, char, mbstate_t>::do_encoding() const throw() +{ + return 0; +} + +bool +codecvt<char16_t, char, mbstate_t>::do_always_noconv() const throw() +{ + return false; +} + +int +codecvt<char16_t, char, mbstate_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const extern_type* frm_nxt = frm; + for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t) + { + unsigned char c1 = static_cast<unsigned char>(*frm_nxt); + if (c1 < 0x80) + { + ++frm_nxt; + } + else if (c1 < 0xC2) + { + break; + } + else if (c1 < 0xE0) + { + if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80) + break; + frm_nxt += 2; + } + else if (c1 < 0xF0) + { + if (frm_end-frm_nxt < 3) + break; + unsigned char c2 = frm_nxt[1]; + unsigned char c3 = frm_nxt[2]; + switch (c1) + { + case 0xE0: + if ((c2 & 0xE0) != 0xA0) + return static_cast<int>(frm_nxt - frm); + break; + case 0xED: + if ((c2 & 0xE0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + default: + if ((c2 & 0xC0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + } + if ((c3 & 0xC0) != 0x80) + break; + frm_nxt += 3; + } + else if (c1 < 0xF5) + { + if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2) + break; + unsigned char c2 = frm_nxt[1]; + unsigned char c3 = frm_nxt[2]; + unsigned char c4 = frm_nxt[3]; + switch (c1) + { + case 0xF0: + if (!(0x90 <= c2 && c2 <= 0xBF)) + return static_cast<int>(frm_nxt - frm); + break; + case 0xF4: + if ((c2 & 0xF0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + default: + if ((c2 & 0xC0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + } + if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) + break; + ++nchar16_t; + frm_nxt += 4; + } + else + { + break; + } + } + return static_cast<int>(frm_nxt - frm); +} + +int +codecvt<char16_t, char, mbstate_t>::do_max_length() const throw() +{ + return 4; +} + +// template <> class codecvt<char32_t, char, mbstate_t> + +locale::id codecvt<char32_t, char, mbstate_t>::id; + +codecvt<char32_t, char, mbstate_t>::~codecvt() +{ +} + +codecvt<char32_t, char, mbstate_t>::result +codecvt<char32_t, char, mbstate_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end; ++frm_nxt) + { + intern_type wc = *frm_nxt; + if ((wc & 0xFFFFF800) == 0x00D800 || wc >= 0x110000) + return error; + if (wc < 0x000080) + { + if (to_end-to_nxt < 1) + return partial; + *to_nxt++ = static_cast<extern_type>(wc); + } + else if (wc < 0x000800) + { + if (to_end-to_nxt < 2) + return partial; + *to_nxt++ = static_cast<extern_type>(0xC0 | (wc >> 6)); + *to_nxt++ = static_cast<extern_type>(0x80 | (wc & 0x03F)); + } + else if (wc < 0x010000) + { + if (to_end-to_nxt < 3) + return partial; + *to_nxt++ = static_cast<extern_type>(0xE0 | (wc >> 12)); + *to_nxt++ = static_cast<extern_type>(0x80 | ((wc & 0x0FC0) >> 6)); + *to_nxt++ = static_cast<extern_type>(0x80 | (wc & 0x003F)); + } + else // if (wc < 0x110000) + { + if (to_end-to_nxt < 4) + return partial; + *to_nxt++ = static_cast<extern_type>(0xF0 | (wc >> 18)); + *to_nxt++ = static_cast<extern_type>(0x80 | ((wc & 0x03F000) >> 12)); + *to_nxt++ = static_cast<extern_type>(0x80 | ((wc & 0x000FC0) >> 6)); + *to_nxt++ = static_cast<extern_type>(0x80 | (wc & 0x00003F)); + } + } + return ok; +} + +codecvt<char32_t, char, mbstate_t>::result +codecvt<char32_t, char, mbstate_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) + { + unsigned char c1 = static_cast<unsigned char>(*frm_nxt); + if (c1 < 0x80) + { + *to_nxt = static_cast<intern_type>(c1); + ++frm_nxt; + } + else if (c1 < 0xC2) + { + return error; + } + else if (c1 < 0xE0) + { + if (frm_end-frm_nxt < 2) + return partial; + unsigned char c2 = frm_nxt[1]; + if ((c2 & 0xC0) != 0x80) + return error; + *to_nxt = static_cast<intern_type>(((c1 & 0x1F) << 6) + | (c2 & 0x3F)); + frm_nxt += 2; + } + else if (c1 < 0xF0) + { + if (frm_end-frm_nxt < 3) + return partial; + unsigned char c2 = frm_nxt[1]; + unsigned char c3 = frm_nxt[2]; + switch (c1) + { + case 0xE0: + if ((c2 & 0xE0) != 0xA0) + return error; + break; + case 0xED: + if ((c2 & 0xE0) != 0x80) + return error; + break; + default: + if ((c2 & 0xC0) != 0x80) + return error; + break; + } + if ((c3 & 0xC0) != 0x80) + return error; + *to_nxt = static_cast<intern_type>(((c1 & 0x0F) << 12) + | ((c2 & 0x3F) << 6) + | (c3 & 0x3F)); + frm_nxt += 3; + } + else if (c1 < 0xF5) + { + if (frm_end-frm_nxt < 4) + return partial; + unsigned char c2 = frm_nxt[1]; + unsigned char c3 = frm_nxt[2]; + unsigned char c4 = frm_nxt[3]; + switch (c1) + { + case 0xF0: + if (!(0x90 <= c2 && c2 <= 0xBF)) + return error; + break; + case 0xF4: + if ((c2 & 0xF0) != 0x80) + return error; + break; + default: + if ((c2 & 0xC0) != 0x80) + return error; + break; + } + if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) + return error; + *to_nxt = static_cast<intern_type>(((c1 & 0x07) << 18) + | ((c2 & 0x3F) << 12) + | ((c3 & 0x3F) << 6) + | (c4 & 0x3F)); + frm_nxt += 4; + } + else + { + return error; + } + } + return frm_nxt < frm_end ? partial : ok; +} + +codecvt<char32_t, char, mbstate_t>::result +codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +codecvt<char32_t, char, mbstate_t>::do_encoding() const throw() +{ + return 0; +} + +bool +codecvt<char32_t, char, mbstate_t>::do_always_noconv() const throw() +{ + return false; +} + +int +codecvt<char32_t, char, mbstate_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const extern_type* frm_nxt = frm; + for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) + { + unsigned char c1 = static_cast<unsigned char>(*frm_nxt); + if (c1 < 0x80) + { + ++frm_nxt; + } + else if (c1 < 0xC2) + { + break; + } + else if (c1 < 0xE0) + { + if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) + break; + frm_nxt += 2; + } + else if (c1 < 0xF0) + { + if (frm_end-frm_nxt < 3) + break; + unsigned char c2 = frm_nxt[1]; + unsigned char c3 = frm_nxt[2]; + switch (c1) + { + case 0xE0: + if ((c2 & 0xE0) != 0xA0) + return static_cast<int>(frm_nxt - frm); + break; + case 0xED: + if ((c2 & 0xE0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + default: + if ((c2 & 0xC0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + } + if ((c3 & 0xC0) != 0x80) + break; + frm_nxt += 3; + } + else if (c1 < 0xF5) + { + if (frm_end-frm_nxt < 4) + break; + unsigned char c2 = frm_nxt[1]; + unsigned char c3 = frm_nxt[2]; + unsigned char c4 = frm_nxt[3]; + switch (c1) + { + case 0xF0: + if (!(0x90 <= c2 && c2 <= 0xBF)) + return static_cast<int>(frm_nxt - frm); + break; + case 0xF4: + if ((c2 & 0xF0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + default: + if ((c2 & 0xC0) != 0x80) + return static_cast<int>(frm_nxt - frm); + break; + } + if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) + break; + frm_nxt += 4; + } + else + { + break; + } + } + return static_cast<int>(frm_nxt - frm); +} + +int +codecvt<char32_t, char, mbstate_t>::do_max_length() const throw() +{ + return 4; +} + +// template <> class codecvt<char32_t, char16_t, mbstate_t> + +locale::id codecvt<char32_t, char16_t, mbstate_t>::id; + +codecvt<char32_t, char16_t, mbstate_t>::~codecvt() +{ +} + +codecvt<char32_t, char16_t, mbstate_t>::result +codecvt<char32_t, char16_t, mbstate_t>::do_out(state_type&, + const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, + extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ + for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end; ++frm_nxt) + { + intern_type wc = *frm_nxt; + if ((wc & 0xFFFFF800) == 0x00D800 || wc >= 0x110000) + return error; + if (wc < 0x010000) + { + if (to_end-to_nxt < 1) + return partial; + *to_nxt++ = static_cast<extern_type>(wc); + } + else + { + if (to_end-to_nxt < 2) + return partial; + *to_nxt++ = static_cast<extern_type>( + 0xD800 + | ((((wc & 0x1F0000) >> 16) - 1) << 6) + | ((wc & 0x00FC00) >> 10)); + *to_nxt++ = static_cast<extern_type>( + 0xDC00 + | (wc & 0x03FF)); + } + } + return ok; +} + +codecvt<char32_t, char16_t, mbstate_t>::result +codecvt<char32_t, char16_t, mbstate_t>::do_in(state_type&, + const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, + intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ + for (frm_nxt = frm, to_nxt = to; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) + { + extern_type c1 = *frm_nxt; + if ((c1 & 0xFC00) == 0xDC00) + return error; + if ((c1 & 0xFC00) != 0xD800) + { + *to_nxt = static_cast<intern_type>(c1); + ++frm_nxt; + } + else + { + if (frm_end-frm_nxt < 2) + return partial; + extern_type c2 = frm_nxt[1]; + if ((c2 & 0xFC00) != 0xDC00) + return error; + *to_nxt = static_cast<intern_type>( + ((((c1 & 0x03C0) >> 6) + 1) << 16) + | ((c1 & 0x003F) << 10) + | (c2 & 0x03FF)); + frm_nxt += 2; + } + } + return frm_nxt < frm_end ? partial : ok; +} + +codecvt<char32_t, char16_t, mbstate_t>::result +codecvt<char32_t, char16_t, mbstate_t>::do_unshift(state_type&, + extern_type* to, extern_type*, extern_type*& to_nxt) const +{ + to_nxt = to; + return noconv; +} + +int +codecvt<char32_t, char16_t, mbstate_t>::do_encoding() const throw() +{ + return 0; +} + +bool +codecvt<char32_t, char16_t, mbstate_t>::do_always_noconv() const throw() +{ + return false; +} + +int +codecvt<char32_t, char16_t, mbstate_t>::do_length(state_type&, + const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ + const extern_type* frm_nxt = frm; + for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) + { + extern_type c1 = *frm_nxt; + if ((c1 & 0xFC00) == 0xDC00) + break; + if ((c1 & 0xFC00) != 0xD800) + { + ++frm_nxt; + } + else + { + if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xFC00) != 0xDC00) + break; + frm_nxt += 2; + } + } + return static_cast<int>(frm_nxt - frm); +} + +int +codecvt<char32_t, char16_t, mbstate_t>::do_max_length() const throw() +{ + return 2; +} + +// __narrow_to_utf8<16> + +__narrow_to_utf8<16>::~__narrow_to_utf8() +{ +} + +// __narrow_to_utf8<32> + +__narrow_to_utf8<32>::~__narrow_to_utf8() +{ +} + +// __widen_from_utf8<16> + +__widen_from_utf8<16>::~__widen_from_utf8() +{ +} + +// __widen_from_utf8<32> + +__widen_from_utf8<32>::~__widen_from_utf8() +{ +} + +// numpunct<char> && numpunct<wchar_t> + +locale::id numpunct< char >::id; +locale::id numpunct<wchar_t>::id; + +numpunct<char>::numpunct(size_t refs) + : locale::facet(refs), + __decimal_point_('.'), + __thousands_sep_(',') +{ +} + +numpunct<wchar_t>::numpunct(size_t refs) + : locale::facet(refs), + __decimal_point_(L'.'), + __thousands_sep_(L',') +{ +} + +numpunct<char>::~numpunct() +{ +} + +numpunct<wchar_t>::~numpunct() +{ +} + + char numpunct< char >::do_decimal_point() const {return __decimal_point_;} +wchar_t numpunct<wchar_t>::do_decimal_point() const {return __decimal_point_;} + + char numpunct< char >::do_thousands_sep() const {return __thousands_sep_;} +wchar_t numpunct<wchar_t>::do_thousands_sep() const {return __thousands_sep_;} + +string numpunct< char >::do_grouping() const {return __grouping_;} +string numpunct<wchar_t>::do_grouping() const {return __grouping_;} + + string numpunct< char >::do_truename() const {return "true";} +wstring numpunct<wchar_t>::do_truename() const {return L"true";} + + string numpunct< char >::do_falsename() const {return "false";} +wstring numpunct<wchar_t>::do_falsename() const {return L"false";} + +// numpunct_byname<char> + +numpunct_byname<char>::numpunct_byname(const char* nm, size_t refs) + : numpunct<char>(refs) +{ + __init(nm); +} + +numpunct_byname<char>::numpunct_byname(const string& nm, size_t refs) + : numpunct<char>(refs) +{ + __init(nm.c_str()); +} + +numpunct_byname<char>::~numpunct_byname() +{ +} + +void +numpunct_byname<char>::__init(const char* nm) +{ + if (strcmp(nm, "C") != 0) + { + unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); + if (loc == 0) + throw runtime_error("numpunct_byname<char>::numpunct_byname" + " failed to construct for " + string(nm)); + lconv* lc = localeconv_l(loc.get()); + if (*lc->decimal_point) + __decimal_point_ = *lc->decimal_point; + if (*lc->thousands_sep) + __thousands_sep_ = *lc->thousands_sep; + __grouping_ = lc->grouping; + // locallization for truename and falsename is not available + } +} + +// numpunct_byname<wchar_t> + +numpunct_byname<wchar_t>::numpunct_byname(const char* nm, size_t refs) + : numpunct<wchar_t>(refs) +{ + __init(nm); +} + +numpunct_byname<wchar_t>::numpunct_byname(const string& nm, size_t refs) + : numpunct<wchar_t>(refs) +{ + __init(nm.c_str()); +} + +numpunct_byname<wchar_t>::~numpunct_byname() +{ +} + +void +numpunct_byname<wchar_t>::__init(const char* nm) +{ + if (strcmp(nm, "C") != 0) + { + unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); + if (loc == 0) + throw runtime_error("numpunct_byname<char>::numpunct_byname" + " failed to construct for " + string(nm)); + lconv* lc = localeconv_l(loc.get()); + if (*lc->decimal_point) + __decimal_point_ = *lc->decimal_point; + if (*lc->thousands_sep) + __thousands_sep_ = *lc->thousands_sep; + __grouping_ = lc->grouping; + // locallization for truename and falsename is not available + } +} + +// num_get helpers + +int +__num_get_base::__get_base(ios_base& iob) +{ + ios_base::fmtflags __basefield = iob.flags() & ios_base::basefield; + if (__basefield == ios_base::oct) + return 8; + else if (__basefield == ios_base::hex) + return 16; + else if (__basefield == 0) + return 0; + return 10; +} + +const char __num_get_base::__src[33] = "0123456789abcdefABCDEFxX+-pPiInN"; + +void +__check_grouping(const string& __grouping, unsigned* __g, unsigned* __g_end, + ios_base::iostate& __err) +{ + if (__grouping.size() != 0) + { + reverse(__g, __g_end); + const char* __ig = __grouping.data(); + const char* __eg = __ig + __grouping.size(); + for (unsigned* __r = __g; __r < __g_end-1; ++__r) + { + if (0 < *__ig && *__ig < numeric_limits<char>::max()) + { + if (*__ig != *__r) + { + __err = ios_base::failbit; + return; + } + } + if (__eg - __ig > 1) + ++__ig; + } + if (0 < *__ig && *__ig < numeric_limits<char>::max()) + { + if (*__ig < __g_end[-1] || __g_end[-1] == 0) + __err = ios_base::failbit; + } + } +} + +void +__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd, + ios_base::fmtflags __flags) +{ + if (__flags & ios_base::showpos) + *__fmtp++ = '+'; + if (__flags & ios_base::showbase) + *__fmtp++ = '#'; + while(*__len) + *__fmtp++ = *__len++; + if ((__flags & ios_base::basefield) == ios_base::oct) + *__fmtp = 'o'; + else if ((__flags & ios_base::basefield) == ios_base::hex) + { + if (__flags & ios_base::uppercase) + *__fmtp = 'X'; + else + *__fmtp = 'x'; + } + else if (__signd) + *__fmtp = 'd'; + else + *__fmtp = 'u'; +} + +bool +__num_put_base::__format_float(char* __fmtp, const char* __len, + ios_base::fmtflags __flags) +{ + bool specify_precision = true; + if (__flags & ios_base::showpos) + *__fmtp++ = '+'; + if (__flags & ios_base::showpoint) + *__fmtp++ = '#'; + ios_base::fmtflags floatfield = __flags & ios_base::floatfield; + bool uppercase = __flags & ios_base::uppercase; + if (floatfield == (ios_base::fixed | ios_base::scientific)) + specify_precision = false; + else + { + *__fmtp++ = '.'; + *__fmtp++ = '*'; + } + while(*__len) + *__fmtp++ = *__len++; + if (floatfield == ios_base::fixed) + { + if (uppercase) + *__fmtp = 'F'; + else + *__fmtp = 'f'; + } + else if (floatfield == ios_base::scientific) + { + if (uppercase) + *__fmtp = 'E'; + else + *__fmtp = 'e'; + } + else if (floatfield == (ios_base::fixed | ios_base::scientific)) + { + if (uppercase) + *__fmtp = 'A'; + else + *__fmtp = 'a'; + } + else + { + if (uppercase) + *__fmtp = 'G'; + else + *__fmtp = 'g'; + } + return specify_precision; +} + +char* +__num_put_base::__identify_padding(char* __nb, char* __ne, + const ios_base& __iob) +{ + switch (__iob.flags() & ios_base::adjustfield) + { + case ios_base::internal: + if (__nb[0] == '-' || __nb[0] == '+') + return __nb+1; + if (__ne - __nb >= 2 && __nb[0] == '0' + && (__nb[1] == 'x' || __nb[1] == 'X')) + return __nb+2; + break; + case ios_base::left: + return __ne; + case ios_base::right: + default: + break; + } + return __nb; +} + +// time_get + +static +string* +init_weeks() +{ + static string weeks[14]; + weeks[0] = "Sunday"; + weeks[1] = "Monday"; + weeks[2] = "Tuesday"; + weeks[3] = "Wednesday"; + weeks[4] = "Thursday"; + weeks[5] = "Friday"; + weeks[6] = "Saturday"; + weeks[7] = "Sun"; + weeks[8] = "Mon"; + weeks[9] = "Tue"; + weeks[10] = "Wed"; + weeks[11] = "Thu"; + weeks[12] = "Fri"; + weeks[13] = "Sat"; + return weeks; +} + +static +wstring* +init_wweeks() +{ + static wstring weeks[14]; + weeks[0] = L"Sunday"; + weeks[1] = L"Monday"; + weeks[2] = L"Tuesday"; + weeks[3] = L"Wednesday"; + weeks[4] = L"Thursday"; + weeks[5] = L"Friday"; + weeks[6] = L"Saturday"; + weeks[7] = L"Sun"; + weeks[8] = L"Mon"; + weeks[9] = L"Tue"; + weeks[10] = L"Wed"; + weeks[11] = L"Thu"; + weeks[12] = L"Fri"; + weeks[13] = L"Sat"; + return weeks; +} + +template <> +const string* +__time_get_c_storage<char>::__weeks() const +{ + static const string* weeks = init_weeks(); + return weeks; +} + +template <> +const wstring* +__time_get_c_storage<wchar_t>::__weeks() const +{ + static const wstring* weeks = init_wweeks(); + return weeks; +} + +static +string* +init_months() +{ + static string months[24]; + months[0] = "January"; + months[1] = "February"; + months[2] = "March"; + months[3] = "April"; + months[4] = "May"; + months[5] = "June"; + months[6] = "July"; + months[7] = "August"; + months[8] = "September"; + months[9] = "October"; + months[10] = "November"; + months[11] = "December"; + months[12] = "Jan"; + months[13] = "Feb"; + months[14] = "Mar"; + months[15] = "Apr"; + months[16] = "May"; + months[17] = "Jun"; + months[18] = "Jul"; + months[19] = "Aug"; + months[20] = "Sep"; + months[21] = "Oct"; + months[22] = "Nov"; + months[23] = "Dec"; + return months; +} + +static +wstring* +init_wmonths() +{ + static wstring months[24]; + months[0] = L"January"; + months[1] = L"February"; + months[2] = L"March"; + months[3] = L"April"; + months[4] = L"May"; + months[5] = L"June"; + months[6] = L"July"; + months[7] = L"August"; + months[8] = L"September"; + months[9] = L"October"; + months[10] = L"November"; + months[11] = L"December"; + months[12] = L"Jan"; + months[13] = L"Feb"; + months[14] = L"Mar"; + months[15] = L"Apr"; + months[16] = L"May"; + months[17] = L"Jun"; + months[18] = L"Jul"; + months[19] = L"Aug"; + months[20] = L"Sep"; + months[21] = L"Oct"; + months[22] = L"Nov"; + months[23] = L"Dec"; + return months; +} + +template <> +const string* +__time_get_c_storage<char>::__months() const +{ + static const string* months = init_months(); + return months; +} + +template <> +const wstring* +__time_get_c_storage<wchar_t>::__months() const +{ + static const wstring* months = init_wmonths(); + return months; +} + +static +string* +init_am_pm() +{ + static string am_pm[24]; + am_pm[0] = "AM"; + am_pm[1] = "PM"; + return am_pm; +} + +static +wstring* +init_wam_pm() +{ + static wstring am_pm[24]; + am_pm[0] = L"AM"; + am_pm[1] = L"PM"; + return am_pm; +} + +template <> +const string* +__time_get_c_storage<char>::__am_pm() const +{ + static const string* am_pm = init_am_pm(); + return am_pm; +} + +template <> +const wstring* +__time_get_c_storage<wchar_t>::__am_pm() const +{ + static const wstring* am_pm = init_wam_pm(); + return am_pm; +} + +template <> +const string& +__time_get_c_storage<char>::__x() const +{ + static string s("%m/%d/%y"); + return s; +} + +template <> +const wstring& +__time_get_c_storage<wchar_t>::__x() const +{ + static wstring s(L"%m/%d/%y"); + return s; +} + +template <> +const string& +__time_get_c_storage<char>::__X() const +{ + static string s("%H:%M:%S"); + return s; +} + +template <> +const wstring& +__time_get_c_storage<wchar_t>::__X() const +{ + static wstring s(L"%H:%M:%S"); + return s; +} + +template <> +const string& +__time_get_c_storage<char>::__c() const +{ + static string s("%a %b %d %H:%M:%S %Y"); + return s; +} + +template <> +const wstring& +__time_get_c_storage<wchar_t>::__c() const +{ + static wstring s(L"%a %b %d %H:%M:%S %Y"); + return s; +} + +template <> +const string& +__time_get_c_storage<char>::__r() const +{ + static string s("%I:%M:%S %p"); + return s; +} + +template <> +const wstring& +__time_get_c_storage<wchar_t>::__r() const +{ + static wstring s(L"%I:%M:%S %p"); + return s; +} + +// time_get_byname + +__time_get::__time_get(const char* nm) + : __loc_(newlocale(LC_ALL_MASK, nm, 0)) +{ + if (__loc_ == 0) + throw runtime_error("time_get_byname" + " failed to construct for " + string(nm)); +} + +__time_get::__time_get(const string& nm) + : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) +{ + if (__loc_ == 0) + throw runtime_error("time_get_byname" + " failed to construct for " + nm); +} + +__time_get::~__time_get() +{ + freelocale(__loc_); +} + +template <> +string +__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct) +{ + tm t; + t.tm_sec = 59; + t.tm_min = 55; + t.tm_hour = 23; + t.tm_mday = 31; + t.tm_mon = 11; + t.tm_year = 161; + t.tm_wday = 6; + t.tm_yday = 364; + t.tm_isdst = -1; + char buf[100]; + char f[3] = {0}; + f[0] = '%'; + f[1] = fmt; + size_t n = strftime_l(buf, 100, f, &t, __loc_); + char* bb = buf; + char* be = buf + n; + string result; + while (bb != be) + { + if (ct.is(ctype_base::space, *bb)) + { + result.push_back(' '); + for (++bb; bb != be && ct.is(ctype_base::space, *bb); ++bb) + ; + continue; + } + char* w = bb; + ios_base::iostate err = ios_base::goodbit; + int i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14, + ct, err, false) + - this->__weeks_; + if (i < 14) + { + result.push_back('%'); + if (i < 7) + result.push_back('A'); + else + result.push_back('a'); + bb = w; + continue; + } + w = bb; + i = __scan_keyword(w, be, this->__months_, this->__months_+24, + ct, err, false) + - this->__months_; + if (i < 24) + { + result.push_back('%'); + if (i < 12) + result.push_back('B'); + else + result.push_back('b'); + if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) + result.back() = 'm'; + bb = w; + continue; + } + if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) + { + w = bb; + i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2, + ct, err, false) - this->__am_pm_; + if (i < 2) + { + result.push_back('%'); + result.push_back('p'); + bb = w; + continue; + } + } + w = bb; + if (ct.is(ctype_base::digit, *bb)) + { + switch(__get_up_to_n_digits(bb, be, err, ct, 4)) + { + case 6: + result.push_back('%'); + result.push_back('w'); + break; + case 7: + result.push_back('%'); + result.push_back('u'); + break; + case 11: + result.push_back('%'); + result.push_back('I'); + break; + case 12: + result.push_back('%'); + result.push_back('m'); + break; + case 23: + result.push_back('%'); + result.push_back('H'); + break; + case 31: + result.push_back('%'); + result.push_back('d'); + break; + case 55: + result.push_back('%'); + result.push_back('M'); + break; + case 59: + result.push_back('%'); + result.push_back('S'); + break; + case 61: + result.push_back('%'); + result.push_back('y'); + break; + case 364: + result.push_back('%'); + result.push_back('j'); + break; + case 2061: + result.push_back('%'); + result.push_back('Y'); + break; + default: + for (; w != bb; ++w) + result.push_back(*w); + break; + } + continue; + } + if (*bb == '%') + { + result.push_back('%'); + result.push_back('%'); + ++bb; + continue; + } + result.push_back(*bb); + ++bb; + } + return result; +} + +template <> +wstring +__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct) +{ + tm t; + t.tm_sec = 59; + t.tm_min = 55; + t.tm_hour = 23; + t.tm_mday = 31; + t.tm_mon = 11; + t.tm_year = 161; + t.tm_wday = 6; + t.tm_yday = 364; + t.tm_isdst = -1; + char buf[100]; + char f[3] = {0}; + f[0] = '%'; + f[1] = fmt; + size_t be = strftime_l(buf, 100, f, &t, __loc_); + wchar_t wbuf[100]; + wchar_t* wbb = wbuf; + mbstate_t mb = {0}; + const char* bb = buf; + size_t i = mbsrtowcs_l(wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + if (i == -1) + __throw_runtime_error("locale not supported"); + wchar_t* wbe = wbb + i; + wstring result; + while (wbb != wbe) + { + if (ct.is(ctype_base::space, *wbb)) + { + result.push_back(L' '); + for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb) + ; + continue; + } + wchar_t* w = wbb; + ios_base::iostate err = ios_base::goodbit; + int i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14, + ct, err, false) + - this->__weeks_; + if (i < 14) + { + result.push_back(L'%'); + if (i < 7) + result.push_back(L'A'); + else + result.push_back(L'a'); + wbb = w; + continue; + } + w = wbb; + i = __scan_keyword(w, wbe, this->__months_, this->__months_+24, + ct, err, false) + - this->__months_; + if (i < 24) + { + result.push_back(L'%'); + if (i < 12) + result.push_back(L'B'); + else + result.push_back(L'b'); + if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) + result.back() = L'm'; + wbb = w; + continue; + } + if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) + { + w = wbb; + i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2, + ct, err, false) - this->__am_pm_; + if (i < 2) + { + result.push_back(L'%'); + result.push_back(L'p'); + wbb = w; + continue; + } + } + w = wbb; + if (ct.is(ctype_base::digit, *wbb)) + { + switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4)) + { + case 6: + result.push_back(L'%'); + result.push_back(L'w'); + break; + case 7: + result.push_back(L'%'); + result.push_back(L'u'); + break; + case 11: + result.push_back(L'%'); + result.push_back(L'I'); + break; + case 12: + result.push_back(L'%'); + result.push_back(L'm'); + break; + case 23: + result.push_back(L'%'); + result.push_back(L'H'); + break; + case 31: + result.push_back(L'%'); + result.push_back(L'd'); + break; + case 55: + result.push_back(L'%'); + result.push_back(L'M'); + break; + case 59: + result.push_back(L'%'); + result.push_back(L'S'); + break; + case 61: + result.push_back(L'%'); + result.push_back(L'y'); + break; + case 364: + result.push_back(L'%'); + result.push_back(L'j'); + break; + case 2061: + result.push_back(L'%'); + result.push_back(L'Y'); + break; + default: + for (; w != wbb; ++w) + result.push_back(*w); + break; + } + continue; + } + if (ct.narrow(*wbb, 0) == '%') + { + result.push_back(L'%'); + result.push_back(L'%'); + ++wbb; + continue; + } + result.push_back(*wbb); + ++wbb; + } + return result; +} + +template <> +void +__time_get_storage<char>::init(const ctype<char>& ct) +{ + tm t; + char buf[100]; + // __weeks_ + for (int i = 0; i < 7; ++i) + { + t.tm_wday = i; + strftime_l(buf, 100, "%A", &t, __loc_); + __weeks_[i] = buf; + strftime_l(buf, 100, "%a", &t, __loc_); + __weeks_[i+7] = buf; + } + // __months_ + for (int i = 0; i < 12; ++i) + { + t.tm_mon = i; + strftime_l(buf, 100, "%B", &t, __loc_); + __months_[i] = buf; + strftime_l(buf, 100, "%b", &t, __loc_); + __months_[i+12] = buf; + } + // __am_pm_ + t.tm_hour = 1; + strftime_l(buf, 100, "%p", &t, __loc_); + __am_pm_[0] = buf; + t.tm_hour = 13; + strftime_l(buf, 100, "%p", &t, __loc_); + __am_pm_[1] = buf; + __c_ = __analyze('c', ct); + __r_ = __analyze('r', ct); + __x_ = __analyze('x', ct); + __X_ = __analyze('X', ct); +} + +template <> +void +__time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) +{ + tm t = {0}; + char buf[100]; + size_t be; + wchar_t wbuf[100]; + wchar_t* wbe; + mbstate_t mb = {0}; + // __weeks_ + for (int i = 0; i < 7; ++i) + { + t.tm_wday = i; + be = strftime_l(buf, 100, "%A", &t, __loc_); + mb = mbstate_t(); + const char* bb = buf; + size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + if (j == -1) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __weeks_[i].assign(wbuf, wbe); + be = strftime_l(buf, 100, "%a", &t, __loc_); + mb = mbstate_t(); + bb = buf; + j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + if (j == -1) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __weeks_[i+7].assign(wbuf, wbe); + } + // __months_ + for (int i = 0; i < 12; ++i) + { + t.tm_mon = i; + be = strftime_l(buf, 100, "%B", &t, __loc_); + mb = mbstate_t(); + const char* bb = buf; + size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + if (j == -1) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __months_[i].assign(wbuf, wbe); + be = strftime_l(buf, 100, "%b", &t, __loc_); + mb = mbstate_t(); + bb = buf; + j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + if (j == -1) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __months_[i+12].assign(wbuf, wbe); + } + // __am_pm_ + t.tm_hour = 1; + be = strftime_l(buf, 100, "%p", &t, __loc_); + mb = mbstate_t(); + const char* bb = buf; + size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + if (j == -1) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __am_pm_[0].assign(wbuf, wbe); + t.tm_hour = 13; + be = strftime_l(buf, 100, "%p", &t, __loc_); + mb = mbstate_t(); + bb = buf; + j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); + if (j == -1) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __am_pm_[1].assign(wbuf, wbe); + __c_ = __analyze('c', ct); + __r_ = __analyze('r', ct); + __x_ = __analyze('x', ct); + __X_ = __analyze('X', ct); +} + +template <class CharT> +struct _LIBCPP_HIDDEN __time_get_temp + : public ctype_byname<CharT> +{ + explicit __time_get_temp(const char* nm) + : ctype_byname<CharT>(nm, 1) {} + explicit __time_get_temp(const string& nm) + : ctype_byname<CharT>(nm, 1) {} +}; + +template <> +__time_get_storage<char>::__time_get_storage(const char* __nm) + : __time_get(__nm) +{ + const __time_get_temp<char> ct(__nm); + init(ct); +} + +template <> +__time_get_storage<char>::__time_get_storage(const string& __nm) + : __time_get(__nm) +{ + const __time_get_temp<char> ct(__nm); + init(ct); +} + +template <> +__time_get_storage<wchar_t>::__time_get_storage(const char* __nm) + : __time_get(__nm) +{ + const __time_get_temp<wchar_t> ct(__nm); + init(ct); +} + +template <> +__time_get_storage<wchar_t>::__time_get_storage(const string& __nm) + : __time_get(__nm) +{ + const __time_get_temp<wchar_t> ct(__nm); + init(ct); +} + +template <> +time_base::dateorder +__time_get_storage<char>::__do_date_order() const +{ + unsigned i; + for (i = 0; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + ++i; + switch (__x_[i]) + { + case 'y': + case 'Y': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + switch (__x_[i]) + { + case 'm': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'd') + return time_base::ymd; + break; + case 'd': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'm') + return time_base::ydm; + break; + } + break; + case 'm': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'd') + { + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'y' || __x_[i] == 'Y') + return time_base::mdy; + break; + } + break; + case 'd': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'm') + { + for (++i; i < __x_.size(); ++i) + if (__x_[i] == '%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == 'y' || __x_[i] == 'Y') + return time_base::dmy; + break; + } + break; + } + return time_base::no_order; +} + +template <> +time_base::dateorder +__time_get_storage<wchar_t>::__do_date_order() const +{ + unsigned i; + for (i = 0; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + ++i; + switch (__x_[i]) + { + case L'y': + case L'Y': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + switch (__x_[i]) + { + case L'm': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'd') + return time_base::ymd; + break; + case L'd': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'm') + return time_base::ydm; + break; + } + break; + case L'm': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'd') + { + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'y' || __x_[i] == L'Y') + return time_base::mdy; + break; + } + break; + case L'd': + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'm') + { + for (++i; i < __x_.size(); ++i) + if (__x_[i] == L'%') + break; + if (i == __x_.size()) + break; + ++i; + if (__x_[i] == L'y' || __x_[i] == L'Y') + return time_base::dmy; + break; + } + break; + } + return time_base::no_order; +} + +// time_put + +__time_put::__time_put(const char* nm) + : __loc_(newlocale(LC_ALL_MASK, nm, 0)) +{ + if (__loc_ == 0) + throw runtime_error("time_put_byname" + " failed to construct for " + string(nm)); +} + +__time_put::__time_put(const string& nm) + : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) +{ + if (__loc_ == 0) + throw runtime_error("time_put_byname" + " failed to construct for " + nm); +} + +__time_put::~__time_put() +{ + if (__loc_) + freelocale(__loc_); +} + +void +__time_put::__do_put(char* __nb, char*& __ne, const tm* __tm, + char __fmt, char __mod) const +{ + char fmt[] = {'%', __fmt, __mod, 0}; + if (__mod != 0) + swap(fmt[1], fmt[2]); + size_t n = strftime_l(__nb, __ne-__nb, fmt, __tm, __loc_); + __ne = __nb + n; +} + +void +__time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, + char __fmt, char __mod) const +{ + char __nar[100]; + char* __ne = __nar + 100; + __do_put(__nar, __ne, __tm, __fmt, __mod); + mbstate_t mb = {0}; + const char* __nb = __nar; + size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_); + if (j == -1) + __throw_runtime_error("locale not supported"); + __we = __wb + j; +} + +// moneypunct_byname + +static +void +__init_pat(money_base::pattern& pat, char cs_precedes, char sep_by_space, char sign_posn) +{ + const char sign = static_cast<char>(money_base::sign); + const char space = static_cast<char>(money_base::space); + const char none = static_cast<char>(money_base::none); + const char symbol = static_cast<char>(money_base::symbol); + const char value = static_cast<char>(money_base::value); + switch (cs_precedes) + { + case 0: + switch (sign_posn) + { + case 0: + pat.field[0] = sign; + pat.field[1] = value; + pat.field[3] = symbol; + switch (sep_by_space) + { + case 0: + pat.field[2] = none; + return; + case 1: + case 2: + pat.field[2] = space; + return; + default: + break; + } + break; + case 1: + pat.field[0] = sign; + pat.field[3] = symbol; + switch (sep_by_space) + { + case 0: + pat.field[1] = value; + pat.field[2] = none; + return; + case 1: + pat.field[1] = value; + pat.field[2] = space; + return; + case 2: + pat.field[1] = space; + pat.field[2] = value; + return; + default: + break; + } + break; + case 2: + pat.field[0] = value; + pat.field[3] = sign; + switch (sep_by_space) + { + case 0: + pat.field[1] = none; + pat.field[2] = symbol; + return; + case 1: + pat.field[1] = space; + pat.field[2] = symbol; + return; + case 2: + pat.field[1] = symbol; + pat.field[2] = space; + return; + default: + break; + } + break; + case 3: + pat.field[0] = value; + pat.field[3] = symbol; + switch (sep_by_space) + { + case 0: + pat.field[1] = none; + pat.field[2] = sign; + return; + case 1: + pat.field[1] = space; + pat.field[2] = sign; + return; + case 2: + pat.field[1] = sign; + pat.field[2] = space; + return; + default: + break; + } + break; + case 4: + pat.field[0] = value; + pat.field[3] = sign; + switch (sep_by_space) + { + case 0: + pat.field[1] = none; + pat.field[2] = symbol; + return; + case 1: + pat.field[1] = space; + pat.field[2] = symbol; + return; + case 2: + pat.field[1] = symbol; + pat.field[2] = space; + return; + default: + break; + } + break; + default: + break; + } + break; + case 1: + switch (sign_posn) + { + case 0: + pat.field[0] = sign; + pat.field[1] = symbol; + pat.field[3] = value; + switch (sep_by_space) + { + case 0: + pat.field[2] = none; + return; + case 1: + case 2: + pat.field[2] = space; + return; + default: + break; + } + break; + case 1: + pat.field[0] = sign; + pat.field[3] = value; + switch (sep_by_space) + { + case 0: + pat.field[1] = symbol; + pat.field[2] = none; + return; + case 1: + pat.field[1] = symbol; + pat.field[2] = space; + return; + case 2: + pat.field[1] = space; + pat.field[2] = symbol; + return; + default: + break; + } + break; + case 2: + pat.field[0] = symbol; + pat.field[3] = sign; + switch (sep_by_space) + { + case 0: + pat.field[1] = none; + pat.field[2] = value; + return; + case 1: + pat.field[1] = space; + pat.field[2] = value; + return; + case 2: + pat.field[1] = value; + pat.field[2] = space; + return; + default: + break; + } + break; + case 3: + pat.field[0] = sign; + pat.field[3] = value; + switch (sep_by_space) + { + case 0: + pat.field[1] = symbol; + pat.field[2] = none; + return; + case 1: + pat.field[1] = symbol; + pat.field[2] = space; + return; + case 2: + pat.field[1] = space; + pat.field[2] = symbol; + return; + default: + break; + } + break; + case 4: + pat.field[0] = symbol; + pat.field[3] = value; + switch (sep_by_space) + { + case 0: + pat.field[1] = sign; + pat.field[2] = none; + return; + case 1: + pat.field[1] = sign; + pat.field[2] = space; + return; + case 2: + pat.field[1] = space; + pat.field[2] = sign; + return; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + pat.field[0] = symbol; + pat.field[1] = sign; + pat.field[2] = none; + pat.field[3] = value; +} + +template<> +void +moneypunct_byname<char, false>::init(const char* nm) +{ + typedef moneypunct<char, false> base; + unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); + if (loc == 0) + throw runtime_error("moneypunct_byname" + " failed to construct for " + string(nm)); + lconv* lc = localeconv_l(loc.get()); + if (*lc->mon_decimal_point) + __decimal_point_ = *lc->mon_decimal_point; + else + __decimal_point_ = base::do_decimal_point(); + if (*lc->mon_thousands_sep) + __thousands_sep_ = *lc->mon_thousands_sep; + else + __thousands_sep_ = base::do_thousands_sep(); + __grouping_ = lc->mon_grouping; + __curr_symbol_ = lc->currency_symbol; + if (lc->frac_digits != CHAR_MAX) + __frac_digits_ = lc->frac_digits; + else + __frac_digits_ = base::do_frac_digits(); + if (lc->p_sign_posn == 0) + __positive_sign_ = "()"; + else + __positive_sign_ = lc->positive_sign; + if (lc->n_sign_posn == 0) + __negative_sign_ = "()"; + else + __negative_sign_ = lc->negative_sign; + __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn); + __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn); +} + +template<> +void +moneypunct_byname<char, true>::init(const char* nm) +{ + typedef moneypunct<char, true> base; + unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); + if (loc == 0) + throw runtime_error("moneypunct_byname" + " failed to construct for " + string(nm)); + lconv* lc = localeconv_l(loc.get()); + if (*lc->mon_decimal_point) + __decimal_point_ = *lc->mon_decimal_point; + else + __decimal_point_ = base::do_decimal_point(); + if (*lc->mon_thousands_sep) + __thousands_sep_ = *lc->mon_thousands_sep; + else + __thousands_sep_ = base::do_thousands_sep(); + __grouping_ = lc->mon_grouping; + __curr_symbol_ = lc->int_curr_symbol; + if (lc->int_frac_digits != CHAR_MAX) + __frac_digits_ = lc->int_frac_digits; + else + __frac_digits_ = base::do_frac_digits(); + if (lc->int_p_sign_posn == 0) + __positive_sign_ = "()"; + else + __positive_sign_ = lc->positive_sign; + if (lc->int_n_sign_posn == 0) + __negative_sign_ = "()"; + else + __negative_sign_ = lc->negative_sign; + __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn); + __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn); +} + +template<> +void +moneypunct_byname<wchar_t, false>::init(const char* nm) +{ + typedef moneypunct<wchar_t, false> base; + unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); + if (loc == 0) + throw runtime_error("moneypunct_byname" + " failed to construct for " + string(nm)); + lconv* lc = localeconv_l(loc.get()); + if (*lc->mon_decimal_point) + __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point); + else + __decimal_point_ = base::do_decimal_point(); + if (*lc->mon_thousands_sep) + __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep); + else + __thousands_sep_ = base::do_thousands_sep(); + __grouping_ = lc->mon_grouping; + wchar_t wbuf[100]; + mbstate_t mb = {0}; + const char* bb = lc->currency_symbol; + size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + if (j == -1) + __throw_runtime_error("locale not supported"); + wchar_t* wbe = wbuf + j; + __curr_symbol_.assign(wbuf, wbe); + if (lc->frac_digits != CHAR_MAX) + __frac_digits_ = lc->frac_digits; + else + __frac_digits_ = base::do_frac_digits(); + if (lc->p_sign_posn == 0) + __positive_sign_ = L"()"; + else + { + mb = mbstate_t(); + bb = lc->positive_sign; + j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + if (j == -1) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __positive_sign_.assign(wbuf, wbe); + } + if (lc->n_sign_posn == 0) + __negative_sign_ = L"()"; + else + { + mb = mbstate_t(); + bb = lc->negative_sign; + j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + if (j == -1) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __negative_sign_.assign(wbuf, wbe); + } + __init_pat(__pos_format_, lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn); + __init_pat(__neg_format_, lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn); +} + +template<> +void +moneypunct_byname<wchar_t, true>::init(const char* nm) +{ + typedef moneypunct<wchar_t, true> base; + unique_ptr<_xlocale, int(*)(locale_t)> loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); + if (loc == 0) + throw runtime_error("moneypunct_byname" + " failed to construct for " + string(nm)); + lconv* lc = localeconv_l(loc.get()); + if (*lc->mon_decimal_point) + __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point); + else + __decimal_point_ = base::do_decimal_point(); + if (*lc->mon_thousands_sep) + __thousands_sep_ = static_cast<wchar_t>(*lc->mon_thousands_sep); + else + __thousands_sep_ = base::do_thousands_sep(); + __grouping_ = lc->mon_grouping; + wchar_t wbuf[100]; + mbstate_t mb = {0}; + const char* bb = lc->int_curr_symbol; + size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + if (j == -1) + __throw_runtime_error("locale not supported"); + wchar_t* wbe = wbuf + j; + __curr_symbol_.assign(wbuf, wbe); + if (lc->int_frac_digits != CHAR_MAX) + __frac_digits_ = lc->int_frac_digits; + else + __frac_digits_ = base::do_frac_digits(); + if (lc->int_p_sign_posn == 0) + __positive_sign_ = L"()"; + else + { + mb = mbstate_t(); + bb = lc->positive_sign; + j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + if (j == -1) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __positive_sign_.assign(wbuf, wbe); + } + if (lc->int_n_sign_posn == 0) + __negative_sign_ = L"()"; + else + { + mb = mbstate_t(); + bb = lc->negative_sign; + j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); + if (j == -1) + __throw_runtime_error("locale not supported"); + wbe = wbuf + j; + __negative_sign_.assign(wbuf, wbe); + } + __init_pat(__pos_format_, lc->int_p_cs_precedes, lc->int_p_sep_by_space, lc->int_p_sign_posn); + __init_pat(__neg_format_, lc->int_n_cs_precedes, lc->int_n_sep_by_space, lc->int_n_sign_posn); +} + +void __do_nothing(void*) {} + +void __throw_runtime_error(const char* msg) +{ + throw runtime_error(msg); +} + +template class collate<char>; +template class collate<wchar_t>; + +template class num_get<char>; +template class num_get<wchar_t>; + +template class __num_get<char>; +template class __num_get<wchar_t>; + +template class num_put<char>; +template class num_put<wchar_t>; + +template class __num_put<char>; +template class __num_put<wchar_t>; + +template class time_get<char>; +template class time_get<wchar_t>; + +template class time_get_byname<char>; +template class time_get_byname<wchar_t>; + +template class time_put<char>; +template class time_put<wchar_t>; + +template class time_put_byname<char>; +template class time_put_byname<wchar_t>; + +template class moneypunct<char, false>; +template class moneypunct<char, true>; +template class moneypunct<wchar_t, false>; +template class moneypunct<wchar_t, true>; + +template class moneypunct_byname<char, false>; +template class moneypunct_byname<char, true>; +template class moneypunct_byname<wchar_t, false>; +template class moneypunct_byname<wchar_t, true>; + +template class money_get<char>; +template class money_get<wchar_t>; + +template class __money_get<char>; +template class __money_get<wchar_t>; + +template class money_put<char>; +template class money_put<wchar_t>; + +template class __money_put<char>; +template class __money_put<wchar_t>; + +template class messages<char>; +template class messages<wchar_t>; + +template class messages_byname<char>; +template class messages_byname<wchar_t>; + +template class codecvt_byname<char, char, mbstate_t>; +template class codecvt_byname<wchar_t, char, mbstate_t>; +template class codecvt_byname<char16_t, char, mbstate_t>; +template class codecvt_byname<char32_t, char, mbstate_t>; + +template class __vector_base_common<true>; + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/memory.cpp b/libcxx/src/memory.cpp new file mode 100644 index 00000000000..1970598c6f7 --- /dev/null +++ b/libcxx/src/memory.cpp @@ -0,0 +1,201 @@ +//===------------------------ memory.cpp ----------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "memory" +#include <libkern/OSAtomic.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace +{ + +template <class T> +inline +typename enable_if +< + sizeof(T) * __CHAR_BIT__ == 32, + T +>::type +increment(T& t) +{ + return OSAtomicIncrement32Barrier((volatile int32_t*)&t); +} + +template <class T> +inline +typename enable_if +< + sizeof(T) * __CHAR_BIT__ == 32, + T +>::type +decrement(T& t) +{ + return OSAtomicDecrement32Barrier((volatile int32_t*)&t); +} + +#ifndef __ppc__ + +template <class T> +inline +typename enable_if +< + sizeof(T) * __CHAR_BIT__ == 64, + T +>::type +increment(T& t) +{ + return OSAtomicIncrement64Barrier((volatile int64_t*)&t); +} + +template <class T> +inline +typename enable_if +< + sizeof(T) * __CHAR_BIT__ == 64, + T +>::type +decrement(T& t) +{ + return OSAtomicDecrement64Barrier((volatile int64_t*)&t); +} + +#endif + +} // namespace + + +const allocator_arg_t allocator_arg = allocator_arg_t(); + +bad_weak_ptr::~bad_weak_ptr() throw() {} + +const char* +bad_weak_ptr::what() const throw() +{ + return "bad_weak_ptr"; +} + +__shared_count::~__shared_count() +{ +} + +void +__shared_count::__add_shared() +{ + increment(__shared_owners_); +} + +void +__shared_count::__release_shared() +{ + if (decrement(__shared_owners_) == -1) + __on_zero_shared(); +} + +__shared_weak_count::~__shared_weak_count() +{ +} + +void +__shared_weak_count::__add_shared() +{ + __shared_count::__add_shared(); + __add_weak(); +} + +void +__shared_weak_count::__add_weak() +{ + increment(__shared_weak_owners_); +} + +void +__shared_weak_count::__release_shared() +{ + __shared_count::__release_shared(); + __release_weak(); +} + +void +__shared_weak_count::__release_weak() +{ + if (decrement(__shared_weak_owners_) == -1) + __on_zero_shared_weak(); +} + +__shared_weak_count* +__shared_weak_count::lock() +{ + long object_owners = __shared_owners_; + while (object_owners != -1) + { + if (OSAtomicCompareAndSwapLongBarrier(object_owners, + object_owners+1, + &__shared_owners_)) + { + __add_weak(); + return this; + } + object_owners = __shared_owners_; + } + return 0; +} + +const void* +__shared_weak_count::__get_deleter(const type_info&) const +{ + return 0; +} + +void +declare_reachable(void*) +{ +} + +void +declare_no_pointers(char*, size_t) +{ +} + +void +undeclare_no_pointers(char*, size_t) +{ +} + +pointer_safety +get_pointer_safety() +{ + return pointer_safety::relaxed; +} + +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 = (char*)((size_t)(p1 + (alignment - 1)) & -alignment); + ptrdiff_t d = p2 - p1; + if (d <= space - size) + { + r = p2; + ptr = r; + space -= d; + } + } + return r; +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/mutex.cpp b/libcxx/src/mutex.cpp new file mode 100644 index 00000000000..26f22985d7d --- /dev/null +++ b/libcxx/src/mutex.cpp @@ -0,0 +1,246 @@ +//===------------------------- mutex.cpp ----------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "mutex" +#include "limits" +#include "system_error" +#include "cassert" + +_LIBCPP_BEGIN_NAMESPACE_STD + +const defer_lock_t defer_lock = {}; +const try_to_lock_t try_to_lock = {}; +const adopt_lock_t adopt_lock = {}; + +mutex::~mutex() +{ + int e = pthread_mutex_destroy(&__m_); +// assert(e == 0); +} + +void +mutex::lock() +{ + int ec = pthread_mutex_lock(&__m_); + if (ec) + __throw_system_error(ec, "mutex lock failed"); +} + +bool +mutex::try_lock() +{ + return pthread_mutex_trylock(&__m_) == 0; +} + +void +mutex::unlock() +{ + int ec = pthread_mutex_unlock(&__m_); + assert(ec == 0); +} + +// recursive_mutex + +recursive_mutex::recursive_mutex() +{ + pthread_mutexattr_t attr; + int ec = pthread_mutexattr_init(&attr); + if (ec) + goto fail; + ec = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + if (ec) + { + pthread_mutexattr_destroy(&attr); + goto fail; + } + ec = pthread_mutex_init(&__m_, &attr); + if (ec) + { + pthread_mutexattr_destroy(&attr); + goto fail; + } + ec = pthread_mutexattr_destroy(&attr); + if (ec) + { + pthread_mutex_destroy(&__m_); + goto fail; + } + return; +fail: + __throw_system_error(ec, "recursive_mutex constructor failed"); +} + +recursive_mutex::~recursive_mutex() +{ + int e = pthread_mutex_destroy(&__m_); + assert(e == 0); +} + +void +recursive_mutex::lock() +{ + int ec = pthread_mutex_lock(&__m_); + if (ec) + __throw_system_error(ec, "recursive_mutex lock failed"); +} + +void +recursive_mutex::unlock() +{ + int e = pthread_mutex_unlock(&__m_); + assert(e == 0); +} + +bool +recursive_mutex::try_lock() +{ + return pthread_mutex_trylock(&__m_) == 0; +} + +// 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() +{ + unique_lock<mutex> lk(__m_, try_to_lock); + if (lk.owns_lock() && !__locked_) + { + __locked_ = true; + return true; + } + return false; +} + +void +timed_mutex::unlock() +{ + lock_guard<mutex> _(__m_); + __locked_ = false; + __cv_.notify_one(); +} + +// recursive_timed_mutex + +recursive_timed_mutex::recursive_timed_mutex() + : __count_(0), + __id_(nullptr) +{ +} + +recursive_timed_mutex::~recursive_timed_mutex() +{ + lock_guard<mutex> _(__m_); +} + +void +recursive_timed_mutex::lock() +{ + pthread_t id = pthread_self(); + unique_lock<mutex> lk(__m_); + if (pthread_equal(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() +{ + pthread_t id = pthread_self(); + unique_lock<mutex> lk(__m_, try_to_lock); + if (lk.owns_lock() && (__count_ == 0 || pthread_equal(id, __id_))) + { + if (__count_ == numeric_limits<size_t>::max()) + return false; + ++__count_; + __id_ = id; + return true; + } + return false; +} + +void +recursive_timed_mutex::unlock() +{ + unique_lock<mutex> lk(__m_); + if (--__count_ == 0) + { + __id_ = nullptr; + lk.unlock(); + __cv_.notify_one(); + } +} + +// 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. + +static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t cv = PTHREAD_COND_INITIALIZER; + +void +__call_once(volatile unsigned long& flag, void* arg, void(*func)(void*)) +{ + pthread_mutex_lock(&mut); + while (flag == 1) + pthread_cond_wait(&cv, &mut); + if (flag == 0) + { + try + { + flag = 1; + pthread_mutex_unlock(&mut); + func(arg); + pthread_mutex_lock(&mut); + flag = ~0ul; + pthread_mutex_unlock(&mut); + pthread_cond_broadcast(&cv); + } + catch (...) + { + pthread_mutex_lock(&mut); + flag = 0ul; + pthread_mutex_unlock(&mut); + pthread_cond_signal(&cv); + throw; + } + } + else + pthread_mutex_unlock(&mut); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/new.cpp b/libcxx/src/new.cpp new file mode 100644 index 00000000000..4ab199b916e --- /dev/null +++ b/libcxx/src/new.cpp @@ -0,0 +1,31 @@ +//===--------------------------- new.cpp ----------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "new" + +namespace std +{ + +bad_array_new_length::~bad_array_new_length() throw() +{ +} + +const char* +bad_array_new_length::what() const throw() +{ + return "bad_array_new_length"; +} + +void +__throw_bad_alloc() +{ + throw bad_alloc(); +} + +} // std diff --git a/libcxx/src/random.cpp b/libcxx/src/random.cpp new file mode 100644 index 00000000000..269a5974e1c --- /dev/null +++ b/libcxx/src/random.cpp @@ -0,0 +1,46 @@ +//===-------------------------- random.cpp --------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "random" +#include "system_error" + +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + + +_LIBCPP_BEGIN_NAMESPACE_STD + +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; + read(__f_, &r, sizeof(r)); + return r; +} + +double +random_device::entropy() const +{ + return 0; +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/stdexcept.cpp b/libcxx/src/stdexcept.cpp new file mode 100644 index 00000000000..e936188895a --- /dev/null +++ b/libcxx/src/stdexcept.cpp @@ -0,0 +1,179 @@ +//===------------------------ stdexcept.cpp -------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "stdexcept" +#include "new" +#include "string" +#include <cstdlib> +#include <cstring> +#include <cstdint> +#include <cstddef> +#include "system_error" +#include <libkern/OSAtomic.h> + +// Note: optimize for size + +#pragma GCC visibility push(hidden) + +namespace +{ + +class __libcpp_nmstr +{ +private: + const char* str_; + + typedef std::size_t unused_t; + typedef std::int32_t count_t; + + static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) + + sizeof(count_t)); + + count_t& count() const throw() {return (count_t&)(*(str_ - sizeof(count_t)));} +public: + explicit __libcpp_nmstr(const char* msg); + __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; + __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; + ~__libcpp_nmstr() _LIBCPP_CANTTHROW; + const char* c_str() const throw() {return str_;} +}; + +__libcpp_nmstr::__libcpp_nmstr(const char* msg) +{ + std::size_t len = strlen(msg); + str_ = new char[len + 1 + offset]; + unused_t* c = (unused_t*)str_; + c[0] = c[1] = len; + str_ += offset; + count() = 0; + std::strcpy(const_cast<char*>(c_str()), msg); +} + +inline +__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) + : str_(s.str_) +{ + OSAtomicIncrement32Barrier(&count()); +} + +__libcpp_nmstr& +__libcpp_nmstr::operator=(const __libcpp_nmstr& s) +{ + const char* p = str_; + str_ = s.str_; + OSAtomicIncrement32Barrier(&count()); + if (OSAtomicDecrement32((count_t*)(p-sizeof(count_t))) < 0) + delete [] (p-offset); + return *this; +} + +inline +__libcpp_nmstr::~__libcpp_nmstr() +{ + if (OSAtomicDecrement32(&count()) < 0) + delete [] (str_ - offset); +} + +} + +#pragma GCC visiblity pop + +namespace std // purposefully not using versioning namespace +{ + +logic_error::logic_error(const string& msg) +{ + __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; + ::new(&s) __libcpp_nmstr(msg.c_str()); +} + +logic_error::logic_error(const char* msg) +{ + __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; + ::new(&s) __libcpp_nmstr(msg); +} + +logic_error::logic_error(const logic_error& le) throw() +{ + __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; + ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); +} + +logic_error& +logic_error::operator=(const logic_error& le) throw() +{ + __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; + const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; + s1 = s2; + return *this; +} + +logic_error::~logic_error() throw() +{ + __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; + s.~__libcpp_nmstr(); +} + +const char* +logic_error::what() const throw() +{ + __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; + return s.c_str(); +} + +runtime_error::runtime_error(const string& msg) +{ + __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; + ::new(&s) __libcpp_nmstr(msg.c_str()); +} + +runtime_error::runtime_error(const char* msg) +{ + __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; + ::new(&s) __libcpp_nmstr(msg); +} + +runtime_error::runtime_error(const runtime_error& le) throw() +{ + __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; + ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); +} + +runtime_error& +runtime_error::operator=(const runtime_error& le) throw() +{ + __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; + const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; + s1 = s2; + return *this; +} + +runtime_error::~runtime_error() throw() +{ + __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; + s.~__libcpp_nmstr(); +} + +const char* +runtime_error::what() const throw() +{ + __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; + return s.c_str(); +} + +domain_error::~domain_error() throw() {} +invalid_argument::~invalid_argument() throw() {} +length_error::~length_error() throw() {} +out_of_range::~out_of_range() throw() {} + +range_error::~range_error() throw() {} +overflow_error::~overflow_error() throw() {} +underflow_error::~underflow_error() throw() {} + +} // std diff --git a/libcxx/src/strstream.cpp b/libcxx/src/strstream.cpp new file mode 100644 index 00000000000..d3d257e1ffe --- /dev/null +++ b/libcxx/src/strstream.cpp @@ -0,0 +1,363 @@ +//===------------------------ strstream.cpp -------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "strstream" +#include "algorithm" +#include "climits" +#include "cstring" + +_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 = 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((char*)__gnext, __n, nullptr); +} + +strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg) + : __strmode_(), + __alsize_(__default_alsize), + __palloc_(nullptr), + __pfree_(nullptr) +{ + __init((char*)__gnext, __n, (char*)__pbeg); +} + +strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n) + : __strmode_(__constant), + __alsize_(__default_alsize), + __palloc_(nullptr), + __pfree_(nullptr) +{ + __init((char*)__gnext, __n, nullptr); +} + +strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg) + : __strmode_(), + __alsize_(__default_alsize), + __palloc_(nullptr), + __pfree_(nullptr) +{ + __init((char*)__gnext, __n, (char*)__pbeg); +} + +strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n) + : __strmode_(__constant), + __alsize_(__default_alsize), + __palloc_(nullptr), + __pfree_(nullptr) +{ + __init((char*)__gnext, __n, nullptr); +} + +#ifdef _LIBCPP_MOVE + +strstreambuf::strstreambuf(strstreambuf&& __rhs) + : streambuf(__rhs), + __strmode_(__rhs.__strmode_), + __alsize_(__rhs.__alsize_), + __palloc_(__rhs.__palloc_), + __pfree_(__rhs.__pfree_) +{ + __rhs.setg(nullptr, nullptr, nullptr); + __rhs.setp(nullptr, nullptr); +} + +strstreambuf& +strstreambuf::operator=(strstreambuf&& __rhs) +{ + if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0) + { + if (__pfree_) + __pfree_(eback()); + else + delete [] eback(); + } + streambuf::operator=(__rhs); + __strmode_ = __rhs.__strmode_; + __alsize_ = __rhs.__alsize_; + __palloc_ = __rhs.__palloc_; + __pfree_ = __rhs.__pfree_; + __rhs.setg(nullptr, nullptr, nullptr); + __rhs.setp(nullptr, nullptr); +} + +#endif + +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); + _STD::swap(__strmode_, __rhs.__strmode_); + _STD::swap(__alsize_, __rhs.__alsize_); + _STD::swap(__palloc_, __rhs.__palloc_); + _STD::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); + streamsize old_size = (epptr() ? epptr() : egptr()) - eback(); + streamsize new_size = max<streamsize>(__alsize_, 2*old_size); + 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); + memcpy(buf, eback(), old_size); + ptrdiff_t ninp = gptr() - eback(); + ptrdiff_t einp = egptr() - eback(); + ptrdiff_t nout = pptr() - pbase(); + ptrdiff_t eout = epptr() - pbase(); + if (__strmode_ & __allocated) + { + if (__pfree_) + __pfree_(eback()); + else + delete [] eback(); + } + setg(buf, buf + ninp, buf + einp); + setp(buf + einp, buf + einp + eout); + pbump(nout); + __strmode_ |= __allocated; + } + *pptr() = static_cast<char>(__c); + pbump(1); + return int_type((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((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; + bool pos_out = __which & ios::out; + 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; + } + newoff += __off; + if (0 <= newoff && newoff <= seekhigh - eback()) + { + char* newpos = eback() + newoff; + if (pos_in) + setg(eback(), newpos, max(newpos, egptr())); + if (pos_out) + { + // min(pbase, newpos), newpos, epptr() + __off = epptr() - newpos; + setp(min(pbase(), newpos), epptr()); + pbump(static_cast<int>((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; + bool pos_out = __which & ios::out; + 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, max(newpos, egptr())); + if (pos_out) + { + // min(pbase, newpos), newpos, epptr() + off_type temp = epptr() - newpos; + setp(min(pbase(), newpos), epptr()); + pbump(static_cast<int>((epptr() - pbase()) - temp)); + } + __p = newoff; + } + } + } + return pos_type(__p); +} + +istrstream::~istrstream() +{ +} + +ostrstream::~ostrstream() +{ +} + +strstream::~strstream() +{ +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/system_error.cpp b/libcxx/src/system_error.cpp new file mode 100644 index 00000000000..aa870e45c15 --- /dev/null +++ b/libcxx/src/system_error.cpp @@ -0,0 +1,193 @@ +//===---------------------- system_error.cpp ------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "system_error" +#include "string" +#include "cstring" + +_LIBCPP_BEGIN_NAMESPACE_STD + +// class error_category + +error_category::error_category() +{ +} + +error_category::~error_category() +{ +} + +error_condition +error_category::default_error_condition(int ev) const +{ + return error_condition(ev, *this); +} + +bool +error_category::equivalent(int code, const error_condition& condition) const +{ + return default_error_condition(code) == condition; +} + +bool +error_category::equivalent(const error_code& code, int condition) const +{ + return *this == code.category() && code.value() == condition; +} + +string +__do_message::message(int ev) const +{ + return string(strerror(ev)); +} + +class _LIBCPP_HIDDEN __generic_error_category + : public __do_message +{ +public: + virtual const char* name() const; + virtual string message(int ev) const; +}; + +const char* +__generic_error_category::name() const +{ + return "generic"; +} + +string +__generic_error_category::message(int ev) const +{ + if (ev <= ELAST) + return __do_message::message(ev); + return string("unspecified generic_category error"); +} + +const error_category& +generic_category() +{ + static __generic_error_category s; + return s; +} + +class _LIBCPP_HIDDEN __system_error_category + : public __do_message +{ +public: + virtual const char* name() const; + virtual string message(int ev) const; + virtual error_condition default_error_condition(int ev) const; +}; + +const char* +__system_error_category::name() const +{ + return "system"; +} + +string +__system_error_category::message(int ev) const +{ + if (ev <= ELAST) + return __do_message::message(ev); + return string("unspecified system_category error"); +} + +error_condition +__system_error_category::default_error_condition(int ev) const +{ + if (ev <= ELAST) + return error_condition(ev, generic_category()); + return error_condition(ev, system_category()); +} + +const error_category& +system_category() +{ + 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 _STD::move(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() throw() +{ +} + +void +__throw_system_error(int ev, const char* what_arg) +{ + throw system_error(error_code(ev, system_category()), what_arg); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/thread.cpp b/libcxx/src/thread.cpp new file mode 100644 index 00000000000..ce391877f60 --- /dev/null +++ b/libcxx/src/thread.cpp @@ -0,0 +1,73 @@ +//===------------------------- thread.cpp----------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "thread" +#include "exception" +#include <sys/sysctl.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +thread::~thread() +{ + if (__t_ != nullptr) + terminate(); +} + +void +thread::join() +{ + int ec = pthread_join(__t_, 0); + if (ec) + throw system_error(error_code(ec, system_category()), "thread::join failed"); + __t_ = nullptr; +} + +void +thread::detach() +{ + int ec = EINVAL; + if (__t_ != 0) + { + ec = pthread_detach(__t_); + if (ec == 0) + __t_ = 0; + } + if (ec) + throw system_error(error_code(ec, system_category()), "thread::detach failed"); +} + +unsigned +thread::hardware_concurrency() +{ + int n; + int mib[2] = {CTL_HW, HW_NCPU}; + std::size_t s = sizeof(n); + sysctl(mib, 2, &n, &s, 0, 0); + return n; +} + +namespace this_thread +{ + +void +sleep_for(const chrono::nanoseconds& ns) +{ + using namespace chrono; + if (ns >= nanoseconds::zero()) + { + timespec ts; + ts.tv_sec = static_cast<decltype(ts.tv_sec)>(duration_cast<seconds>(ns).count()); + ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns - seconds(ts.tv_sec)).count()); + nanosleep(&ts, 0); + } +} + +} // this_thread + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/utility.cpp b/libcxx/src/utility.cpp new file mode 100644 index 00000000000..81689b3252e --- /dev/null +++ b/libcxx/src/utility.cpp @@ -0,0 +1,16 @@ +//===------------------------ utility.cpp ---------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "utility" + +_LIBCPP_BEGIN_NAMESPACE_STD + +const piecewise_construct_t piecewise_construct = {}; + +_LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/src/valarray.cpp b/libcxx/src/valarray.cpp new file mode 100644 index 00000000000..ff3406f749b --- /dev/null +++ b/libcxx/src/valarray.cpp @@ -0,0 +1,54 @@ +//===------------------------ valarray.cpp --------------------------------===// +// +// ΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚΚThe LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "valarray" + +_LIBCPP_BEGIN_NAMESPACE_STD + +template valarray<size_t>::valarray(size_t); +template valarray<size_t>::~valarray(); +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 |