diff options
Diffstat (limited to 'contrib/libc++/src')
26 files changed, 11231 insertions, 0 deletions
diff --git a/contrib/libc++/src/algorithm.cpp b/contrib/libc++/src/algorithm.cpp new file mode 100644 index 000000000000..6d5cf7c0bc81 --- /dev/null +++ b/contrib/libc++/src/algorithm.cpp @@ -0,0 +1,83 @@ +//===----------------------- algorithm.cpp --------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "algorithm" +#include "random" +#include "mutex" + +_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>&); + +static pthread_mutex_t __rs_mut = PTHREAD_MUTEX_INITIALIZER; +unsigned __rs_default::__c_ = 0; + +__rs_default::__rs_default() +{ +    pthread_mutex_lock(&__rs_mut); +    __c_ = 1; +} + +__rs_default::__rs_default(const __rs_default&) +{ +    ++__c_; +} + +__rs_default::~__rs_default() +{ +    if (--__c_ == 0) +        pthread_mutex_unlock(&__rs_mut); +} + +__rs_default::result_type +__rs_default::operator()() +{ +    static mt19937 __rs_g; +    return __rs_g(); +} + +__rs_default +__rs_get() +{ +    return __rs_default(); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/bind.cpp b/contrib/libc++/src/bind.cpp new file mode 100644 index 000000000000..cab0b7c03a91 --- /dev/null +++ b/contrib/libc++/src/bind.cpp @@ -0,0 +1,30 @@ +//===-------------------------- bind.cpp ----------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. 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/contrib/libc++/src/chrono.cpp b/contrib/libc++/src/chrono.cpp new file mode 100644 index 000000000000..73c83ee084e9 --- /dev/null +++ b/contrib/libc++/src/chrono.cpp @@ -0,0 +1,128 @@ +//===------------------------- chrono.cpp ---------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "chrono" +#include <sys/time.h>        //for gettimeofday and timeval +#if __APPLE__ +#include <mach/mach_time.h>  // mach_absolute_time, mach_timebase_info_data_t +#else  /* !__APPLE__ */ +#include <cerrno>  // errno +#include <system_error>  // __throw_system_error +#include <time.h>  // clock_gettime, CLOCK_MONOTONIC +#endif  // __APPLE__ + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace chrono +{ + +// system_clock + +system_clock::time_point +system_clock::now() _NOEXCEPT +{ +    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) _NOEXCEPT +{ +    return time_t(duration_cast<seconds>(t.time_since_epoch()).count()); +} + +system_clock::time_point +system_clock::from_time_t(time_t t) _NOEXCEPT +{ +    return system_clock::time_point(seconds(t)); +} + +// steady_clock + +#if __APPLE__ +//   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 +steady_clock::rep +steady_simplified() +{ +    return static_cast<steady_clock::rep>(mach_absolute_time()); +} + +static +double +compute_steady_factor() +{ +    mach_timebase_info_data_t MachInfo; +    mach_timebase_info(&MachInfo); +    return static_cast<double>(MachInfo.numer) / MachInfo.denom; +} + +static +steady_clock::rep +steady_full() +{ +    static const double factor = compute_steady_factor(); +    return static_cast<steady_clock::rep>(mach_absolute_time() * factor); +} + +typedef steady_clock::rep (*FP)(); + +static +FP +init_steady_clock() +{ +    mach_timebase_info_data_t MachInfo; +    mach_timebase_info(&MachInfo); +    if (MachInfo.numer == MachInfo.denom) +        return &steady_simplified; +    return &steady_full; +} + +#pragma GCC visibility pop + +steady_clock::time_point +steady_clock::now() _NOEXCEPT +{ +    static FP fp = init_steady_clock(); +    return time_point(duration(fp())); +} + +#else  // __APPLE__ +// FIXME: We assume that clock_gettime(CLOCK_MONOTONIC) works on +// non-apple systems.  Instead, we should check _POSIX_TIMERS and +// _POSIX_MONOTONIC_CLOCK and fall back to something else if those +// don't exist. + +// Warning:  If this is not truly steady, then it is non-conforming.  It is +//  better for it to not exist and have the rest of libc++ use system_clock +//  instead. + +steady_clock::time_point +steady_clock::now() _NOEXCEPT +{ +    struct timespec tp; +    if (0 != clock_gettime(CLOCK_MONOTONIC, &tp)) +        __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed"); +    return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec)); +} +#endif  // __APPLE__ + +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/condition_variable.cpp b/contrib/libc++/src/condition_variable.cpp new file mode 100644 index 000000000000..b53b836bfe7f --- /dev/null +++ b/contrib/libc++/src/condition_variable.cpp @@ -0,0 +1,69 @@ +//===-------------------- condition_variable.cpp --------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "condition_variable" +#include "thread" +#include "system_error" +#include "cassert" + +_LIBCPP_BEGIN_NAMESPACE_STD + +condition_variable::~condition_variable() +{ +    pthread_cond_destroy(&__cv_); +} + +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"); +} + +void +notify_all_at_thread_exit(condition_variable& cond, unique_lock<mutex> lk) +{ +    __thread_local_data()->notify_all_at_thread_exit(&cond, lk.release()); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/debug.cpp b/contrib/libc++/src/debug.cpp new file mode 100644 index 000000000000..406b247b7fec --- /dev/null +++ b/contrib/libc++/src/debug.cpp @@ -0,0 +1,484 @@ +//===-------------------------- debug.cpp ---------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define _LIBCPP_DEBUG2 1 +#include "__config" +#include "__debug" +#include "functional" +#include "algorithm" +#include "__hash_table" +#include "mutex" + +_LIBCPP_BEGIN_NAMESPACE_STD + +_LIBCPP_VISIBLE +__libcpp_db* +__get_db() +{ +    static __libcpp_db db; +    return &db; +}; + +_LIBCPP_VISIBLE +const __libcpp_db* +__get_const_db() +{ +    return __get_db(); +} + +namespace +{ + +typedef mutex mutex_type; +typedef lock_guard<mutex_type> WLock; +typedef lock_guard<mutex_type> RLock; + +mutex_type& +mut() +{ +    static mutex_type m; +    return m; +} + +}  // unnamed namespace + +__i_node::~__i_node() +{ +    if (__next_) +    { +        __next_->~__i_node(); +        free(__next_); +    } +} + +__c_node::~__c_node() +{ +    free(beg_); +    if (__next_) +    { +        __next_->~__c_node(); +        free(__next_); +    } +} + +__libcpp_db::__libcpp_db() +    : __cbeg_(nullptr), +      __cend_(nullptr), +      __csz_(0), +      __ibeg_(nullptr), +      __iend_(nullptr), +      __isz_(0) +{ +} + +__libcpp_db::~__libcpp_db() +{ +    if (__cbeg_) +    { +        for (__c_node** p = __cbeg_; p != __cend_; ++p) +        { +            if (*p != nullptr) +            { +                (*p)->~__c_node(); +                free(*p); +            } +        } +        free(__cbeg_); +    } +    if (__ibeg_) +    { +        for (__i_node** p = __ibeg_; p != __iend_; ++p) +        { +            if (*p != nullptr) +            { +                (*p)->~__i_node(); +                free(*p); +            } +        } +        free(__ibeg_); +    } +} + +void* +__libcpp_db::__find_c_from_i(void* __i) const +{ +    RLock _(mut()); +    __i_node* i = __find_iterator(__i); +    _LIBCPP_ASSERT(i != nullptr, "iterator constructed in translation unit with debug mode not enabled." +                   "  #define _LIBCPP_DEBUG2 1 for that translation unit."); +    return i->__c_ != nullptr ? i->__c_->__c_ : nullptr; +} + +void +__libcpp_db::__insert_ic(void* __i, const void* __c) +{ +    WLock _(mut()); +    __i_node* i = __insert_iterator(__i); +    const char* errmsg = +        "Container constructed in a translation unit with debug mode disabled." +        " But it is being used in a translation unit with debug mode enabled." +        " Enable it in the other translation unit with #define _LIBCPP_DEBUG2 1"; +    _LIBCPP_ASSERT(__cbeg_ != __cend_, errmsg); +    size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); +    __c_node* c = __cbeg_[hc]; +    _LIBCPP_ASSERT(c != nullptr, errmsg); +    while (c->__c_ != __c) +    { +        c = c->__next_; +        _LIBCPP_ASSERT(c != nullptr, errmsg); +    } +    c->__add(i); +    i->__c_ = c; +} + +__c_node* +__libcpp_db::__insert_c(void* __c) +{ +    WLock _(mut()); +    if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_)) +    { +        size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1); +        __c_node** cbeg = (__c_node**)calloc(nc, sizeof(void*)); +        if (cbeg == nullptr) +            throw bad_alloc(); +        for (__c_node** p = __cbeg_; p != __cend_; ++p) +        { +            __c_node* q = *p; +            while (q != nullptr) +            { +                size_t h = hash<void*>()(q->__c_) % nc; +                __c_node* r = q->__next_; +                q->__next_ = cbeg[h]; +                cbeg[h] = q; +                q = r; +            } +        } +        free(__cbeg_); +        __cbeg_ = cbeg; +        __cend_ = __cbeg_ + nc; +    } +    size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); +    __c_node* p = __cbeg_[hc]; +    __c_node* r = __cbeg_[hc] = (__c_node*)malloc(sizeof(__c_node)); +    if (__cbeg_[hc] == nullptr) +        throw bad_alloc(); +    r->__c_ = __c; +    r->__next_ = p; +    ++__csz_; +    return r; +} + +void +__libcpp_db::__erase_i(void* __i) +{ +    WLock _(mut()); +    if (__ibeg_ != __iend_) +    { +        size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); +        __i_node* p = __ibeg_[hi]; +        if (p != nullptr) +        { +            __i_node* q = nullptr; +            while (p->__i_ != __i) +            { +                q = p; +                p = p->__next_; +                if (p == nullptr) +                    return; +            } +            if (q == nullptr) +                __ibeg_[hi] = p->__next_; +            else +                q->__next_ = p->__next_; +            __c_node* c = p->__c_; +            free(p); +            --__isz_; +            if (c != nullptr) +                c->__remove(p); +        } +    } +} + +void +__libcpp_db::__invalidate_all(void* __c) +{ +    WLock _(mut()); +    size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); +    __c_node* p = __cbeg_[hc]; +    _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __invalidate_all A"); +    while (p->__c_ != __c) +    { +        p = p->__next_; +        _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __invalidate_all B"); +    } +    while (p->end_ != p->beg_) +    { +        --p->end_; +        (*p->end_)->__c_ = nullptr; +    } +} + +__c_node* +__libcpp_db::__find_c_and_lock(void* __c) const +{ +    mut().lock(); +    size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); +    __c_node* p = __cbeg_[hc]; +    _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c_and_lock A"); +    while (p->__c_ != __c) +    { +        p = p->__next_; +        _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c_and_lock B"); +    } +    return p; +} + +__c_node* +__libcpp_db::__find_c(void* __c) const +{ +    size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); +    __c_node* p = __cbeg_[hc]; +    _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A"); +    while (p->__c_ != __c) +    { +        p = p->__next_; +        _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B"); +    } +    return p; +} + +void +__libcpp_db::unlock() const +{ +    mut().unlock(); +} + +void +__libcpp_db::__erase_c(void* __c) +{ +    WLock _(mut()); +    size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); +    __c_node* p = __cbeg_[hc]; +    __c_node* q = nullptr; +    _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A"); +    while (p->__c_ != __c) +    { +        q = p; +        p = p->__next_; +        _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B"); +    } +    if (q == nullptr) +        __cbeg_[hc] = p->__next_; +    else +        q->__next_ = p->__next_; +    while (p->end_ != p->beg_) +    { +        --p->end_; +        (*p->end_)->__c_ = nullptr; +    } +    free(p->beg_); +    free(p); +    --__csz_; +} + +void +__libcpp_db::__iterator_copy(void* __i, const void* __i0) +{ +    WLock _(mut()); +    __i_node* i = __find_iterator(__i); +    __i_node* i0 = __find_iterator(__i0); +    __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr; +    if (i == nullptr && c0 != nullptr) +        i = __insert_iterator(__i); +    __c_node* c = i != nullptr ? i->__c_ : nullptr; +    if (c != c0) +    { +        if (c != nullptr) +            c->__remove(i); +        if (i != nullptr) +        { +            i->__c_ = nullptr; +            if (c0 != nullptr) +            { +                i->__c_ = c0; +                i->__c_->__add(i); +            } +        } +    } +} + +bool +__libcpp_db::__dereferenceable(const void* __i) const +{ +    RLock _(mut()); +    __i_node* i = __find_iterator(__i); +    return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i); +} + +bool +__libcpp_db::__decrementable(const void* __i) const +{ +    RLock _(mut()); +    __i_node* i = __find_iterator(__i); +    return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i); +} + +bool +__libcpp_db::__addable(const void* __i, ptrdiff_t __n) const +{ +    RLock _(mut()); +    __i_node* i = __find_iterator(__i); +    return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n); +} + +bool +__libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const +{ +    RLock _(mut()); +    __i_node* i = __find_iterator(__i); +    return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n); +} + +bool +__libcpp_db::__comparable(const void* __i, const void* __j) const +{ +    RLock _(mut()); +    __i_node* i = __find_iterator(__i); +    __i_node* j = __find_iterator(__j); +    __c_node* ci = i != nullptr ? i->__c_ : nullptr; +    __c_node* cj = j != nullptr ? j->__c_ : nullptr; +    return ci != nullptr && ci == cj; +} + +void +__libcpp_db::swap(void* c1, void* c2) +{ +    WLock _(mut()); +    size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_); +    __c_node* p1 = __cbeg_[hc]; +    _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A"); +    while (p1->__c_ != c1) +    { +        p1 = p1->__next_; +        _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B"); +    } +    hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_); +    __c_node* p2 = __cbeg_[hc]; +    _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C"); +    while (p2->__c_ != c2) +    { +        p2 = p2->__next_; +        _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D"); +    } +    std::swap(p1->beg_, p2->beg_); +    std::swap(p1->end_, p2->end_); +    std::swap(p1->cap_, p2->cap_); +    for (__i_node** p = p1->beg_; p != p1->end_; ++p) +        (*p)->__c_ = p1; +    for (__i_node** p = p2->beg_; p != p2->end_; ++p) +        (*p)->__c_ = p2; +} + +void +__libcpp_db::__insert_i(void* __i) +{ +    WLock _(mut()); +    __insert_iterator(__i); +} + +void +__c_node::__add(__i_node* i) +{ +    if (end_ == cap_) +    { +        size_t nc = 2*static_cast<size_t>(cap_ - beg_); +        if (nc == 0) +            nc = 1; +        __i_node** beg = (__i_node**)malloc(nc * sizeof(__i_node*)); +        if (beg == nullptr) +            throw bad_alloc(); +        if (nc > 1) +            memcpy(beg, beg_, nc/2*sizeof(__i_node*)); +        free(beg_); +        beg_ = beg; +        end_ = beg_ + nc/2; +        cap_ = beg_ + nc; +    } +    *end_++ = i; +} + +// private api + +_LIBCPP_HIDDEN +__i_node* +__libcpp_db::__insert_iterator(void* __i) +{ +    if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_)) +    { +        size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1); +        __i_node** ibeg = (__i_node**)calloc(nc, sizeof(void*)); +        if (ibeg == nullptr) +            throw bad_alloc(); +        for (__i_node** p = __ibeg_; p != __iend_; ++p) +        { +            __i_node* q = *p; +            while (q != nullptr) +            { +                size_t h = hash<void*>()(q->__i_) % nc; +                __i_node* r = q->__next_; +                q->__next_ = ibeg[h]; +                ibeg[h] = q; +                q = r; +            } +        } +        free(__ibeg_); +        __ibeg_ = ibeg; +        __iend_ = __ibeg_ + nc; +    } +    size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); +    __i_node* p = __ibeg_[hi]; +    __i_node* r = __ibeg_[hi] = (__i_node*)malloc(sizeof(__i_node)); +    if (r == nullptr) +        throw bad_alloc(); +    ::new(r) __i_node(__i, p, nullptr); +    ++__isz_; +    return r; +} + +_LIBCPP_HIDDEN +__i_node* +__libcpp_db::__find_iterator(const void* __i) const +{ +    __i_node* r = nullptr; +    if (__ibeg_ != __iend_) +    { +        size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); +        for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_) +        { +            if (nd->__i_ == __i) +            { +                r = nd; +                break; +            } +        } +    } +    return r; +} + +_LIBCPP_HIDDEN +void +__c_node::__remove(__i_node* p) +{ +    __i_node** r = find(beg_, end_, p); +    _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove"); +    if (--end_ != r) +        memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*)); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/exception.cpp b/contrib/libc++/src/exception.cpp new file mode 100644 index 000000000000..6b5e6984a606 --- /dev/null +++ b/contrib/libc++/src/exception.cpp @@ -0,0 +1,217 @@ +//===------------------------ exception.cpp -------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdlib.h> + +#include "exception" + +#if __APPLE__ +  #include <cxxabi.h> + +  using namespace __cxxabiv1; +  #define HAVE_DEPENDENT_EH_ABI 1 +  #ifndef _LIBCPPABI_VERSION +    using namespace __cxxabiapple; +    // On Darwin, there are two STL shared libraries and a lower level ABI +    // shared libray.  The globals holding the current terminate handler and +    // current unexpected handler are in the ABI library. +    #define __terminate_handler  __cxxabiapple::__cxa_terminate_handler +    #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler +  #endif  // _LIBCPPABI_VERSION +#elif defined(LIBCXXRT) +  #include <cxxabi.h> +  using namespace __cxxabiv1; +  #define HAVE_DEPENDENT_EH_ABI 1 +#else  // __APPLE__ +  static std::terminate_handler  __terminate_handler; +  static std::unexpected_handler __unexpected_handler; +#endif  // __APPLE__ + +namespace std +{ + +#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) + +// libcxxrt provides implementations of these functions itself. +unexpected_handler +set_unexpected(unexpected_handler func) _NOEXCEPT +{ +    return __sync_lock_test_and_set(&__unexpected_handler, func); +} + +unexpected_handler +get_unexpected() _NOEXCEPT +{ +    return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0); +} + +_ATTRIBUTE(noreturn) +void +unexpected() +{ +    (*get_unexpected())(); +    // unexpected handler should not return +    terminate(); +} + +terminate_handler +set_terminate(terminate_handler func) _NOEXCEPT +{ +    return __sync_lock_test_and_set(&__terminate_handler, func); +} + +terminate_handler +get_terminate() _NOEXCEPT +{ +    return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0); +} + +_ATTRIBUTE(noreturn) +void +terminate() _NOEXCEPT +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    try +    { +#endif  // _LIBCPP_NO_EXCEPTIONS +        (*get_terminate())(); +        // handler should not return +        ::abort (); +#ifndef _LIBCPP_NO_EXCEPTIONS +    } +    catch (...) +    { +        // handler should not throw exception +        ::abort (); +    } +#endif  // _LIBCPP_NO_EXCEPTIONS +} +#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) + +#ifndef LIBCXXRT +bool uncaught_exception() _NOEXCEPT +{ +#if __APPLE__ +    // on Darwin, there is a helper function so __cxa_get_globals is private +    return __cxa_uncaught_exception(); +#elif LIBCXXRT +    __cxa_eh_globals * globals = __cxa_get_globals(); +    return (globals->uncaughtExceptions != 0); +#else  // __APPLE__ +    #warning uncaught_exception not yet implemented +    ::abort(); +#endif  // __APPLE__ +} + +#ifndef _LIBCPPABI_VERSION + +exception::~exception() _NOEXCEPT +{ +} + +bad_exception::~bad_exception() _NOEXCEPT +{ +} + +const char* exception::what() const _NOEXCEPT +{ +  return "std::exception"; +} + +const char* bad_exception::what() const _NOEXCEPT +{ +  return "std::bad_exception"; +} + +#endif  // _LIBCPPABI_VERSION +#endif //LIBCXXRT + +exception_ptr::~exception_ptr() _NOEXCEPT +{ +#if HAVE_DEPENDENT_EH_ABI +    __cxa_decrement_exception_refcount(__ptr_); +#else +    #warning exception_ptr not yet implemented +    ::abort(); +#endif  // __APPLE__ +} + +exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT +    : __ptr_(other.__ptr_) +{ +#if HAVE_DEPENDENT_EH_ABI +    __cxa_increment_exception_refcount(__ptr_); +#else +    #warning exception_ptr not yet implemented +    ::abort(); +#endif  // __APPLE__ +} + +exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT +{ +#if HAVE_DEPENDENT_EH_ABI +    if (__ptr_ != other.__ptr_) +    { +        __cxa_increment_exception_refcount(other.__ptr_); +        __cxa_decrement_exception_refcount(__ptr_); +        __ptr_ = other.__ptr_; +    } +    return *this; +#else  // __APPLE__ +    #warning exception_ptr not yet implemented +    ::abort(); +#endif  // __APPLE__ +} + +nested_exception::nested_exception() _NOEXCEPT +    : __ptr_(current_exception()) +{ +} + +nested_exception::~nested_exception() _NOEXCEPT +{ +} + +_ATTRIBUTE(noreturn) +void +nested_exception::rethrow_nested() const +{ +    if (__ptr_ == nullptr) +        terminate(); +    rethrow_exception(__ptr_); +} + + +exception_ptr current_exception() _NOEXCEPT +{ +#if HAVE_DEPENDENT_EH_ABI +    // be nicer if there was a constructor that took a ptr, then +    // this whole function would be just: +    //    return exception_ptr(__cxa_current_primary_exception()); +    exception_ptr ptr; +    ptr.__ptr_ = __cxa_current_primary_exception(); +    return ptr; +#else  // __APPLE__ +    #warning exception_ptr not yet implemented +    ::abort(); +#endif  // __APPLE__ +} + +_ATTRIBUTE(noreturn) +void rethrow_exception(exception_ptr p) +{ +#if HAVE_DEPENDENT_EH_ABI +    __cxa_rethrow_primary_exception(p.__ptr_); +    // if p.__ptr_ is NULL, above returns so we terminate +    terminate(); +#else  // __APPLE__ +    #warning exception_ptr not yet implemented +    ::abort(); +#endif  // __APPLE__ +} +} // std diff --git a/contrib/libc++/src/future.cpp b/contrib/libc++/src/future.cpp new file mode 100644 index 000000000000..29357112df98 --- /dev/null +++ b/contrib/libc++/src/future.cpp @@ -0,0 +1,285 @@ +//===------------------------- future.cpp ---------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "future" +#include "string" + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_HIDDEN __future_error_category +    : public __do_message +{ +public: +    virtual const char* name() const _NOEXCEPT; +    virtual string message(int ev) const; +}; + +const char* +__future_error_category::name() const _NOEXCEPT +{ +    return "future"; +} + +string +__future_error_category::message(int ev) const +{ +    switch (static_cast<future_errc>(ev)) +    { +    case future_errc::broken_promise: +        return string("The associated promise has been destructed prior " +                      "to the associated state becoming ready."); +    case future_errc::future_already_retrieved: +        return string("The future has already been retrieved from " +                      "the promise or packaged_task."); +    case future_errc::promise_already_satisfied: +        return string("The state of the promise has already been set."); +    case future_errc::no_state: +        return string("Operation not permitted on an object without " +                      "an associated state."); +    } +    return string("unspecified future_errc value\n"); +} + +const error_category& +future_category() +{ +    static __future_error_category __f; +    return __f; +} + +future_error::future_error(error_code __ec) +    : logic_error(__ec.message()), +      __ec_(__ec) +{ +} + +future_error::~future_error() _NOEXCEPT +{ +} + +void +__assoc_sub_state::__on_zero_shared() _NOEXCEPT +{ +    delete this; +} + +void +__assoc_sub_state::set_value() +{ +    unique_lock<mutex> __lk(__mut_); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__has_value()) +        throw future_error(make_error_code(future_errc::promise_already_satisfied)); +#endif +    __state_ |= __constructed | ready; +    __lk.unlock(); +    __cv_.notify_all(); +} + +void +__assoc_sub_state::set_value_at_thread_exit() +{ +    unique_lock<mutex> __lk(__mut_); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__has_value()) +        throw future_error(make_error_code(future_errc::promise_already_satisfied)); +#endif +    __state_ |= __constructed; +    __thread_local_data()->__make_ready_at_thread_exit(this); +    __lk.unlock(); +} + +void +__assoc_sub_state::set_exception(exception_ptr __p) +{ +    unique_lock<mutex> __lk(__mut_); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__has_value()) +        throw future_error(make_error_code(future_errc::promise_already_satisfied)); +#endif +    __exception_ = __p; +    __state_ |= ready; +    __lk.unlock(); +    __cv_.notify_all(); +} + +void +__assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) +{ +    unique_lock<mutex> __lk(__mut_); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__has_value()) +        throw future_error(make_error_code(future_errc::promise_already_satisfied)); +#endif +    __exception_ = __p; +    __thread_local_data()->__make_ready_at_thread_exit(this); +    __lk.unlock(); +} + +void +__assoc_sub_state::__make_ready() +{ +    unique_lock<mutex> __lk(__mut_); +    __state_ |= ready; +    __lk.unlock(); +    __cv_.notify_all(); +} + +void +__assoc_sub_state::copy() +{ +    unique_lock<mutex> __lk(__mut_); +    __sub_wait(__lk); +    if (__exception_ != nullptr) +        rethrow_exception(__exception_); +} + +void +__assoc_sub_state::wait() +{ +    unique_lock<mutex> __lk(__mut_); +    __sub_wait(__lk); +} + +void +__assoc_sub_state::__sub_wait(unique_lock<mutex>& __lk) +{ +    if (!__is_ready()) +    { +        if (__state_ & static_cast<unsigned>(deferred)) +        { +            __state_ &= ~static_cast<unsigned>(deferred); +            __lk.unlock(); +            __execute(); +        } +        else +            while (!__is_ready()) +                __cv_.wait(__lk); +    } +} + +void +__assoc_sub_state::__execute() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    throw future_error(make_error_code(future_errc::no_state)); +#endif +} + +future<void>::future(__assoc_sub_state* __state) +    : __state_(__state) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__state_->__has_future_attached()) +        throw future_error(make_error_code(future_errc::future_already_retrieved)); +#endif +    __state_->__add_shared(); +    __state_->__set_future_attached(); +} + +future<void>::~future() +{ +    if (__state_) +        __state_->__release_shared(); +} + +void +future<void>::get() +{ +    unique_ptr<__shared_count, __release_shared_count> __(__state_); +    __assoc_sub_state* __s = __state_; +    __state_ = nullptr; +    __s->copy(); +} + +promise<void>::promise() +    : __state_(new __assoc_sub_state) +{ +} + +promise<void>::~promise() +{ +    if (__state_) +    { +        if (!__state_->__has_value() && __state_->use_count() > 1) +            __state_->set_exception(make_exception_ptr( +                      future_error(make_error_code(future_errc::broken_promise)) +                                                      )); +        __state_->__release_shared(); +    } +} + +future<void> +promise<void>::get_future() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__state_ == nullptr) +        throw future_error(make_error_code(future_errc::no_state)); +#endif +    return future<void>(__state_); +} + +void +promise<void>::set_value() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__state_ == nullptr) +        throw future_error(make_error_code(future_errc::no_state)); +#endif +    __state_->set_value(); +} + +void +promise<void>::set_exception(exception_ptr __p) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__state_ == nullptr) +        throw future_error(make_error_code(future_errc::no_state)); +#endif +    __state_->set_exception(__p); +} + +void +promise<void>::set_value_at_thread_exit() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__state_ == nullptr) +        throw future_error(make_error_code(future_errc::no_state)); +#endif +    __state_->set_value_at_thread_exit(); +} + +void +promise<void>::set_exception_at_thread_exit(exception_ptr __p) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__state_ == nullptr) +        throw future_error(make_error_code(future_errc::no_state)); +#endif +    __state_->set_exception_at_thread_exit(__p); +} + +shared_future<void>::~shared_future() +{ +    if (__state_) +        __state_->__release_shared(); +} + +shared_future<void>& +shared_future<void>::operator=(const shared_future& __rhs) +{ +    if (__rhs.__state_) +        __rhs.__state_->__add_shared(); +    if (__state_) +        __state_->__release_shared(); +    __state_ = __rhs.__state_; +    return *this; +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/hash.cpp b/contrib/libc++/src/hash.cpp new file mode 100644 index 000000000000..6f30d5a60581 --- /dev/null +++ b/contrib/libc++/src/hash.cpp @@ -0,0 +1,560 @@ +//===-------------------------- hash.cpp ----------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "__hash_table" +#include "algorithm" +#include "stdexcept" + +_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. + +inline _LIBCPP_INLINE_VISIBILITY +void +__check_for_overflow(size_t N, integral_constant<size_t, 32>) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS  +    if (N > 0xFFFFFFFB) +        throw overflow_error("__next_prime overflow"); +#endif +} + +inline _LIBCPP_INLINE_VISIBILITY +void +__check_for_overflow(size_t N, integral_constant<size_t, 64>) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS  +    if (N > 0xFFFFFFFFFFFFFFC5ull) +        throw overflow_error("__next_prime overflow"); +#endif +} + +size_t +__next_prime(size_t n) +{ +    const size_t L = 210; +    const size_t N = sizeof(small_primes) / sizeof(small_primes[0]); +    // If n is small enough, search in small_primes +    if (n <= small_primes[N-1]) +        return *std::lower_bound(small_primes, small_primes + N, n); +    // Else n > largest small_primes +    // Check for overflow +    __check_for_overflow(n, integral_constant<size_t,  +                                                   sizeof(n) * __CHAR_BIT__>()); +    // Start searching list of potential primes: L * k0 + indices[in] +    const size_t M = sizeof(indices) / sizeof(indices[0]); +    // Select first potential prime >= n +    //   Known a-priori n >= L +    size_t k0 = n / L; +    size_t in = static_cast<size_t>(std::lower_bound(indices, indices + M, n - k0 * L) +                                    - indices); +    n = L * k0 + indices[in]; +    while (true) +    { +        // Divide n by all primes or potential primes (i) until: +        //    1.  The division is even, so try next potential prime. +        //    2.  The i > sqrt(n), in which case n is prime. +        // It is known a-priori that n is not divisible by 2, 3, 5 or 7, +        //    so don't test those (j == 5 ->  divide by 11 first).  And the +        //    potential primes start with 211, so don't test against the last +        //    small prime. +        for (size_t j = 5; j < N - 1; ++j) +        { +            const std::size_t p = small_primes[j]; +            const std::size_t q = n / p; +            if (q < p) +                return n; +            if (n == q * p) +                goto next; +        } +        // n wasn't divisible by small primes, try potential primes +        { +            size_t i = 211; +            while (true) +            { +                std::size_t q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 10; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 8; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 8; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 6; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 4; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 2; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                i += 10; +                q = n / i; +                if (q < i) +                    return n; +                if (n == q * i) +                    break; + +                // This will loop i to the next "plane" of potential primes +                i += 2; +            } +        } +next: +        // n is not prime.  Increment n to next potential prime. +        if (++in == M) +        { +            ++k0; +            in = 0; +        } +        n = L * k0 + indices[in]; +    } +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/ios.cpp b/contrib/libc++/src/ios.cpp new file mode 100644 index 000000000000..80917a046d2f --- /dev/null +++ b/contrib/libc++/src/ios.cpp @@ -0,0 +1,455 @@ +//===-------------------------- ios.cpp -----------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. 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_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 _NOEXCEPT; +    virtual string message(int ev) const; +}; + +const char* +__iostream_category::name() const _NOEXCEPT +{ +    return "iostream"; +} + +string +__iostream_category::message(int ev) const +{ +    if (ev != static_cast<int>(io_errc::stream) +#ifdef ELAST +        && ev <= ELAST +#endif +        ) +        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 = _VSTD::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 = _VSTD::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 = _VSTD::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; +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (((state | (__rdbuf_ ? goodbit : badbit)) & __exceptions_) != 0) +        throw failure("ios_base::clear"); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +// 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_)); +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (!new_callbacks) +            throw bad_alloc(); +#endif  // _LIBCPP_NO_EXCEPTIONS +        new_ints.reset((int*)malloc(sizeof(int) * rhs.__event_size_)); +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (!new_ints) +            throw bad_alloc(); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (__iarray_cap_ < rhs.__iarray_size_) +    { +        new_longs.reset((long*)malloc(sizeof(long) * rhs.__iarray_size_)); +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (!new_longs) +            throw bad_alloc(); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (__parray_cap_ < rhs.__parray_size_) +    { +        new_pointers.reset((void**)malloc(sizeof(void*) * rhs.__parray_size_)); +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (!new_pointers) +            throw bad_alloc(); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    // 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) +{ +    _VSTD::swap(__fmtflags_, rhs.__fmtflags_); +    _VSTD::swap(__precision_, rhs.__precision_); +    _VSTD::swap(__width_, rhs.__width_); +    _VSTD::swap(__rdstate_, rhs.__rdstate_); +    _VSTD::swap(__exceptions_, rhs.__exceptions_); +    locale& lhs_loc = *(locale*)&__loc_; +    locale& rhs_loc = *(locale*)&rhs.__loc_; +    _VSTD::swap(lhs_loc, rhs_loc); +    _VSTD::swap(__fn_, rhs.__fn_); +    _VSTD::swap(__index_, rhs.__index_); +    _VSTD::swap(__event_size_, rhs.__event_size_); +    _VSTD::swap(__event_cap_, rhs.__event_cap_); +    _VSTD::swap(__iarray_, rhs.__iarray_); +    _VSTD::swap(__iarray_size_, rhs.__iarray_size_); +    _VSTD::swap(__iarray_cap_, rhs.__iarray_cap_); +    _VSTD::swap(__parray_, rhs.__parray_); +    _VSTD::swap(__parray_size_, rhs.__parray_size_); +    _VSTD::swap(__parray_cap_, rhs.__parray_cap_); +} + +void +ios_base::__set_badbit_and_consider_rethrow() +{ +    __rdstate_ |= badbit; +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__exceptions_ & badbit) +        throw; +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +void +ios_base::__set_failbit_and_consider_rethrow() +{ +    __rdstate_ |= failbit; +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__exceptions_ & failbit) +        throw; +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +bool +ios_base::sync_with_stdio(bool sync) +{ +    static bool previous_state = true; +    bool r = previous_state; +    previous_state = sync; +    return r; +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/iostream.cpp b/contrib/libc++/src/iostream.cpp new file mode 100644 index 000000000000..157c3977d478 --- /dev/null +++ b/contrib/libc++/src/iostream.cpp @@ -0,0 +1,53 @@ +//===------------------------ iostream.cpp --------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. 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); +    _VSTD::unitbuf(cerr); +    cerr.tie(&cout); + +    wcin.tie(&wcout); +    _VSTD::unitbuf(wcerr); +    wcerr.tie(&wcout); +} + +ios_base::Init::~Init() +{ +    cout.flush(); +    clog.flush(); + +    wcout.flush(); +    wclog.flush(); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/locale.cpp b/contrib/libc++/src/locale.cpp new file mode 100644 index 000000000000..fe994881d462 --- /dev/null +++ b/contrib/libc++/src/locale.cpp @@ -0,0 +1,6017 @@ +//===------------------------- locale.cpp ---------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// On Solaris, we need to define something to make the C99 parts of localeconv +// visible. +#ifdef __sun__ +#define _LCONV_C99 +#endif + +#include "string" +#include "locale" +#include "codecvt" +#include "vector" +#include "algorithm" +#include "algorithm" +#include "typeinfo" +#include "type_traits" +#include "clocale" +#include "cstring" +#include "cwctype" +#include "__sso_allocator" +#if _WIN32 +#include <support/win32/locale_win32.h> +#else // _WIN32 +#include <langinfo.h> +#endif // _!WIN32 +#include <stdlib.h> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#ifdef __cloc_defined +locale_t __cloc() { +  // In theory this could create a race condition. In practice +  // the race condition is non-fatal since it will just create +  // a little resource leak. Better approach would be appreciated. +  static locale_t result = newlocale(LC_ALL_MASK, "C", 0); +  return result; +} +#endif // __cloc_defined + +namespace { + +struct release +{ +    void operator()(locale::facet* p) {p->__release_shared();} +}; + +template <class T, class 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; +} + +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" + +class _LIBCPP_HIDDEN locale::__imp +    : public facet +{ +    enum {N = 28}; +    vector<facet*, __sso_allocator<facet*, N> > facets_; +    string         name_; +public: +    explicit __imp(size_t refs = 0); +    explicit __imp(const string& name, size_t refs = 0); +    __imp(const __imp&); +    __imp(const __imp&, const string&, locale::category c); +    __imp(const __imp& other, const __imp& one, locale::category c); +    __imp(const __imp&, facet* f, long id); +    ~__imp(); + +    const string& name() const {return name_;} +    bool has_facet(long id) const +        {return static_cast<size_t>(id) < facets_.size() && facets_[static_cast<size_t>(id)];} +    const locale::facet* use_facet(long id) const; + +    static const locale& make_classic(); +    static       locale& make_global(); +private: +    void install(facet* f, long id); +    template <class F> void install(F* f) {install(f, f->id.__get());} +    template <class F> void install_from(const __imp& other); +}; + +#pragma clang diagnostic pop + +locale::__imp::__imp(size_t refs) +    : facet(refs), +      facets_(N), +      name_("C") +{ +    facets_.clear(); +    install(&make<_VSTD::collate<char> >(1u)); +    install(&make<_VSTD::collate<wchar_t> >(1u)); +    install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u)); +    install(&make<_VSTD::ctype<wchar_t> >(1u)); +    install(&make<codecvt<char, char, mbstate_t> >(1u)); +    install(&make<codecvt<wchar_t, char, mbstate_t> >(1u)); +    install(&make<codecvt<char16_t, char, mbstate_t> >(1u)); +    install(&make<codecvt<char32_t, char, mbstate_t> >(1u)); +    install(&make<numpunct<char> >(1u)); +    install(&make<numpunct<wchar_t> >(1u)); +    install(&make<num_get<char> >(1u)); +    install(&make<num_get<wchar_t> >(1u)); +    install(&make<num_put<char> >(1u)); +    install(&make<num_put<wchar_t> >(1u)); +    install(&make<moneypunct<char, false> >(1u)); +    install(&make<moneypunct<char, true> >(1u)); +    install(&make<moneypunct<wchar_t, false> >(1u)); +    install(&make<moneypunct<wchar_t, true> >(1u)); +    install(&make<money_get<char> >(1u)); +    install(&make<money_get<wchar_t> >(1u)); +    install(&make<money_put<char> >(1u)); +    install(&make<money_put<wchar_t> >(1u)); +    install(&make<time_get<char> >(1u)); +    install(&make<time_get<wchar_t> >(1u)); +    install(&make<time_put<char> >(1u)); +    install(&make<time_put<wchar_t> >(1u)); +    install(&make<_VSTD::messages<char> >(1u)); +    install(&make<_VSTD::messages<wchar_t> >(1u)); +} + +locale::__imp::__imp(const string& name, size_t refs) +    : facet(refs), +      facets_(N), +      name_(name) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    try +    { +#endif  // _LIBCPP_NO_EXCEPTIONS +        facets_ = locale::classic().__locale_->facets_; +        for (unsigned i = 0; i < facets_.size(); ++i) +            if (facets_[i]) +                facets_[i]->__add_shared(); +        install(new collate_byname<char>(name_)); +        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_)); +#ifndef _LIBCPP_NO_EXCEPTIONS +    } +    catch (...) +    { +        for (unsigned i = 0; i < facets_.size(); ++i) +            if (facets_[i]) +                facets_[i]->__release_shared(); +        throw; +    } +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +locale::__imp::__imp(const __imp& other) +    : facets_(max<size_t>(N, other.facets_.size())), +      name_(other.name_) +{ +    facets_ = other.facets_; +    for (unsigned i = 0; i < facets_.size(); ++i) +        if (facets_[i]) +            facets_[i]->__add_shared(); +} + +locale::__imp::__imp(const __imp& other, const string& name, locale::category c) +    : facets_(N), +      name_("*") +{ +    facets_ = other.facets_; +    for (unsigned i = 0; i < facets_.size(); ++i) +        if (facets_[i]) +            facets_[i]->__add_shared(); +#ifndef _LIBCPP_NO_EXCEPTIONS +    try +    { +#endif  // _LIBCPP_NO_EXCEPTIONS +        if (c & locale::collate) +        { +            install(new collate_byname<char>(name)); +            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)); +        } +#ifndef _LIBCPP_NO_EXCEPTIONS +    } +    catch (...) +    { +        for (unsigned i = 0; i < facets_.size(); ++i) +            if (facets_[i]) +                facets_[i]->__release_shared(); +        throw; +    } +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +template<class F> +inline +void +locale::__imp::install_from(const locale::__imp& one) +{ +    long id = F::id.__get(); +    install(const_cast<F*>(static_cast<const F*>(one.use_facet(id))), id); +} + +locale::__imp::__imp(const __imp& other, const __imp& one, locale::category c) +    : facets_(N), +      name_("*") +{ +    facets_ = other.facets_; +    for (unsigned i = 0; i < facets_.size(); ++i) +        if (facets_[i]) +            facets_[i]->__add_shared(); +#ifndef _LIBCPP_NO_EXCEPTIONS +    try +    { +#endif  // _LIBCPP_NO_EXCEPTIONS +        if (c & locale::collate) +        { +            install_from<_VSTD::collate<char> >(one); +            install_from<_VSTD::collate<wchar_t> >(one); +        } +        if (c & locale::ctype) +        { +            install_from<_VSTD::ctype<char> >(one); +            install_from<_VSTD::ctype<wchar_t> >(one); +            install_from<_VSTD::codecvt<char, char, mbstate_t> >(one); +            install_from<_VSTD::codecvt<char16_t, char, mbstate_t> >(one); +            install_from<_VSTD::codecvt<char32_t, char, mbstate_t> >(one); +            install_from<_VSTD::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<_VSTD::messages<char> >(one); +            install_from<_VSTD::messages<wchar_t> >(one); +        } +#ifndef _LIBCPP_NO_EXCEPTIONS +    } +    catch (...) +    { +        for (unsigned i = 0; i < facets_.size(); ++i) +            if (facets_[i]) +                facets_[i]->__release_shared(); +        throw; +    } +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +locale::__imp::__imp(const __imp& other, facet* f, long id) +    : facets_(max<size_t>(N, other.facets_.size()+1)), +      name_("*") +{ +    f->__add_shared(); +    unique_ptr<facet, release> hold(f); +    facets_ = other.facets_; +    for (unsigned i = 0; i < other.facets_.size(); ++i) +        if (facets_[i]) +            facets_[i]->__add_shared(); +    install(hold.get(), id); +} + +locale::__imp::~__imp() +{ +    for (unsigned i = 0; i < facets_.size(); ++i) +        if (facets_[i]) +            facets_[i]->__release_shared(); +} + +void +locale::__imp::install(facet* f, long id) +{ +    f->__add_shared(); +    unique_ptr<facet, release> hold(f); +    if (static_cast<size_t>(id) >= facets_.size()) +        facets_.resize(static_cast<size_t>(id+1)); +    if (facets_[static_cast<size_t>(id)]) +        facets_[static_cast<size_t>(id)]->__release_shared(); +    facets_[static_cast<size_t>(id)] = hold.release(); +} + +const locale::facet* +locale::__imp::use_facet(long id) const +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (!has_facet(id)) +        throw bad_cast(); +#endif  // _LIBCPP_NO_EXCEPTIONS +    return facets_[static_cast<size_t>(id)]; +} + +// locale + +const locale& +locale::__imp::make_classic() +{ +    // only one thread can get in here and it only gets in once +    static aligned_storage<sizeof(locale)>::type buf; +    locale* c = (locale*)&buf; +    c->__locale_ = &make<__imp>(1u); +    return *c; +} + +const locale& +locale::classic() +{ +    static const locale& c = __imp::make_classic(); +    return c; +} + +locale& +locale::__imp::make_global() +{ +    // only one thread can get in here and it only gets in once +    static aligned_storage<sizeof(locale)>::type buf; +    ::new (&buf) locale(locale::classic()); +    return *(locale*)&buf; +} + +locale& +locale::__global() +{ +    static locale& g = __imp::make_global(); +    return g; +} + +locale::locale()  _NOEXCEPT +    : __locale_(__global().__locale_) +{ +    __locale_->__add_shared(); +} + +locale::locale(const locale& l)  _NOEXCEPT +    : __locale_(l.__locale_) +{ +    __locale_->__add_shared(); +} + +locale::~locale() +{ +    __locale_->__release_shared(); +} + +const locale& +locale::operator=(const locale& other)  _NOEXCEPT +{ +    other.__locale_->__add_shared(); +    __locale_->__release_shared(); +    __locale_ = other.__locale_; +    return *this; +} + +locale::locale(const char* name) +#ifndef _LIBCPP_NO_EXCEPTIONS +    : __locale_(name ? new __imp(name) +                     : throw runtime_error("locale constructed with null")) +#else  // _LIBCPP_NO_EXCEPTIONS +    : __locale_(new __imp(name)) +#endif +{ +    __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) +#ifndef _LIBCPP_NO_EXCEPTIONS +    : __locale_(name ? new __imp(*other.__locale_, name, c) +                     : throw runtime_error("locale constructed with null")) +#else  // _LIBCPP_NO_EXCEPTIONS +    : __locale_(new __imp(*other.__locale_, name, c)) +#endif +{ +    __locale_->__add_shared(); +} + +locale::locale(const locale& other, const string& name, category c) +    : __locale_(new __imp(*other.__locale_, name, c)) +{ +    __locale_->__add_shared(); +} + +locale::locale(const locale& other, const locale& one, category c) +    : __locale_(new __imp(*other.__locale_, *one.__locale_, c)) +{ +    __locale_->__add_shared(); +} + +string +locale::name() const +{ +    return __locale_->name(); +} + +void +locale::__install_ctor(const locale& other, facet* f, long id) +{ +    if (f) +        __locale_ = new __imp(*other.__locale_, f, id); +    else +        __locale_ = other.__locale_; +    __locale_->__add_shared(); +} + +locale +locale::global(const locale& loc) +{ +    locale& g = __global(); +    locale r = g; +    g = loc; +    if (g.name() != "*") +        setlocale(LC_ALL, g.name().c_str()); +    return r; +} + +bool +locale::has_facet(id& x) const +{ +    return __locale_->has_facet(x.__get()); +} + +const locale::facet* +locale::use_facet(id& x) const +{ +    return __locale_->use_facet(x.__get()); +} + +bool +locale::operator==(const locale& y) const +{ +    return (__locale_ == y.__locale_) +        || (__locale_->name() != "*" && __locale_->name() == y.__locale_->name()); +} + +// locale::facet + +locale::facet::~facet() +{ +} + +void +locale::facet::__on_zero_shared() _NOEXCEPT +{ +    delete this; +} + +// locale::id + +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_ = __sync_add_and_fetch(&__next_id, 1); +} + +// template <> class collate_byname<char> + +collate_byname<char>::collate_byname(const char* n, size_t refs) +    : collate<char>(refs), +      __l(newlocale(LC_ALL_MASK, n, 0)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__l == 0) +        throw runtime_error("collate_byname<char>::collate_byname" +                            " failed to construct for " + string(n)); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +collate_byname<char>::collate_byname(const string& name, size_t refs) +    : collate<char>(refs), +      __l(newlocale(LC_ALL_MASK, name.c_str(), 0)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__l == 0) +        throw runtime_error("collate_byname<char>::collate_byname" +                            " failed to construct for " + name); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +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)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__l == 0) +        throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" +                            " failed to construct for " + string(n)); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +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)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__l == 0) +        throw runtime_error("collate_byname<wchar_t>::collate_byname(size_t refs)" +                            " failed to construct for " + name); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +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) ? ctype<char>::classic_table()[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) ? +                                   ctype<char>::classic_table()[*low] : 0); +    return low; +} + +const wchar_t* +ctype<wchar_t>::do_scan_is(mask m, const char_type* low, const char_type* high) const +{ +    for (; low != high; ++low) +        if (isascii(*low) && (ctype<char>::classic_table()[*low] & m)) +            break; +    return low; +} + +const wchar_t* +ctype<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const +{ +    for (; low != high; ++low) +        if (!(isascii(*low) && (ctype<char>::classic_table()[*low] & m))) +            break; +    return low; +} + +wchar_t +ctype<wchar_t>::do_toupper(char_type c) const +{ +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE +    return isascii(c) ? _DefaultRuneLocale.__mapupper[c] : c; +#elif defined(__GLIBC__) +    return isascii(c) ? ctype<char>::__classic_upper_table()[c] : c; +#else +    return (isascii(c) && iswlower_l(c, __cloc())) ? c-L'a'+L'A' : c; +#endif +} + +const wchar_t* +ctype<wchar_t>::do_toupper(char_type* low, const char_type* high) const +{ +    for (; low != high; ++low) +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE +        *low = isascii(*low) ? _DefaultRuneLocale.__mapupper[*low] : *low; +#elif defined(__GLIBC__) +        *low = isascii(*low) ? ctype<char>::__classic_upper_table()[*low] +                             : *low; +#else +        *low = (isascii(*low) && islower_l(*low, __cloc())) ? (*low-L'a'+L'A') : *low; +#endif +    return low; +} + +wchar_t +ctype<wchar_t>::do_tolower(char_type c) const +{ +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE +    return isascii(c) ? _DefaultRuneLocale.__maplower[c] : c; +#elif defined(__GLIBC__) +    return isascii(c) ? ctype<char>::__classic_lower_table()[c] : c; +#else +    return (isascii(c) && isupper_l(c, __cloc())) ? c-L'A'+'a' : c; +#endif +} + +const wchar_t* +ctype<wchar_t>::do_tolower(char_type* low, const char_type* high) const +{ +    for (; low != high; ++low) +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE +        *low = isascii(*low) ? _DefaultRuneLocale.__maplower[*low] : *low; +#elif defined(__GLIBC__) +        *low = isascii(*low) ? ctype<char>::__classic_lower_table()[*low] +                             : *low; +#else +        *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-L'A'+L'a' : *low; +#endif +    return low; +} + +wchar_t +ctype<wchar_t>::do_widen(char c) const +{ +    return c; +} + +const char* +ctype<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const +{ +    for (; low != high; ++low, ++dest) +        *dest = *low; +    return low; +} + +char +ctype<wchar_t>::do_narrow(char_type c, char dfault) const +{ +    if (isascii(c)) +        return static_cast<char>(c); +    return dfault; +} + +const wchar_t* +ctype<wchar_t>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const +{ +    for (; low != high; ++low, ++dest) +        if (isascii(*low)) +            *dest = static_cast<char>(*low); +        else +            *dest = dfault; +    return low; +} + +// template <> class ctype<char>; + +locale::id ctype<char>::id; + +ctype<char>::ctype(const mask* tab, bool del, size_t refs) +    : locale::facet(refs), +      __tab_(tab), +      __del_(del) +{ +  if (__tab_ == 0) +      __tab_ = classic_table(); +} + +ctype<char>::~ctype() +{ +    if (__tab_ && __del_) +        delete [] __tab_; +} + +char +ctype<char>::do_toupper(char_type c) const +{ +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE +    return isascii(c) ? +      static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(c)]) : c; +#elif defined(__GLIBC__) +    return isascii(c) ? __classic_upper_table()[c] : c; +#else +    return (isascii(c) && islower_l(c, __cloc())) ? c-'a'+'A' : c; +#endif +} + +const char* +ctype<char>::do_toupper(char_type* low, const char_type* high) const +{ +    for (; low != high; ++low) +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE +        *low = isascii(*low) ? +          static_cast<char>(_DefaultRuneLocale.__mapupper[static_cast<ptrdiff_t>(*low)]) : *low; +#elif defined(__GLIBC__) +        *low = isascii(*low) ? __classic_upper_table()[*low] : *low; +#else +        *low = (isascii(*low) && islower_l(*low, __cloc())) ? *low-'a'+'A' : *low; +#endif +    return low; +} + +char +ctype<char>::do_tolower(char_type c) const +{ +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE +    return isascii(c) ? +      static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(c)]) : c; +#elif defined(__GLIBC__) +    return isascii(c) ? __classic_lower_table()[c] : c; +#else +    return (isascii(c) && isupper_l(c, __cloc())) ? c-'A'+'a' : c; +#endif +} + +const char* +ctype<char>::do_tolower(char_type* low, const char_type* high) const +{ +    for (; low != high; ++low) +#ifdef _LIBCPP_HAS_DEFAULTRUNELOCALE +        *low = isascii(*low) ? static_cast<char>(_DefaultRuneLocale.__maplower[static_cast<ptrdiff_t>(*low)]) : *low; +#elif defined(__GLIBC__) +        *low = isascii(*low) ? __classic_lower_table()[*low] : *low; +#else +        *low = (isascii(*low) && isupper_l(*low, __cloc())) ? *low-'A'+'a' : *low; +#endif +    return low; +} + +char +ctype<char>::do_widen(char c) const +{ +    return c; +} + +const char* +ctype<char>::do_widen(const char* low, const char* high, char_type* dest) const +{ +    for (; low != high; ++low, ++dest) +        *dest = *low; +    return low; +} + +char +ctype<char>::do_narrow(char_type c, char dfault) const +{ +    if (isascii(c)) +        return static_cast<char>(c); +    return dfault; +} + +const char* +ctype<char>::do_narrow(const char_type* low, const char_type* high, char dfault, char* dest) const +{ +    for (; low != high; ++low, ++dest) +        if (isascii(*low)) +            *dest = *low; +        else +            *dest = dfault; +    return low; +} + +const ctype<char>::mask* +ctype<char>::classic_table()  _NOEXCEPT +{ +#if defined(__APPLE__) || defined(__FreeBSD__) +    return _DefaultRuneLocale.__runetype; +#elif defined(__GLIBC__) +    return __cloc()->__ctype_b; +#elif __sun__ +    return __ctype_mask; +#elif _WIN32 +    return _ctype+1; // internal ctype mask table defined in msvcrt.dll +// This is assumed to be safe, which is a nonsense assumption because we're +// going to end up dereferencing it later... +#else +    // Platform not supported: abort so the person doing the port knows what to +    // fix +# warning  ctype<char>::classic_table() is not implemented +    abort(); +    return NULL; +#endif +} + +#if defined(__GLIBC__) +const int* +ctype<char>::__classic_lower_table() _NOEXCEPT +{ +    return __cloc()->__ctype_tolower; +} + +const int* +ctype<char>::__classic_upper_table() _NOEXCEPT +{ +    return __cloc()->__ctype_toupper; +} +#endif // __GLIBC__ + +// 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)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__l == 0) +        throw runtime_error("ctype_byname<char>::ctype_byname" +                            " failed to construct for " + string(name)); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +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)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__l == 0) +        throw runtime_error("ctype_byname<char>::ctype_byname" +                            " failed to construct for " + name); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +ctype_byname<char>::~ctype_byname() +{ +    freelocale(__l); +} + +char +ctype_byname<char>::do_toupper(char_type c) const +{ +    return static_cast<char>(toupper_l(c, __l)); +} + +const char* +ctype_byname<char>::do_toupper(char_type* low, const char_type* high) const +{ +    for (; low != high; ++low) +        *low = static_cast<char>(toupper_l(*low, __l)); +    return low; +} + +char +ctype_byname<char>::do_tolower(char_type c) const +{ +    return static_cast<char>(tolower_l(c, __l)); +} + +const char* +ctype_byname<char>::do_tolower(char_type* low, const char_type* high) const +{ +    for (; low != high; ++low) +        *low = static_cast<char>(tolower_l(*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)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__l == 0) +        throw runtime_error("ctype_byname<wchar_t>::ctype_byname" +                            " failed to construct for " + string(name)); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +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)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__l == 0) +        throw runtime_error("ctype_byname<wchar_t>::ctype_byname" +                            " failed to construct for " + name); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +ctype_byname<wchar_t>::~ctype_byname() +{ +    freelocale(__l); +} + +bool +ctype_byname<wchar_t>::do_is(mask m, char_type c) const +{ +#ifdef _LIBCPP_WCTYPE_IS_MASK +    return static_cast<bool>(iswctype_l(c, m, __l)); +#else +    bool result = true; +    if (m & space && !iswspace_l(c, __l)) result = false; +    if (m & print && !iswprint_l(c, __l)) result = false; +    if (m & cntrl && !iswcntrl_l(c, __l)) result = false; +    if (m & upper && !iswupper_l(c, __l)) result = false; +    if (m & lower && !iswlower_l(c, __l)) result = false; +    if (m & alpha && !iswalpha_l(c, __l)) result = false; +    if (m & digit && !iswdigit_l(c, __l)) result = false; +    if (m & punct && !iswpunct_l(c, __l)) result = false; +    if (m & xdigit && !iswxdigit_l(c, __l)) result = false; +    if (m & blank && !iswblank_l(c, __l)) result = false; +    return result; +#endif +} + +const wchar_t* +ctype_byname<wchar_t>::do_is(const char_type* low, const char_type* high, mask* vec) const +{ +    for (; low != high; ++low, ++vec) +    { +        if (isascii(*low)) +            *vec = static_cast<mask>(ctype<char>::classic_table()[*low]); +        else +        { +            *vec = 0; +            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) +    { +#ifdef _LIBCPP_WCTYPE_IS_MASK +        if (iswctype_l(*low, m, __l)) +            break; +#else +        if (m & space && !iswspace_l(*low, __l)) continue; +        if (m & print && !iswprint_l(*low, __l)) continue; +        if (m & cntrl && !iswcntrl_l(*low, __l)) continue; +        if (m & upper && !iswupper_l(*low, __l)) continue; +        if (m & lower && !iswlower_l(*low, __l)) continue; +        if (m & alpha && !iswalpha_l(*low, __l)) continue; +        if (m & digit && !iswdigit_l(*low, __l)) continue; +        if (m & punct && !iswpunct_l(*low, __l)) continue; +        if (m & xdigit && !iswxdigit_l(*low, __l)) continue; +        if (m & blank && !iswblank_l(*low, __l)) continue; +        break; +#endif +    } +    return low; +} + +const wchar_t* +ctype_byname<wchar_t>::do_scan_not(mask m, const char_type* low, const char_type* high) const +{ +    for (; low != high; ++low) +    { +#ifdef _LIBCPP_WCTYPE_IS_MASK +        if (!iswctype_l(*low, m, __l)) +            break; +#else +        if (m & space && iswspace_l(*low, __l)) continue; +        if (m & print && iswprint_l(*low, __l)) continue; +        if (m & cntrl && iswcntrl_l(*low, __l)) continue; +        if (m & upper && iswupper_l(*low, __l)) continue; +        if (m & lower && iswlower_l(*low, __l)) continue; +        if (m & alpha && iswalpha_l(*low, __l)) continue; +        if (m & digit && iswdigit_l(*low, __l)) continue; +        if (m & punct && iswpunct_l(*low, __l)) continue; +        if (m & xdigit && iswxdigit_l(*low, __l)) continue; +        if (m & blank && iswblank_l(*low, __l)) continue; +        break; +#endif +    } +    return low; +} + +wchar_t +ctype_byname<wchar_t>::do_toupper(char_type c) const +{ +    return towupper_l(c, __l); +} + +const wchar_t* +ctype_byname<wchar_t>::do_toupper(char_type* low, const char_type* high) const +{ +    for (; low != high; ++low) +        *low = towupper_l(*low, __l); +    return low; +} + +wchar_t +ctype_byname<wchar_t>::do_tolower(char_type c) const +{ +    return towlower_l(c, __l); +} + +const wchar_t* +ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const +{ +    for (; low != high; ++low) +        *low = towlower_l(*low, __l); +    return low; +} + +wchar_t +ctype_byname<wchar_t>::do_widen(char c) const +{ +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    return btowc_l(c, __l); +#else +    return __btowc_l(c, __l); +#endif +} + +const char* +ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const +{ +    for (; low != high; ++low, ++dest) +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        *dest = btowc_l(*low, __l); +#else +        *dest = __btowc_l(*low, __l); +#endif +    return low; +} + +char +ctype_byname<wchar_t>::do_narrow(char_type c, char dfault) const +{ +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    int r = wctob_l(c, __l); +#else +    int r = __wctob_l(c, __l); +#endif +    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) +    { +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        int r = wctob_l(*low, __l); +#else +        int r = __wctob_l(*low, __l); +#endif +        *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  _NOEXCEPT +{ +    return 1; +} + +bool +codecvt<char, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT +{ +    return true; +} + +int +codecvt<char, char, mbstate_t>::do_length(state_type&, +    const extern_type* frm, const extern_type* end, size_t mx) const +{ +    return static_cast<int>(min<size_t>(mx, static_cast<size_t>(end-frm))); +} + +int +codecvt<char, char, mbstate_t>::do_max_length() const  _NOEXCEPT +{ +    return 1; +} + +// template <> class codecvt<wchar_t, char, mbstate_t> + +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)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__l == 0) +        throw runtime_error("codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname" +                            " failed to construct for " + string(nm)); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +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; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        size_t n = wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), +                                static_cast<size_t>(to_end-to), &st, __l); +#else +        size_t n = __wcsnrtombs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l); +#endif +        if (n == size_t(-1)) +        { +            // need to recover to_nxt +            for (to_nxt = to; frm != frm_nxt; ++frm) +            { +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +                n = wcrtomb_l(to_nxt, *frm, &save_state, __l); +#else +                n = __wcrtomb_l(to_nxt, *frm, &save_state, __l); +#endif +                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]; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +            n = wcrtomb_l(tmp, intern_type(), &st, __l); +#else +            n = __wcrtomb_l(tmp, intern_type(), &st, __l); +#endif +            if (n == size_t(-1))  // on error +                return error; +            if (n > static_cast<size_t>(to_end-to_nxt))  // is there room? +                return partial; +            for (extern_type* p = tmp; n; --n)  // write it +                *to_nxt++ = *p++; +            ++frm_nxt; +            // look for next null in frm +            for (fend = frm_nxt; fend != frm_end; ++fend) +                if (*fend == 0) +                    break; +        } +    } +    return frm_nxt == frm_end ? ok : partial; +} + +codecvt<wchar_t, char, mbstate_t>::result +codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    // look for first internal null in frm +    const extern_type* fend = frm; +    for (; fend != frm_end; ++fend) +        if (*fend == 0) +            break; +    // loop over all null-terminated sequences in frm +    to_nxt = to; +    for (frm_nxt = frm; frm != frm_end && to != to_end; frm = frm_nxt, to = to_nxt) +    { +        // save state in case needed to reover to_nxt on error +        mbstate_t save_state = st; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        size_t n = mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), +                                static_cast<size_t>(to_end-to), &st, __l); +#else +        size_t n = __mbsnrtowcs_l(to, &frm_nxt, fend-frm, to_end-to, &st, __l); +#endif +        if (n == size_t(-1)) +        { +            // need to recover to_nxt +            for (to_nxt = to; frm != frm_nxt; ++to_nxt) +            { +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +                n = mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm), +                              &save_state, __l); +#else +                n = __mbrtowc_l(to_nxt, frm, fend-frm, &save_state, __l); +#endif +                switch (n) +                { +                case 0: +                    ++frm; +                    break; +                case size_t(-1): +                    frm_nxt = frm; +                    return error; +                case size_t(-2): +                    frm_nxt = frm; +                    return partial; +                default: +                    frm += n; +                    break; +                } +            } +            frm_nxt = frm; +            return frm_nxt == frm_end ? ok : partial; +        } +        if (n == 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 +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +            n = mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l); +#else +            n = __mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l); +#endif +            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]; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    size_t n = wcrtomb_l(tmp, intern_type(), &st, __l); +#else +    size_t n = __wcrtomb_l(tmp, intern_type(), &st, __l); +#endif +    if (n == size_t(-1) || n == 0)  // on error +        return error; +    --n; +    if (n > static_cast<size_t>(to_end-to_nxt))  // is there room? +        return partial; +    for (extern_type* p = tmp; n; --n)  // write it +        *to_nxt++ = *p++; +    return ok; +} + +int +codecvt<wchar_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT +{ +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    if (mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0) +#else +    if (__mbtowc_l((wchar_t*) 0, (const char*) 0, MB_LEN_MAX, __l) == 0) +#endif +    { +        // stateless encoding +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        if (__l == 0 || MB_CUR_MAX_L(__l) == 1)  // there are no known constant length encodings +#else +        if (__l == 0 || __mb_cur_max_l(__l) == 1)  // there are no known constant length encodings +#endif +            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  _NOEXCEPT +{ +    return false; +} + +int +codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    int nbytes = 0; +    for (size_t nwchar_t = 0; nwchar_t < mx && frm != frm_end; ++nwchar_t) +    { +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        size_t n = mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l); +#else +        size_t n = __mbrlen_l(frm, frm_end-frm, &st, __l); +#endif +        switch (n) +        { +        case 0: +            ++nbytes; +            ++frm; +            break; +        case size_t(-1): +        case size_t(-2): +            return nbytes; +        default: +            nbytes += n; +            frm += n; +            break; +        } +    } +    return nbytes; +} + +int +codecvt<wchar_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT +{ +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    return __l == 0 ? 1 : MB_CUR_MAX_L(__l); +#else +    return __l == 0 ? 1 : __mb_cur_max_l(__l); +#endif +} + +//                                     Valid UTF ranges +//     UTF-32               UTF-16                          UTF-8               # of code points +//                     first      second       first   second    third   fourth +// 000000 - 00007F  0000 - 007F               00 - 7F                                 127 +// 000080 - 0007FF  0080 - 07FF               C2 - DF, 80 - BF                       1920 +// 000800 - 000FFF  0800 - 0FFF               E0 - E0, A0 - BF, 80 - BF              2048 +// 001000 - 00CFFF  1000 - CFFF               E1 - EC, 80 - BF, 80 - BF             49152 +// 00D000 - 00D7FF  D000 - D7FF               ED - ED, 80 - 9F, 80 - BF              2048 +// 00D800 - 00DFFF                invalid +// 00E000 - 00FFFF  E000 - FFFF               EE - EF, 80 - BF, 80 - BF              8192 +// 010000 - 03FFFF  D800 - D8BF, DC00 - DFFF  F0 - F0, 90 - BF, 80 - BF, 80 - BF   196608 +// 040000 - 0FFFFF  D8C0 - DBBF, DC00 - DFFF  F1 - F3, 80 - BF, 80 - BF, 80 - BF   786432 +// 100000 - 10FFFF  DBC0 - DBFF, DC00 - DFFF  F4 - F4, 80 - 8F, 80 - BF, 80 - BF    65536 + +static +codecvt_base::result +utf16_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, +              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, +              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & generate_header) +    { +        if (to_end-to_nxt < 3) +            return codecvt_base::partial; +        *to_nxt++ = static_cast<uint8_t>(0xEF); +        *to_nxt++ = static_cast<uint8_t>(0xBB); +        *to_nxt++ = static_cast<uint8_t>(0xBF); +    } +    for (; frm_nxt < frm_end; ++frm_nxt) +    { +        uint16_t wc1 = *frm_nxt; +        if (wc1 > Maxcode) +            return codecvt_base::error; +        if (wc1 < 0x0080) +        { +            if (to_end-to_nxt < 1) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(wc1); +        } +        else if (wc1 < 0x0800) +        { +            if (to_end-to_nxt < 2) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); +        } +        else if (wc1 < 0xD800) +        { +            if (to_end-to_nxt < 3) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F)); +        } +        else if (wc1 < 0xDC00) +        { +            if (frm_end-frm_nxt < 2) +                return codecvt_base::partial; +            uint16_t wc2 = frm_nxt[1]; +            if ((wc2 & 0xFC00) != 0xDC00) +                return codecvt_base::error; +            if (to_end-to_nxt < 4) +                return codecvt_base::partial; +            if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) + +                (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode) +                return codecvt_base::error; +            ++frm_nxt; +            uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; +            *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F)); +        } +        else if (wc1 < 0xE000) +        { +            return codecvt_base::error; +        } +        else +        { +            if (to_end-to_nxt < 3) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F)); +        } +    } +    return codecvt_base::ok; +} + +static +codecvt_base::result +utf16_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, +              uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, +              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & generate_header) +    { +        if (to_end-to_nxt < 3) +            return codecvt_base::partial; +        *to_nxt++ = static_cast<uint8_t>(0xEF); +        *to_nxt++ = static_cast<uint8_t>(0xBB); +        *to_nxt++ = static_cast<uint8_t>(0xBF); +    } +    for (; frm_nxt < frm_end; ++frm_nxt) +    { +        uint16_t wc1 = static_cast<uint16_t>(*frm_nxt); +        if (wc1 > Maxcode) +            return codecvt_base::error; +        if (wc1 < 0x0080) +        { +            if (to_end-to_nxt < 1) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(wc1); +        } +        else if (wc1 < 0x0800) +        { +            if (to_end-to_nxt < 2) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc1 >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc1 & 0x03F)); +        } +        else if (wc1 < 0xD800) +        { +            if (to_end-to_nxt < 3) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F)); +        } +        else if (wc1 < 0xDC00) +        { +            if (frm_end-frm_nxt < 2) +                return codecvt_base::partial; +            uint16_t wc2 = static_cast<uint16_t>(frm_nxt[1]); +            if ((wc2 & 0xFC00) != 0xDC00) +                return codecvt_base::error; +            if (to_end-to_nxt < 4) +                return codecvt_base::partial; +            if ((((((unsigned long)wc1 & 0x03C0) >> 6) + 1) << 16) + +                (((unsigned long)wc1 & 0x003F) << 10) + (wc2 & 0x03FF) > Maxcode) +                return codecvt_base::error; +            ++frm_nxt; +            uint8_t z = ((wc1 & 0x03C0) >> 6) + 1; +            *to_nxt++ = static_cast<uint8_t>(0xF0 | (z >> 2)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((z & 0x03) << 4)     | ((wc1 & 0x003C) >> 2)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0003) << 4) | ((wc2 & 0x03C0) >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc2 & 0x003F)); +        } +        else if (wc1 < 0xE000) +        { +            return codecvt_base::error; +        } +        else +        { +            if (to_end-to_nxt < 3) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc1 >> 12)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc1 & 0x0FC0) >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc1 & 0x003F)); +        } +    } +    return codecvt_base::ok; +} + +static +codecvt_base::result +utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, +              uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, +              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && +                                                          frm_nxt[2] == 0xBF) +            frm_nxt += 3; +    } +    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) +    { +        uint8_t c1 = *frm_nxt; +        if (c1 > Maxcode) +            return codecvt_base::error; +        if (c1 < 0x80) +        { +            *to_nxt = static_cast<uint16_t>(c1); +            ++frm_nxt; +        } +        else if (c1 < 0xC2) +        { +            return codecvt_base::error; +        } +        else if (c1 < 0xE0) +        { +            if (frm_end-frm_nxt < 2) +                return codecvt_base::partial; +            uint8_t c2 = frm_nxt[1]; +            if ((c2 & 0xC0) != 0x80) +                return codecvt_base::error; +            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); +            if (t > Maxcode) +                return codecvt_base::error; +            *to_nxt = t; +            frm_nxt += 2; +        } +        else if (c1 < 0xF0) +        { +            if (frm_end-frm_nxt < 3) +                return codecvt_base::partial; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            switch (c1) +            { +            case 0xE0: +                if ((c2 & 0xE0) != 0xA0) +                    return codecvt_base::error; +                 break; +            case 0xED: +                if ((c2 & 0xE0) != 0x80) +                    return codecvt_base::error; +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return codecvt_base::error; +                 break; +            } +            if ((c3 & 0xC0) != 0x80) +                return codecvt_base::error; +            uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) +                                             | ((c2 & 0x3F) << 6) +                                             |  (c3 & 0x3F)); +            if (t > Maxcode) +                return codecvt_base::error; +            *to_nxt = t; +            frm_nxt += 3; +        } +        else if (c1 < 0xF5) +        { +            if (frm_end-frm_nxt < 4) +                return codecvt_base::partial; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            uint8_t c4 = frm_nxt[3]; +            switch (c1) +            { +            case 0xF0: +                if (!(0x90 <= c2 && c2 <= 0xBF)) +                    return codecvt_base::error; +                 break; +            case 0xF4: +                if ((c2 & 0xF0) != 0x80) +                    return codecvt_base::error; +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return codecvt_base::error; +                 break; +            } +            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) +                return codecvt_base::error; +            if (to_end-to_nxt < 2) +                return codecvt_base::partial; +            if (((((unsigned long)c1 & 7) << 18) + +                (((unsigned long)c2 & 0x3F) << 12) + +                (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode) +                return codecvt_base::error; +            *to_nxt = static_cast<uint16_t>( +                    0xD800 +                  | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) +                  | ((c2 & 0x0F) << 2) +                  | ((c3 & 0x30) >> 4)); +            *++to_nxt = static_cast<uint16_t>( +                    0xDC00 +                  | ((c3 & 0x0F) << 6) +                  |  (c4 & 0x3F)); +            frm_nxt += 4; +        } +        else +        { +            return codecvt_base::error; +        } +    } +    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +codecvt_base::result +utf8_to_utf16(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, +              uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, +              unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && +                                                          frm_nxt[2] == 0xBF) +            frm_nxt += 3; +    } +    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) +    { +        uint8_t c1 = *frm_nxt; +        if (c1 > Maxcode) +            return codecvt_base::error; +        if (c1 < 0x80) +        { +            *to_nxt = static_cast<uint32_t>(c1); +            ++frm_nxt; +        } +        else if (c1 < 0xC2) +        { +            return codecvt_base::error; +        } +        else if (c1 < 0xE0) +        { +            if (frm_end-frm_nxt < 2) +                return codecvt_base::partial; +            uint8_t c2 = frm_nxt[1]; +            if ((c2 & 0xC0) != 0x80) +                return codecvt_base::error; +            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (c2 & 0x3F)); +            if (t > Maxcode) +                return codecvt_base::error; +            *to_nxt = static_cast<uint32_t>(t); +            frm_nxt += 2; +        } +        else if (c1 < 0xF0) +        { +            if (frm_end-frm_nxt < 3) +                return codecvt_base::partial; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            switch (c1) +            { +            case 0xE0: +                if ((c2 & 0xE0) != 0xA0) +                    return codecvt_base::error; +                 break; +            case 0xED: +                if ((c2 & 0xE0) != 0x80) +                    return codecvt_base::error; +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return codecvt_base::error; +                 break; +            } +            if ((c3 & 0xC0) != 0x80) +                return codecvt_base::error; +            uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) +                                             | ((c2 & 0x3F) << 6) +                                             |  (c3 & 0x3F)); +            if (t > Maxcode) +                return codecvt_base::error; +            *to_nxt = static_cast<uint32_t>(t); +            frm_nxt += 3; +        } +        else if (c1 < 0xF5) +        { +            if (frm_end-frm_nxt < 4) +                return codecvt_base::partial; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            uint8_t c4 = frm_nxt[3]; +            switch (c1) +            { +            case 0xF0: +                if (!(0x90 <= c2 && c2 <= 0xBF)) +                    return codecvt_base::error; +                 break; +            case 0xF4: +                if ((c2 & 0xF0) != 0x80) +                    return codecvt_base::error; +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return codecvt_base::error; +                 break; +            } +            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) +                return codecvt_base::error; +            if (to_end-to_nxt < 2) +                return codecvt_base::partial; +            if (((((unsigned long)c1 & 7) << 18) + +                (((unsigned long)c2 & 0x3F) << 12) + +                (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode) +                return codecvt_base::error; +            *to_nxt = static_cast<uint32_t>( +                    0xD800 +                  | (((((c1 & 0x07) << 2) | ((c2 & 0x30) >> 4)) - 1) << 6) +                  | ((c2 & 0x0F) << 2) +                  | ((c3 & 0x30) >> 4)); +            *++to_nxt = static_cast<uint32_t>( +                    0xDC00 +                  | ((c3 & 0x0F) << 6) +                  |  (c4 & 0x3F)); +            frm_nxt += 4; +        } +        else +        { +            return codecvt_base::error; +        } +    } +    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf8_to_utf16_length(const uint8_t* frm, const uint8_t* frm_end, +                     size_t mx, unsigned long Maxcode = 0x10FFFF, +                     codecvt_mode mode = codecvt_mode(0)) +{ +    const uint8_t* frm_nxt = frm; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && +                                                          frm_nxt[2] == 0xBF) +            frm_nxt += 3; +    } +    for (size_t nchar16_t = 0; frm_nxt < frm_end && nchar16_t < mx; ++nchar16_t) +    { +        uint8_t c1 = *frm_nxt; +        if (c1 > Maxcode) +            break; +        if (c1 < 0x80) +        { +            ++frm_nxt; +        } +        else if (c1 < 0xC2) +        { +            break; +        } +        else if (c1 < 0xE0) +        { +            if ((frm_end-frm_nxt < 2) || (frm_nxt[1] & 0xC0) != 0x80) +                break; +            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) | (frm_nxt[1] & 0x3F)); +            if (t > Maxcode) +                break; +            frm_nxt += 2; +        } +        else if (c1 < 0xF0) +        { +            if (frm_end-frm_nxt < 3) +                break; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            switch (c1) +            { +            case 0xE0: +                if ((c2 & 0xE0) != 0xA0) +                    return static_cast<int>(frm_nxt - frm); +                break; +            case 0xED: +                if ((c2 & 0xE0) != 0x80) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            } +            if ((c3 & 0xC0) != 0x80) +                break; +            if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) +                break; +            frm_nxt += 3; +        } +        else if (c1 < 0xF5) +        { +            if (frm_end-frm_nxt < 4 || mx-nchar16_t < 2) +                break; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            uint8_t c4 = frm_nxt[3]; +            switch (c1) +            { +            case 0xF0: +                if (!(0x90 <= c2 && c2 <= 0xBF)) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            case 0xF4: +                if ((c2 & 0xF0) != 0x80) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            } +            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) +                break; +            if (((((unsigned long)c1 & 7) << 18) + +                (((unsigned long)c2 & 0x3F) << 12) + +                (((unsigned long)c3 & 0x3F) << 6) + (c4 & 0x3F)) > Maxcode) +                break; +            ++nchar16_t; +            frm_nxt += 4; +        } +        else +        { +            break; +        } +    } +    return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs4_to_utf8(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, +             uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, +             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & generate_header) +    { +        if (to_end-to_nxt < 3) +            return codecvt_base::partial; +        *to_nxt++ = static_cast<uint8_t>(0xEF); +        *to_nxt++ = static_cast<uint8_t>(0xBB); +        *to_nxt++ = static_cast<uint8_t>(0xBF); +    } +    for (; frm_nxt < frm_end; ++frm_nxt) +    { +        uint32_t wc = *frm_nxt; +        if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) +            return codecvt_base::error; +        if (wc < 0x000080) +        { +            if (to_end-to_nxt < 1) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(wc); +        } +        else if (wc < 0x000800) +        { +            if (to_end-to_nxt < 2) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); +        } +        else if (wc < 0x010000) +        { +            if (to_end-to_nxt < 3) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F)); +        } +        else // if (wc < 0x110000) +        { +            if (to_end-to_nxt < 4) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xF0 |  (wc >> 18)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x03F000) >> 12)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x000FC0) >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x00003F)); +        } +    } +    return codecvt_base::ok; +} + +static +codecvt_base::result +utf8_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, +             uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, +             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && +                                                          frm_nxt[2] == 0xBF) +            frm_nxt += 3; +    } +    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) +    { +        uint8_t c1 = static_cast<uint8_t>(*frm_nxt); +        if (c1 < 0x80) +        { +            if (c1 > Maxcode) +                return codecvt_base::error; +            *to_nxt = static_cast<uint32_t>(c1); +            ++frm_nxt; +        } +        else if (c1 < 0xC2) +        { +            return codecvt_base::error; +        } +        else if (c1 < 0xE0) +        { +            if (frm_end-frm_nxt < 2) +                return codecvt_base::partial; +            uint8_t c2 = frm_nxt[1]; +            if ((c2 & 0xC0) != 0x80) +                return codecvt_base::error; +            uint32_t t = static_cast<uint32_t>(((c1 & 0x1F) << 6) +                                              | (c2 & 0x3F)); +            if (t > Maxcode) +                return codecvt_base::error; +            *to_nxt = t; +            frm_nxt += 2; +        } +        else if (c1 < 0xF0) +        { +            if (frm_end-frm_nxt < 3) +                return codecvt_base::partial; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            switch (c1) +            { +            case 0xE0: +                if ((c2 & 0xE0) != 0xA0) +                    return codecvt_base::error; +                 break; +            case 0xED: +                if ((c2 & 0xE0) != 0x80) +                    return codecvt_base::error; +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return codecvt_base::error; +                 break; +            } +            if ((c3 & 0xC0) != 0x80) +                return codecvt_base::error; +            uint32_t t = static_cast<uint32_t>(((c1 & 0x0F) << 12) +                                             | ((c2 & 0x3F) << 6) +                                             |  (c3 & 0x3F)); +            if (t > Maxcode) +                return codecvt_base::error; +            *to_nxt = t; +            frm_nxt += 3; +        } +        else if (c1 < 0xF5) +        { +            if (frm_end-frm_nxt < 4) +                return codecvt_base::partial; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            uint8_t c4 = frm_nxt[3]; +            switch (c1) +            { +            case 0xF0: +                if (!(0x90 <= c2 && c2 <= 0xBF)) +                    return codecvt_base::error; +                 break; +            case 0xF4: +                if ((c2 & 0xF0) != 0x80) +                    return codecvt_base::error; +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return codecvt_base::error; +                 break; +            } +            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) +                return codecvt_base::error; +            uint32_t t = static_cast<uint32_t>(((c1 & 0x07) << 18) +                                             | ((c2 & 0x3F) << 12) +                                             | ((c3 & 0x3F) << 6) +                                             |  (c4 & 0x3F)); +            if (t > Maxcode) +                return codecvt_base::error; +            *to_nxt = t; +            frm_nxt += 4; +        } +        else +        { +            return codecvt_base::error; +        } +    } +    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf8_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, +                    size_t mx, unsigned long Maxcode = 0x10FFFF, +                    codecvt_mode mode = codecvt_mode(0)) +{ +    const uint8_t* frm_nxt = frm; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && +                                                          frm_nxt[2] == 0xBF) +            frm_nxt += 3; +    } +    for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) +    { +        uint8_t c1 = static_cast<uint8_t>(*frm_nxt); +        if (c1 < 0x80) +        { +            if (c1 > Maxcode) +                break; +            ++frm_nxt; +        } +        else if (c1 < 0xC2) +        { +            break; +        } +        else if (c1 < 0xE0) +        { +            if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) +                break; +            if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) +                break; +            frm_nxt += 2; +        } +        else if (c1 < 0xF0) +        { +            if (frm_end-frm_nxt < 3) +                break; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            switch (c1) +            { +            case 0xE0: +                if ((c2 & 0xE0) != 0xA0) +                    return static_cast<int>(frm_nxt - frm); +                break; +            case 0xED: +                if ((c2 & 0xE0) != 0x80) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            } +            if ((c3 & 0xC0) != 0x80) +                break; +            if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) +                break; +            frm_nxt += 3; +        } +        else if (c1 < 0xF5) +        { +            if (frm_end-frm_nxt < 4) +                break; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            uint8_t c4 = frm_nxt[3]; +            switch (c1) +            { +            case 0xF0: +                if (!(0x90 <= c2 && c2 <= 0xBF)) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            case 0xF4: +                if ((c2 & 0xF0) != 0x80) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            } +            if ((c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) +                break; +            if ((((c1 & 0x07u) << 18) | ((c2 & 0x3Fu) << 12) | +                 ((c3 & 0x3Fu) << 6)  |  (c4 & 0x3Fu)) > Maxcode) +                break; +            frm_nxt += 4; +        } +        else +        { +            break; +        } +    } +    return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs2_to_utf8(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, +             uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, +             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & generate_header) +    { +        if (to_end-to_nxt < 3) +            return codecvt_base::partial; +        *to_nxt++ = static_cast<uint8_t>(0xEF); +        *to_nxt++ = static_cast<uint8_t>(0xBB); +        *to_nxt++ = static_cast<uint8_t>(0xBF); +    } +    for (; frm_nxt < frm_end; ++frm_nxt) +    { +        uint16_t wc = *frm_nxt; +        if ((wc & 0xF800) == 0xD800 || wc > Maxcode) +            return codecvt_base::error; +        if (wc < 0x0080) +        { +            if (to_end-to_nxt < 1) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(wc); +        } +        else if (wc < 0x0800) +        { +            if (to_end-to_nxt < 2) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xC0 | (wc >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | (wc & 0x03F)); +        } +        else // if (wc <= 0xFFFF) +        { +            if (to_end-to_nxt < 3) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xE0 |  (wc >> 12)); +            *to_nxt++ = static_cast<uint8_t>(0x80 | ((wc & 0x0FC0) >> 6)); +            *to_nxt++ = static_cast<uint8_t>(0x80 |  (wc & 0x003F)); +        } +    } +    return codecvt_base::ok; +} + +static +codecvt_base::result +utf8_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, +             uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, +             unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && +                                                          frm_nxt[2] == 0xBF) +            frm_nxt += 3; +    } +    for (; frm_nxt < frm_end && to_nxt < to_end; ++to_nxt) +    { +        uint8_t c1 = static_cast<uint8_t>(*frm_nxt); +        if (c1 < 0x80) +        { +            if (c1 > Maxcode) +                return codecvt_base::error; +            *to_nxt = static_cast<uint16_t>(c1); +            ++frm_nxt; +        } +        else if (c1 < 0xC2) +        { +            return codecvt_base::error; +        } +        else if (c1 < 0xE0) +        { +            if (frm_end-frm_nxt < 2) +                return codecvt_base::partial; +            uint8_t c2 = frm_nxt[1]; +            if ((c2 & 0xC0) != 0x80) +                return codecvt_base::error; +            uint16_t t = static_cast<uint16_t>(((c1 & 0x1F) << 6) +                                              | (c2 & 0x3F)); +            if (t > Maxcode) +                return codecvt_base::error; +            *to_nxt = t; +            frm_nxt += 2; +        } +        else if (c1 < 0xF0) +        { +            if (frm_end-frm_nxt < 3) +                return codecvt_base::partial; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            switch (c1) +            { +            case 0xE0: +                if ((c2 & 0xE0) != 0xA0) +                    return codecvt_base::error; +                 break; +            case 0xED: +                if ((c2 & 0xE0) != 0x80) +                    return codecvt_base::error; +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return codecvt_base::error; +                 break; +            } +            if ((c3 & 0xC0) != 0x80) +                return codecvt_base::error; +            uint16_t t = static_cast<uint16_t>(((c1 & 0x0F) << 12) +                                             | ((c2 & 0x3F) << 6) +                                             |  (c3 & 0x3F)); +            if (t > Maxcode) +                return codecvt_base::error; +            *to_nxt = t; +            frm_nxt += 3; +        } +        else +        { +            return codecvt_base::error; +        } +    } +    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf8_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, +                    size_t mx, unsigned long Maxcode = 0x10FFFF, +                    codecvt_mode mode = codecvt_mode(0)) +{ +    const uint8_t* frm_nxt = frm; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 3 && frm_nxt[0] == 0xEF && frm_nxt[1] == 0xBB && +                                                          frm_nxt[2] == 0xBF) +            frm_nxt += 3; +    } +    for (size_t nchar32_t = 0; frm_nxt < frm_end && nchar32_t < mx; ++nchar32_t) +    { +        uint8_t c1 = static_cast<uint8_t>(*frm_nxt); +        if (c1 < 0x80) +        { +            if (c1 > Maxcode) +                break; +            ++frm_nxt; +        } +        else if (c1 < 0xC2) +        { +            break; +        } +        else if (c1 < 0xE0) +        { +            if ((frm_end-frm_nxt < 2) || ((frm_nxt[1] & 0xC0) != 0x80)) +                break; +            if ((((c1 & 0x1Fu) << 6) | (frm_nxt[1] & 0x3Fu)) > Maxcode) +                break; +            frm_nxt += 2; +        } +        else if (c1 < 0xF0) +        { +            if (frm_end-frm_nxt < 3) +                break; +            uint8_t c2 = frm_nxt[1]; +            uint8_t c3 = frm_nxt[2]; +            switch (c1) +            { +            case 0xE0: +                if ((c2 & 0xE0) != 0xA0) +                    return static_cast<int>(frm_nxt - frm); +                break; +            case 0xED: +                if ((c2 & 0xE0) != 0x80) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            default: +                if ((c2 & 0xC0) != 0x80) +                    return static_cast<int>(frm_nxt - frm); +                 break; +            } +            if ((c3 & 0xC0) != 0x80) +                break; +            if ((((c1 & 0x0Fu) << 12) | ((c2 & 0x3Fu) << 6) | (c3 & 0x3Fu)) > Maxcode) +                break; +            frm_nxt += 3; +        } +        else +        { +            break; +        } +    } +    return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs4_to_utf16be(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, +                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, +                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & generate_header) +    { +        if (to_end-to_nxt < 2) +            return codecvt_base::partial; +        *to_nxt++ = static_cast<uint8_t>(0xFE); +        *to_nxt++ = static_cast<uint8_t>(0xFF); +    } +    for (; frm_nxt < frm_end; ++frm_nxt) +    { +        uint32_t wc = *frm_nxt; +        if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) +            return codecvt_base::error; +        if (wc < 0x010000) +        { +            if (to_end-to_nxt < 2) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(wc >> 8); +            *to_nxt++ = static_cast<uint8_t>(wc); +        } +        else +        { +            if (to_end-to_nxt < 4) +                return codecvt_base::partial; +            uint16_t t = static_cast<uint16_t>( +                    0xD800 +                  | ((((wc & 0x1F0000) >> 16) - 1) << 6) +                  |   ((wc & 0x00FC00) >> 10)); +            *to_nxt++ = static_cast<uint8_t>(t >> 8); +            *to_nxt++ = static_cast<uint8_t>(t); +            t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); +            *to_nxt++ = static_cast<uint8_t>(t >> 8); +            *to_nxt++ = static_cast<uint8_t>(t); +        } +    } +    return codecvt_base::ok; +} + +static +codecvt_base::result +utf16be_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, +                uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, +                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) +            frm_nxt += 2; +    } +    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) +    { +        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); +        if ((c1 & 0xFC00) == 0xDC00) +            return codecvt_base::error; +        if ((c1 & 0xFC00) != 0xD800) +        { +            if (c1 > Maxcode) +                return codecvt_base::error; +            *to_nxt = static_cast<uint32_t>(c1); +            frm_nxt += 2; +        } +        else +        { +            if (frm_end-frm_nxt < 4) +                return codecvt_base::partial; +            uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); +            if ((c2 & 0xFC00) != 0xDC00) +                return codecvt_base::error; +            uint32_t t = static_cast<uint32_t>( +                    ((((c1 & 0x03C0) >> 6) + 1) << 16) +                  |   ((c1 & 0x003F) << 10) +                  |    (c2 & 0x03FF)); +            if (t > Maxcode) +                return codecvt_base::error; +            *to_nxt = t; +            frm_nxt += 4; +        } +    } +    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf16be_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, +                       size_t mx, unsigned long Maxcode = 0x10FFFF, +                       codecvt_mode mode = codecvt_mode(0)) +{ +    const uint8_t* frm_nxt = frm; +    frm_nxt = frm; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) +            frm_nxt += 2; +    } +    for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) +    { +        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); +        if ((c1 & 0xFC00) == 0xDC00) +            break; +        if ((c1 & 0xFC00) != 0xD800) +        { +            if (c1 > Maxcode) +                break; +            frm_nxt += 2; +        } +        else +        { +            if (frm_end-frm_nxt < 4) +                break; +            uint16_t c2 = static_cast<uint16_t>(frm_nxt[2] << 8 | frm_nxt[3]); +            if ((c2 & 0xFC00) != 0xDC00) +                break; +            uint32_t t = static_cast<uint32_t>( +                    ((((c1 & 0x03C0) >> 6) + 1) << 16) +                  |   ((c1 & 0x003F) << 10) +                  |    (c2 & 0x03FF)); +            if (t > Maxcode) +                break; +            frm_nxt += 4; +        } +    } +    return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& frm_nxt, +                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, +                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & generate_header) +    { +        if (to_end-to_nxt < 2) +            return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(0xFF); +            *to_nxt++ = static_cast<uint8_t>(0xFE); +    } +    for (; frm_nxt < frm_end; ++frm_nxt) +    { +        uint32_t wc = *frm_nxt; +        if ((wc & 0xFFFFF800) == 0x00D800 || wc > Maxcode) +            return codecvt_base::error; +        if (wc < 0x010000) +        { +            if (to_end-to_nxt < 2) +                return codecvt_base::partial; +            *to_nxt++ = static_cast<uint8_t>(wc); +            *to_nxt++ = static_cast<uint8_t>(wc >> 8); +        } +        else +        { +            if (to_end-to_nxt < 4) +                return codecvt_base::partial; +            uint16_t t = static_cast<uint16_t>( +                    0xD800 +                  | ((((wc & 0x1F0000) >> 16) - 1) << 6) +                  |   ((wc & 0x00FC00) >> 10)); +            *to_nxt++ = static_cast<uint8_t>(t); +            *to_nxt++ = static_cast<uint8_t>(t >> 8); +            t = static_cast<uint16_t>(0xDC00 | (wc & 0x03FF)); +            *to_nxt++ = static_cast<uint8_t>(t); +            *to_nxt++ = static_cast<uint8_t>(t >> 8); +        } +    } +    return codecvt_base::ok; +} + +static +codecvt_base::result +utf16le_to_ucs4(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, +                uint32_t* to, uint32_t* to_end, uint32_t*& to_nxt, +                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) +            frm_nxt += 2; +    } +    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) +    { +        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); +        if ((c1 & 0xFC00) == 0xDC00) +            return codecvt_base::error; +        if ((c1 & 0xFC00) != 0xD800) +        { +            if (c1 > Maxcode) +                return codecvt_base::error; +            *to_nxt = static_cast<uint32_t>(c1); +            frm_nxt += 2; +        } +        else +        { +            if (frm_end-frm_nxt < 4) +                return codecvt_base::partial; +            uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); +            if ((c2 & 0xFC00) != 0xDC00) +                return codecvt_base::error; +            uint32_t t = static_cast<uint32_t>( +                    ((((c1 & 0x03C0) >> 6) + 1) << 16) +                  |   ((c1 & 0x003F) << 10) +                  |    (c2 & 0x03FF)); +            if (t > Maxcode) +                return codecvt_base::error; +            *to_nxt = t; +            frm_nxt += 4; +        } +    } +    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf16le_to_ucs4_length(const uint8_t* frm, const uint8_t* frm_end, +                       size_t mx, unsigned long Maxcode = 0x10FFFF, +                       codecvt_mode mode = codecvt_mode(0)) +{ +    const uint8_t* frm_nxt = frm; +    frm_nxt = frm; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) +            frm_nxt += 2; +    } +    for (size_t nchar32_t = 0; frm_nxt < frm_end - 1 && nchar32_t < mx; ++nchar32_t) +    { +        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); +        if ((c1 & 0xFC00) == 0xDC00) +            break; +        if ((c1 & 0xFC00) != 0xD800) +        { +            if (c1 > Maxcode) +                break; +            frm_nxt += 2; +        } +        else +        { +            if (frm_end-frm_nxt < 4) +                break; +            uint16_t c2 = static_cast<uint16_t>(frm_nxt[3] << 8 | frm_nxt[2]); +            if ((c2 & 0xFC00) != 0xDC00) +                break; +            uint32_t t = static_cast<uint32_t>( +                    ((((c1 & 0x03C0) >> 6) + 1) << 16) +                  |   ((c1 & 0x003F) << 10) +                  |    (c2 & 0x03FF)); +            if (t > Maxcode) +                break; +            frm_nxt += 4; +        } +    } +    return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs2_to_utf16be(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, +                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, +                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & generate_header) +    { +        if (to_end-to_nxt < 2) +            return codecvt_base::partial; +        *to_nxt++ = static_cast<uint8_t>(0xFE); +        *to_nxt++ = static_cast<uint8_t>(0xFF); +    } +    for (; frm_nxt < frm_end; ++frm_nxt) +    { +        uint16_t wc = *frm_nxt; +        if ((wc & 0xF800) == 0xD800 || wc > Maxcode) +            return codecvt_base::error; +        if (to_end-to_nxt < 2) +            return codecvt_base::partial; +        *to_nxt++ = static_cast<uint8_t>(wc >> 8); +        *to_nxt++ = static_cast<uint8_t>(wc); +    } +    return codecvt_base::ok; +} + +static +codecvt_base::result +utf16be_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, +                uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, +                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) +            frm_nxt += 2; +    } +    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) +    { +        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); +        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) +            return codecvt_base::error; +        *to_nxt = c1; +        frm_nxt += 2; +    } +    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf16be_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, +                       size_t mx, unsigned long Maxcode = 0x10FFFF, +                       codecvt_mode mode = codecvt_mode(0)) +{ +    const uint8_t* frm_nxt = frm; +    frm_nxt = frm; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFE && frm_nxt[1] == 0xFF) +            frm_nxt += 2; +    } +    for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) +    { +        uint16_t c1 = static_cast<uint16_t>(frm_nxt[0] << 8 | frm_nxt[1]); +        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) +            break; +        frm_nxt += 2; +    } +    return static_cast<int>(frm_nxt - frm); +} + +static +codecvt_base::result +ucs2_to_utf16le(const uint16_t* frm, const uint16_t* frm_end, const uint16_t*& frm_nxt, +                uint8_t* to, uint8_t* to_end, uint8_t*& to_nxt, +                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & generate_header) +    { +        if (to_end-to_nxt < 2) +            return codecvt_base::partial; +        *to_nxt++ = static_cast<uint8_t>(0xFF); +        *to_nxt++ = static_cast<uint8_t>(0xFE); +    } +    for (; frm_nxt < frm_end; ++frm_nxt) +    { +        uint16_t wc = *frm_nxt; +        if ((wc & 0xF800) == 0xD800 || wc > Maxcode) +            return codecvt_base::error; +        if (to_end-to_nxt < 2) +            return codecvt_base::partial; +        *to_nxt++ = static_cast<uint8_t>(wc); +        *to_nxt++ = static_cast<uint8_t>(wc >> 8); +    } +    return codecvt_base::ok; +} + +static +codecvt_base::result +utf16le_to_ucs2(const uint8_t* frm, const uint8_t* frm_end, const uint8_t*& frm_nxt, +                uint16_t* to, uint16_t* to_end, uint16_t*& to_nxt, +                unsigned long Maxcode = 0x10FFFF, codecvt_mode mode = codecvt_mode(0)) +{ +    frm_nxt = frm; +    to_nxt = to; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) +            frm_nxt += 2; +    } +    for (; frm_nxt < frm_end - 1 && to_nxt < to_end; ++to_nxt) +    { +        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); +        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) +            return codecvt_base::error; +        *to_nxt = c1; +        frm_nxt += 2; +    } +    return frm_nxt < frm_end ? codecvt_base::partial : codecvt_base::ok; +} + +static +int +utf16le_to_ucs2_length(const uint8_t* frm, const uint8_t* frm_end, +                       size_t mx, unsigned long Maxcode = 0x10FFFF, +                       codecvt_mode mode = codecvt_mode(0)) +{ +    const uint8_t* frm_nxt = frm; +    frm_nxt = frm; +    if (mode & consume_header) +    { +        if (frm_end-frm_nxt >= 2 && frm_nxt[0] == 0xFF && frm_nxt[1] == 0xFE) +            frm_nxt += 2; +    } +    for (size_t nchar16_t = 0; frm_nxt < frm_end - 1 && nchar16_t < mx; ++nchar16_t) +    { +        uint16_t c1 = static_cast<uint16_t>(frm_nxt[1] << 8 | frm_nxt[0]); +        if ((c1 & 0xF800) == 0xD800 || c1 > Maxcode) +            break; +        frm_nxt += 2; +    } +    return static_cast<int>(frm_nxt - frm); +} + +// template <> class codecvt<char16_t, char, mbstate_t> + +locale::id codecvt<char16_t, char, mbstate_t>::id; + +codecvt<char16_t, char, mbstate_t>::~codecvt() +{ +} + +codecvt<char16_t, char, mbstate_t>::result +codecvt<char16_t, char, mbstate_t>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); +    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); +    const uint16_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +codecvt<char16_t, char, mbstate_t>::result +codecvt<char16_t, char, mbstate_t>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint16_t* _to = reinterpret_cast<uint16_t*>(to); +    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); +    uint16_t* _to_nxt = _to; +    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +codecvt<char16_t, char, mbstate_t>::result +codecvt<char16_t, char, mbstate_t>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +codecvt<char16_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +codecvt<char16_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +codecvt<char16_t, char, mbstate_t>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf8_to_utf16_length(_frm, _frm_end, mx); +} + +int +codecvt<char16_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT +{ +    return 4; +} + +// template <> class codecvt<char32_t, char, mbstate_t> + +locale::id codecvt<char32_t, char, mbstate_t>::id; + +codecvt<char32_t, char, mbstate_t>::~codecvt() +{ +} + +codecvt<char32_t, char, mbstate_t>::result +codecvt<char32_t, char, mbstate_t>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); +    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); +    const uint32_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +codecvt<char32_t, char, mbstate_t>::result +codecvt<char32_t, char, mbstate_t>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint32_t* _to = reinterpret_cast<uint32_t*>(to); +    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); +    uint32_t* _to_nxt = _to; +    result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +codecvt<char32_t, char, mbstate_t>::result +codecvt<char32_t, char, mbstate_t>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +codecvt<char32_t, char, mbstate_t>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +codecvt<char32_t, char, mbstate_t>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +codecvt<char32_t, char, mbstate_t>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf8_to_ucs4_length(_frm, _frm_end, mx); +} + +int +codecvt<char32_t, char, mbstate_t>::do_max_length() const  _NOEXCEPT +{ +    return 4; +} + +// __codecvt_utf8<wchar_t> + +__codecvt_utf8<wchar_t>::result +__codecvt_utf8<wchar_t>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); +    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); +    const uint32_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                            _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8<wchar_t>::result +__codecvt_utf8<wchar_t>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint32_t* _to = reinterpret_cast<uint32_t*>(to); +    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); +    uint32_t* _to_nxt = _to; +    result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                            _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8<wchar_t>::result +__codecvt_utf8<wchar_t>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf8<wchar_t>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf8<wchar_t>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf8<wchar_t>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf8<wchar_t>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 7; +    return 4; +} + +// __codecvt_utf8<char16_t> + +__codecvt_utf8<char16_t>::result +__codecvt_utf8<char16_t>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); +    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); +    const uint16_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = ucs2_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                            _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8<char16_t>::result +__codecvt_utf8<char16_t>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint16_t* _to = reinterpret_cast<uint16_t*>(to); +    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); +    uint16_t* _to_nxt = _to; +    result r = utf8_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                            _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8<char16_t>::result +__codecvt_utf8<char16_t>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf8<char16_t>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf8<char16_t>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf8<char16_t>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf8_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf8<char16_t>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 6; +    return 3; +} + +// __codecvt_utf8<char32_t> + +__codecvt_utf8<char32_t>::result +__codecvt_utf8<char32_t>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); +    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); +    const uint32_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = ucs4_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                            _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8<char32_t>::result +__codecvt_utf8<char32_t>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint32_t* _to = reinterpret_cast<uint32_t*>(to); +    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); +    uint32_t* _to_nxt = _to; +    result r = utf8_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                            _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8<char32_t>::result +__codecvt_utf8<char32_t>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf8<char32_t>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf8<char32_t>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf8<char32_t>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf8_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf8<char32_t>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 7; +    return 4; +} + +// __codecvt_utf16<wchar_t, false> + +__codecvt_utf16<wchar_t, false>::result +__codecvt_utf16<wchar_t, false>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); +    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); +    const uint32_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<wchar_t, false>::result +__codecvt_utf16<wchar_t, false>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint32_t* _to = reinterpret_cast<uint32_t*>(to); +    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); +    uint32_t* _to_nxt = _to; +    result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<wchar_t, false>::result +__codecvt_utf16<wchar_t, false>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf16<wchar_t, false>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf16<wchar_t, false>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf16<wchar_t, false>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf16<wchar_t, false>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 6; +    return 4; +} + +// __codecvt_utf16<wchar_t, true> + +__codecvt_utf16<wchar_t, true>::result +__codecvt_utf16<wchar_t, true>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); +    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); +    const uint32_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<wchar_t, true>::result +__codecvt_utf16<wchar_t, true>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint32_t* _to = reinterpret_cast<uint32_t*>(to); +    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); +    uint32_t* _to_nxt = _to; +    result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<wchar_t, true>::result +__codecvt_utf16<wchar_t, true>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf16<wchar_t, true>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf16<wchar_t, true>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf16<wchar_t, true>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf16<wchar_t, true>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 6; +    return 4; +} + +// __codecvt_utf16<char16_t, false> + +__codecvt_utf16<char16_t, false>::result +__codecvt_utf16<char16_t, false>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); +    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); +    const uint16_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = ucs2_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<char16_t, false>::result +__codecvt_utf16<char16_t, false>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint16_t* _to = reinterpret_cast<uint16_t*>(to); +    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); +    uint16_t* _to_nxt = _to; +    result r = utf16be_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<char16_t, false>::result +__codecvt_utf16<char16_t, false>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf16<char16_t, false>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf16<char16_t, false>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf16<char16_t, false>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf16be_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf16<char16_t, false>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 4; +    return 2; +} + +// __codecvt_utf16<char16_t, true> + +__codecvt_utf16<char16_t, true>::result +__codecvt_utf16<char16_t, true>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); +    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); +    const uint16_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = ucs2_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<char16_t, true>::result +__codecvt_utf16<char16_t, true>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint16_t* _to = reinterpret_cast<uint16_t*>(to); +    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); +    uint16_t* _to_nxt = _to; +    result r = utf16le_to_ucs2(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<char16_t, true>::result +__codecvt_utf16<char16_t, true>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf16<char16_t, true>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf16<char16_t, true>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf16<char16_t, true>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf16le_to_ucs2_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf16<char16_t, true>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 4; +    return 2; +} + +// __codecvt_utf16<char32_t, false> + +__codecvt_utf16<char32_t, false>::result +__codecvt_utf16<char32_t, false>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); +    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); +    const uint32_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = ucs4_to_utf16be(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<char32_t, false>::result +__codecvt_utf16<char32_t, false>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint32_t* _to = reinterpret_cast<uint32_t*>(to); +    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); +    uint32_t* _to_nxt = _to; +    result r = utf16be_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<char32_t, false>::result +__codecvt_utf16<char32_t, false>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf16<char32_t, false>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf16<char32_t, false>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf16<char32_t, false>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf16be_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf16<char32_t, false>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 6; +    return 4; +} + +// __codecvt_utf16<char32_t, true> + +__codecvt_utf16<char32_t, true>::result +__codecvt_utf16<char32_t, true>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); +    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); +    const uint32_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = ucs4_to_utf16le(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<char32_t, true>::result +__codecvt_utf16<char32_t, true>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint32_t* _to = reinterpret_cast<uint32_t*>(to); +    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); +    uint32_t* _to_nxt = _to; +    result r = utf16le_to_ucs4(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                               _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf16<char32_t, true>::result +__codecvt_utf16<char32_t, true>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf16<char32_t, true>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf16<char32_t, true>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf16<char32_t, true>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf16le_to_ucs4_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf16<char32_t, true>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 6; +    return 4; +} + +// __codecvt_utf8_utf16<wchar_t> + +__codecvt_utf8_utf16<wchar_t>::result +__codecvt_utf8_utf16<wchar_t>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); +    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); +    const uint32_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                             _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8_utf16<wchar_t>::result +__codecvt_utf8_utf16<wchar_t>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint32_t* _to = reinterpret_cast<uint32_t*>(to); +    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); +    uint32_t* _to_nxt = _to; +    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                             _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8_utf16<wchar_t>::result +__codecvt_utf8_utf16<wchar_t>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf8_utf16<wchar_t>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf8_utf16<wchar_t>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf8_utf16<wchar_t>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf8_utf16<wchar_t>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 7; +    return 4; +} + +// __codecvt_utf8_utf16<char16_t> + +__codecvt_utf8_utf16<char16_t>::result +__codecvt_utf8_utf16<char16_t>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint16_t* _frm = reinterpret_cast<const uint16_t*>(frm); +    const uint16_t* _frm_end = reinterpret_cast<const uint16_t*>(frm_end); +    const uint16_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                             _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8_utf16<char16_t>::result +__codecvt_utf8_utf16<char16_t>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint16_t* _to = reinterpret_cast<uint16_t*>(to); +    uint16_t* _to_end = reinterpret_cast<uint16_t*>(to_end); +    uint16_t* _to_nxt = _to; +    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                             _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8_utf16<char16_t>::result +__codecvt_utf8_utf16<char16_t>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf8_utf16<char16_t>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf8_utf16<char16_t>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf8_utf16<char16_t>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf8_utf16<char16_t>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 7; +    return 4; +} + +// __codecvt_utf8_utf16<char32_t> + +__codecvt_utf8_utf16<char32_t>::result +__codecvt_utf8_utf16<char32_t>::do_out(state_type&, +    const intern_type* frm, const intern_type* frm_end, const intern_type*& frm_nxt, +    extern_type* to, extern_type* to_end, extern_type*& to_nxt) const +{ +    const uint32_t* _frm = reinterpret_cast<const uint32_t*>(frm); +    const uint32_t* _frm_end = reinterpret_cast<const uint32_t*>(frm_end); +    const uint32_t* _frm_nxt = _frm; +    uint8_t* _to = reinterpret_cast<uint8_t*>(to); +    uint8_t* _to_end = reinterpret_cast<uint8_t*>(to_end); +    uint8_t* _to_nxt = _to; +    result r = utf16_to_utf8(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                             _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8_utf16<char32_t>::result +__codecvt_utf8_utf16<char32_t>::do_in(state_type&, +    const extern_type* frm, const extern_type* frm_end, const extern_type*& frm_nxt, +    intern_type* to, intern_type* to_end, intern_type*& to_nxt) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    const uint8_t* _frm_nxt = _frm; +    uint32_t* _to = reinterpret_cast<uint32_t*>(to); +    uint32_t* _to_end = reinterpret_cast<uint32_t*>(to_end); +    uint32_t* _to_nxt = _to; +    result r = utf8_to_utf16(_frm, _frm_end, _frm_nxt, _to, _to_end, _to_nxt, +                             _Maxcode_, _Mode_); +    frm_nxt = frm + (_frm_nxt - _frm); +    to_nxt = to + (_to_nxt - _to); +    return r; +} + +__codecvt_utf8_utf16<char32_t>::result +__codecvt_utf8_utf16<char32_t>::do_unshift(state_type&, +    extern_type* to, extern_type*, extern_type*& to_nxt) const +{ +    to_nxt = to; +    return noconv; +} + +int +__codecvt_utf8_utf16<char32_t>::do_encoding() const  _NOEXCEPT +{ +    return 0; +} + +bool +__codecvt_utf8_utf16<char32_t>::do_always_noconv() const  _NOEXCEPT +{ +    return false; +} + +int +__codecvt_utf8_utf16<char32_t>::do_length(state_type&, +    const extern_type* frm, const extern_type* frm_end, size_t mx) const +{ +    const uint8_t* _frm = reinterpret_cast<const uint8_t*>(frm); +    const uint8_t* _frm_end = reinterpret_cast<const uint8_t*>(frm_end); +    return utf8_to_utf16_length(_frm, _frm_end, mx, _Maxcode_, _Mode_); +} + +int +__codecvt_utf8_utf16<char32_t>::do_max_length() const  _NOEXCEPT +{ +    if (_Mode_ & consume_header) +        return 7; +    return 4; +} + +// __narrow_to_utf8<16> + +__narrow_to_utf8<16>::~__narrow_to_utf8() +{ +} + +// __narrow_to_utf8<32> + +__narrow_to_utf8<32>::~__narrow_to_utf8() +{ +} + +// __widen_from_utf8<16> + +__widen_from_utf8<16>::~__widen_from_utf8() +{ +} + +// __widen_from_utf8<32> + +__widen_from_utf8<32>::~__widen_from_utf8() +{ +} + +// 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) +    { +        __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (loc == nullptr) +            throw runtime_error("numpunct_byname<char>::numpunct_byname" +                                " failed to construct for " + string(nm)); +#endif  // _LIBCPP_NO_EXCEPTIONS +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        lconv* lc = localeconv_l(loc.get()); +#else +        lconv* lc = __localeconv_l(loc.get()); +#endif +        if (*lc->decimal_point) +            __decimal_point_ = *lc->decimal_point; +        if (*lc->thousands_sep) +            __thousands_sep_ = *lc->thousands_sep; +        __grouping_ = lc->grouping; +        // localization 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) +    { +        __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (loc == nullptr) +            throw runtime_error("numpunct_byname<char>::numpunct_byname" +                                " failed to construct for " + string(nm)); +#endif  // _LIBCPP_NO_EXCEPTIONS +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        lconv* lc = localeconv_l(loc.get()); +#else +        lconv* lc = __localeconv_l(loc.get()); +#endif +        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 (static_cast<unsigned>(*__ig) != *__r) +                { +                    __err = ios_base::failbit; +                    return; +                } +            } +            if (__eg - __ig > 1) +                ++__ig; +        } +        if (0 < *__ig && *__ig < numeric_limits<char>::max()) +        { +            if (static_cast<unsigned>(*__ig) < __g_end[-1] || __g_end[-1] == 0) +                __err = ios_base::failbit; +        } +    } +} + +void +__num_put_base::__format_int(char* __fmtp, const char* __len, bool __signd, +                             ios_base::fmtflags __flags) +{ +    if (__flags & ios_base::showpos) +        *__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)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__loc_ == 0) +        throw runtime_error("time_get_byname" +                            " failed to construct for " + string(nm)); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +__time_get::__time_get(const string& nm) +    : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__loc_ == 0) +        throw runtime_error("time_get_byname" +                            " failed to construct for " + nm); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +__time_get::~__time_get() +{ +    freelocale(__loc_); +} + +#pragma clang diagnostic ignored "-Wmissing-field-initializers" + +template <> +string +__time_get_storage<char>::__analyze(char fmt, const ctype<char>& ct) +{ +    tm t = {0}; +    t.tm_sec = 59; +    t.tm_min = 55; +    t.tm_hour = 23; +    t.tm_mday = 31; +    t.tm_mon = 11; +    t.tm_year = 161; +    t.tm_wday = 6; +    t.tm_yday = 364; +    t.tm_isdst = -1; +    char buf[100]; +    char f[3] = {0}; +    f[0] = '%'; +    f[1] = fmt; +    size_t n = strftime_l(buf, 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; +        ptrdiff_t i = __scan_keyword(w, be, this->__weeks_, this->__weeks_+14, +                               ct, err, false) +                               - this->__weeks_; +        if (i < 14) +        { +            result.push_back('%'); +            if (i < 7) +                result.push_back('A'); +            else +                result.push_back('a'); +            bb = w; +            continue; +        } +        w = bb; +        i = __scan_keyword(w, be, this->__months_, this->__months_+24, +                           ct, err, false) +                           - this->__months_; +        if (i < 24) +        { +            result.push_back('%'); +            if (i < 12) +                result.push_back('B'); +            else +                result.push_back('b'); +            if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) +                result.back() = 'm'; +            bb = w; +            continue; +        } +        if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) +        { +            w = bb; +            i = __scan_keyword(w, be, this->__am_pm_, this->__am_pm_+2, +                               ct, err, false) - this->__am_pm_; +            if (i < 2) +            { +                result.push_back('%'); +                result.push_back('p'); +                bb = w; +                continue; +            } +        } +        w = bb; +        if (ct.is(ctype_base::digit, *bb)) +        { +            switch(__get_up_to_n_digits(bb, be, err, ct, 4)) +            { +            case 6: +                result.push_back('%'); +                result.push_back('w'); +                break; +            case 7: +                result.push_back('%'); +                result.push_back('u'); +                break; +            case 11: +                result.push_back('%'); +                result.push_back('I'); +                break; +            case 12: +                result.push_back('%'); +                result.push_back('m'); +                break; +            case 23: +                result.push_back('%'); +                result.push_back('H'); +                break; +            case 31: +                result.push_back('%'); +                result.push_back('d'); +                break; +            case 55: +                result.push_back('%'); +                result.push_back('M'); +                break; +            case 59: +                result.push_back('%'); +                result.push_back('S'); +                break; +            case 61: +                result.push_back('%'); +                result.push_back('y'); +                break; +            case 364: +                result.push_back('%'); +                result.push_back('j'); +                break; +            case 2061: +                result.push_back('%'); +                result.push_back('Y'); +                break; +            default: +                for (; w != bb; ++w) +                    result.push_back(*w); +                break; +            } +            continue; +        } +        if (*bb == '%') +        { +            result.push_back('%'); +            result.push_back('%'); +            ++bb; +            continue; +        } +        result.push_back(*bb); +        ++bb; +    } +    return result; +} + +#pragma clang diagnostic ignored "-Wmissing-braces" + +template <> +wstring +__time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct) +{ +    tm t = {0}; +    t.tm_sec = 59; +    t.tm_min = 55; +    t.tm_hour = 23; +    t.tm_mday = 31; +    t.tm_mon = 11; +    t.tm_year = 161; +    t.tm_wday = 6; +    t.tm_yday = 364; +    t.tm_isdst = -1; +    char buf[100]; +    char f[3] = {0}; +    f[0] = '%'; +    f[1] = fmt; +    strftime_l(buf, 100, f, &t, __loc_); +    wchar_t wbuf[100]; +    wchar_t* wbb = wbuf; +    mbstate_t mb = {0}; +    const char* bb = buf; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    size_t j = mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#else +    size_t j = __mbsrtowcs_l( wbb, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#endif +    if (j == size_t(-1)) +        __throw_runtime_error("locale not supported"); +    wchar_t* wbe = wbb + j; +    wstring result; +    while (wbb != wbe) +    { +        if (ct.is(ctype_base::space, *wbb)) +        { +            result.push_back(L' '); +            for (++wbb; wbb != wbe && ct.is(ctype_base::space, *wbb); ++wbb) +                ; +            continue; +        } +        wchar_t* w = wbb; +        ios_base::iostate err = ios_base::goodbit; +        ptrdiff_t i = __scan_keyword(w, wbe, this->__weeks_, this->__weeks_+14, +                               ct, err, false) +                               - this->__weeks_; +        if (i < 14) +        { +            result.push_back(L'%'); +            if (i < 7) +                result.push_back(L'A'); +            else +                result.push_back(L'a'); +            wbb = w; +            continue; +        } +        w = wbb; +        i = __scan_keyword(w, wbe, this->__months_, this->__months_+24, +                           ct, err, false) +                           - this->__months_; +        if (i < 24) +        { +            result.push_back(L'%'); +            if (i < 12) +                result.push_back(L'B'); +            else +                result.push_back(L'b'); +            if (fmt == 'x' && ct.is(ctype_base::digit, this->__months_[i][0])) +                result.back() = L'm'; +            wbb = w; +            continue; +        } +        if (this->__am_pm_[0].size() + this->__am_pm_[1].size() > 0) +        { +            w = wbb; +            i = __scan_keyword(w, wbe, this->__am_pm_, this->__am_pm_+2, +                               ct, err, false) - this->__am_pm_; +            if (i < 2) +            { +                result.push_back(L'%'); +                result.push_back(L'p'); +                wbb = w; +                continue; +            } +        } +        w = wbb; +        if (ct.is(ctype_base::digit, *wbb)) +        { +            switch(__get_up_to_n_digits(wbb, wbe, err, ct, 4)) +            { +            case 6: +                result.push_back(L'%'); +                result.push_back(L'w'); +                break; +            case 7: +                result.push_back(L'%'); +                result.push_back(L'u'); +                break; +            case 11: +                result.push_back(L'%'); +                result.push_back(L'I'); +                break; +            case 12: +                result.push_back(L'%'); +                result.push_back(L'm'); +                break; +            case 23: +                result.push_back(L'%'); +                result.push_back(L'H'); +                break; +            case 31: +                result.push_back(L'%'); +                result.push_back(L'd'); +                break; +            case 55: +                result.push_back(L'%'); +                result.push_back(L'M'); +                break; +            case 59: +                result.push_back(L'%'); +                result.push_back(L'S'); +                break; +            case 61: +                result.push_back(L'%'); +                result.push_back(L'y'); +                break; +            case 364: +                result.push_back(L'%'); +                result.push_back(L'j'); +                break; +            case 2061: +                result.push_back(L'%'); +                result.push_back(L'Y'); +                break; +            default: +                for (; w != wbb; ++w) +                    result.push_back(*w); +                break; +            } +            continue; +        } +        if (ct.narrow(*wbb, 0) == '%') +        { +            result.push_back(L'%'); +            result.push_back(L'%'); +            ++wbb; +            continue; +        } +        result.push_back(*wbb); +        ++wbb; +    } +    return result; +} + +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; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#else +        size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#endif +        if (j == size_t(-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; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#else +        j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#endif +        if (j == size_t(-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; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#else +        size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#endif +        if (j == size_t(-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; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#else +        j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#endif +        if (j == size_t(-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; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#else +    size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#endif +    if (j == size_t(-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; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#else +    j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, __loc_); +#endif +    if (j == size_t(-1)) +        __throw_runtime_error("locale not supported"); +    wbe = wbuf + j; +    __am_pm_[1].assign(wbuf, wbe); +    __c_ = __analyze('c', ct); +    __r_ = __analyze('r', ct); +    __x_ = __analyze('x', ct); +    __X_ = __analyze('X', ct); +} + +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)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__loc_ == 0) +        throw runtime_error("time_put_byname" +                            " failed to construct for " + string(nm)); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +__time_put::__time_put(const string& nm) +    : __loc_(newlocale(LC_ALL_MASK, nm.c_str(), 0)) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (__loc_ == 0) +        throw runtime_error("time_put_byname" +                            " failed to construct for " + nm); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +__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, static_cast<size_t>(__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; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    size_t j = mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_); +#else +    size_t j = __mbsrtowcs_l(__wb, &__nb, 100, &mb, __loc_); +#endif +    if (j == size_t(-1)) +        __throw_runtime_error("locale not supported"); +    __we = __wb + j; +} + +// moneypunct_byname + +template <class charT> +static +void +__init_pat(money_base::pattern& pat, basic_string<charT>& __curr_symbol_, +           bool intl, char cs_precedes, char sep_by_space, char sign_posn, +           charT space_char) +{ +    const char sign = static_cast<char>(money_base::sign); +    const char space = static_cast<char>(money_base::space); +    const char none = static_cast<char>(money_base::none); +    const char symbol = static_cast<char>(money_base::symbol); +    const char value = static_cast<char>(money_base::value); +    const bool symbol_contains_sep = intl && __curr_symbol_.size() == 4; + +    // Comments on case branches reflect 'C11 7.11.2.1 The localeconv +    // function'. "Space between sign and symbol or value" means that +    // if the sign is adjacent to the symbol, there's a space between +    // them, and otherwise there's a space between the sign and value. +    // +    // C11's localeconv specifies that the fourth character of an +    // international curr_symbol is used to separate the sign and +    // value when sep_by_space says to do so. C++ can't represent +    // that, so we just use a space.  When sep_by_space says to +    // separate the symbol and value-or-sign with a space, we rearrange the +    // curr_symbol to put its spacing character on the correct side of +    // the symbol. +    // +    // We also need to avoid adding an extra space between the sign +    // and value when the currency symbol is suppressed (by not +    // setting showbase).  We match glibc's strfmon by interpreting +    // sep_by_space==1 as "omit the space when the currency symbol is +    // absent". +    // +    // Users who want to get this right should use ICU instead. + +    switch (cs_precedes) +    { +    case 0:  // value before curr_symbol +        if (symbol_contains_sep) { +            // Move the separator to before the symbol, to place it +            // between the value and symbol. +            rotate(__curr_symbol_.begin(), __curr_symbol_.begin() + 3, +                   __curr_symbol_.end()); +        } +        switch (sign_posn) +        { +        case 0:  // Parentheses surround the quantity and currency symbol. +            pat.field[0] = sign; +            pat.field[1] = value; +            pat.field[2] = none;  // Any space appears in the symbol. +            pat.field[3] = symbol; +            switch (sep_by_space) +            { +            case 0:  // No space separates the currency symbol and value. +                // This case may have changed between C99 and C11; +                // assume the currency symbol matches the intention. +            case 2:  // Space between sign and currency or value. +                // The "sign" is two parentheses, so no space here either. +                return; +            case 1:  // Space between currency-and-sign or currency and value. +                if (!symbol_contains_sep) { +                    // We insert the space into the symbol instead of +                    // setting pat.field[2]=space so that when +                    // showbase is not set, the space goes away too. +                    __curr_symbol_.insert(0, 1, space_char); +                } +                return; +            default: +                break; +            } +            break; +        case 1:  // The sign string precedes the quantity and currency symbol. +            pat.field[0] = sign; +            pat.field[3] = symbol; +            switch (sep_by_space) +            { +            case 0:  // No space separates the currency symbol and value. +                pat.field[1] = value; +                pat.field[2] = none; +                return; +            case 1:  // Space between currency-and-sign or currency and value. +                pat.field[1] = value; +                pat.field[2] = none; +                if (!symbol_contains_sep) { +                    // We insert the space into the symbol instead of +                    // setting pat.field[2]=space so that when +                    // showbase is not set, the space goes away too. +                    __curr_symbol_.insert(0, 1, space_char); +                } +                return; +            case 2:  // Space between sign and currency or value. +                pat.field[1] = space; +                pat.field[2] = value; +                if (symbol_contains_sep) { +                    // Remove the separator from the symbol, since it +                    // has already appeared after the sign. +                    __curr_symbol_.erase(__curr_symbol_.begin()); +                } +                return; +            default: +                break; +            } +            break; +        case 2:  // The sign string succeeds the quantity and currency symbol. +            pat.field[0] = value; +            pat.field[3] = sign; +            switch (sep_by_space) +            { +            case 0:  // No space separates the currency symbol and value. +                pat.field[1] = none; +                pat.field[2] = symbol; +                return; +            case 1:  // Space between currency-and-sign or currency and value. +                if (!symbol_contains_sep) { +                    // We insert the space into the symbol instead of +                    // setting pat.field[1]=space so that when +                    // showbase is not set, the space goes away too. +                    __curr_symbol_.insert(0, 1, space_char); +                } +                pat.field[1] = none; +                pat.field[2] = symbol; +                return; +            case 2:  // Space between sign and currency or value. +                pat.field[1] = symbol; +                pat.field[2] = space; +                if (symbol_contains_sep) { +                    // Remove the separator from the symbol, since it +                    // should not be removed if showbase is absent. +                    __curr_symbol_.erase(__curr_symbol_.begin()); +                } +                return; +            default: +                break; +            } +            break; +        case 3:  // The sign string immediately precedes the currency symbol. +            pat.field[0] = value; +            pat.field[3] = symbol; +            switch (sep_by_space) +            { +            case 0:  // No space separates the currency symbol and value. +                pat.field[1] = none; +                pat.field[2] = sign; +                return; +            case 1:  // Space between currency-and-sign or currency and value. +                pat.field[1] = space; +                pat.field[2] = sign; +                if (symbol_contains_sep) { +                    // Remove the separator from the symbol, since it +                    // has already appeared before the sign. +                    __curr_symbol_.erase(__curr_symbol_.begin()); +                } +                return; +            case 2:  // Space between sign and currency or value. +                pat.field[1] = sign; +                pat.field[2] = none; +                if (!symbol_contains_sep) { +                    // We insert the space into the symbol instead of +                    // setting pat.field[2]=space so that when +                    // showbase is not set, the space goes away too. +                    __curr_symbol_.insert(0, 1, space_char); +                } +                return; +            default: +                break; +            } +            break; +        case 4:  // The sign string immediately succeeds the currency symbol. +            pat.field[0] = value; +            pat.field[3] = sign; +            switch (sep_by_space) +            { +            case 0:  // No space separates the currency symbol and value. +                pat.field[1] = none; +                pat.field[2] = symbol; +                return; +            case 1:  // Space between currency-and-sign or currency and value. +                pat.field[1] = none; +                pat.field[2] = symbol; +                if (!symbol_contains_sep) { +                    // We insert the space into the symbol instead of +                    // setting pat.field[1]=space so that when +                    // showbase is not set, the space goes away too. +                    __curr_symbol_.insert(0, 1, space_char); +                } +                return; +            case 2:  // Space between sign and currency or value. +                pat.field[1] = symbol; +                pat.field[2] = space; +                if (symbol_contains_sep) { +                    // Remove the separator from the symbol, since it +                    // should not disappear when showbase is absent. +                    __curr_symbol_.erase(__curr_symbol_.begin()); +                } +                return; +            default: +                break; +            } +            break; +        default: +            break; +        } +        break; +    case 1:  // curr_symbol before value +        switch (sign_posn) +        { +        case 0:  // Parentheses surround the quantity and currency symbol. +            pat.field[0] = sign; +            pat.field[1] = symbol; +            pat.field[2] = none;  // Any space appears in the symbol. +            pat.field[3] = value; +            switch (sep_by_space) +            { +            case 0:  // No space separates the currency symbol and value. +                // This case may have changed between C99 and C11; +                // assume the currency symbol matches the intention. +            case 2:  // Space between sign and currency or value. +                // The "sign" is two parentheses, so no space here either. +                return; +            case 1:  // Space between currency-and-sign or currency and value. +                if (!symbol_contains_sep) { +                    // We insert the space into the symbol instead of +                    // setting pat.field[2]=space so that when +                    // showbase is not set, the space goes away too. +                    __curr_symbol_.insert(0, 1, space_char); +                } +                return; +            default: +                break; +            } +            break; +        case 1:  // The sign string precedes the quantity and currency symbol. +            pat.field[0] = sign; +            pat.field[3] = value; +            switch (sep_by_space) +            { +            case 0:  // No space separates the currency symbol and value. +                pat.field[1] = symbol; +                pat.field[2] = none; +                return; +            case 1:  // Space between currency-and-sign or currency and value. +                pat.field[1] = symbol; +                pat.field[2] = none; +                if (!symbol_contains_sep) { +                    // We insert the space into the symbol instead of +                    // setting pat.field[2]=space so that when +                    // showbase is not set, the space goes away too. +                    __curr_symbol_.push_back(space_char); +                } +                return; +            case 2:  // Space between sign and currency or value. +                pat.field[1] = space; +                pat.field[2] = symbol; +                if (symbol_contains_sep) { +                    // Remove the separator from the symbol, since it +                    // has already appeared after the sign. +                    __curr_symbol_.pop_back(); +                } +                return; +            default: +                break; +            } +            break; +        case 2:  // The sign string succeeds the quantity and currency symbol. +            pat.field[0] = symbol; +            pat.field[3] = sign; +            switch (sep_by_space) +            { +            case 0:  // No space separates the currency symbol and value. +                pat.field[1] = none; +                pat.field[2] = value; +                return; +            case 1:  // Space between currency-and-sign or currency and value. +                pat.field[1] = none; +                pat.field[2] = value; +                if (!symbol_contains_sep) { +                    // We insert the space into the symbol instead of +                    // setting pat.field[1]=space so that when +                    // showbase is not set, the space goes away too. +                    __curr_symbol_.push_back(space_char); +                } +                return; +            case 2:  // Space between sign and currency or value. +                pat.field[1] = value; +                pat.field[2] = space; +                if (symbol_contains_sep) { +                    // Remove the separator from the symbol, since it +                    // will appear before the sign. +                    __curr_symbol_.pop_back(); +                } +                return; +            default: +                break; +            } +            break; +        case 3:  // The sign string immediately precedes the currency symbol. +            pat.field[0] = sign; +            pat.field[3] = value; +            switch (sep_by_space) +            { +            case 0:  // No space separates the currency symbol and value. +                pat.field[1] = symbol; +                pat.field[2] = none; +                return; +            case 1:  // Space between currency-and-sign or currency and value. +                pat.field[1] = symbol; +                pat.field[2] = none; +                if (!symbol_contains_sep) { +                    // We insert the space into the symbol instead of +                    // setting pat.field[2]=space so that when +                    // showbase is not set, the space goes away too. +                    __curr_symbol_.push_back(space_char); +                } +                return; +            case 2:  // Space between sign and currency or value. +                pat.field[1] = space; +                pat.field[2] = symbol; +                if (symbol_contains_sep) { +                    // Remove the separator from the symbol, since it +                    // has already appeared after the sign. +                    __curr_symbol_.pop_back(); +                } +                return; +            default: +                break; +            } +            break; +        case 4:  // The sign string immediately succeeds the currency symbol. +            pat.field[0] = symbol; +            pat.field[3] = value; +            switch (sep_by_space) +            { +            case 0:  // No space separates the currency symbol and value. +                pat.field[1] = sign; +                pat.field[2] = none; +                return; +            case 1:  // Space between currency-and-sign or currency and value. +                pat.field[1] = sign; +                pat.field[2] = space; +                if (symbol_contains_sep) { +                    // Remove the separator from the symbol, since it +                    // should not disappear when showbase is absent. +                    __curr_symbol_.pop_back(); +                } +                return; +            case 2:  // Space between sign and currency or value. +                pat.field[1] = none; +                pat.field[2] = sign; +                if (!symbol_contains_sep) { +                    // We insert the space into the symbol instead of +                    // setting pat.field[1]=space so that when +                    // showbase is not set, the space goes away too. +                    __curr_symbol_.push_back(space_char); +                } +                return; +           default: +                break; +            } +            break; +        default: +            break; +        } +        break; +    default: +        break; +    } +    pat.field[0] = symbol; +    pat.field[1] = sign; +    pat.field[2] = none; +    pat.field[3] = value; +} + +template<> +void +moneypunct_byname<char, false>::init(const char* nm) +{ +    typedef moneypunct<char, false> base; +    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (loc == nullptr) +        throw runtime_error("moneypunct_byname" +                            " failed to construct for " + string(nm)); +#endif  // _LIBCPP_NO_EXCEPTIONS +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    lconv* lc = localeconv_l(loc.get()); +#else +    lconv* lc = __localeconv_l(loc.get()); +#endif +    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; +    // Assume the positive and negative formats will want spaces in +    // the same places in curr_symbol since there's no way to +    // represent anything else. +    string_type __dummy_curr_symbol = __curr_symbol_; +    __init_pat(__pos_format_, __dummy_curr_symbol, false, +               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); +    __init_pat(__neg_format_, __curr_symbol_, false, +               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); +} + +template<> +void +moneypunct_byname<char, true>::init(const char* nm) +{ +    typedef moneypunct<char, true> base; +    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (loc == nullptr) +        throw runtime_error("moneypunct_byname" +                            " failed to construct for " + string(nm)); +#endif  // _LIBCPP_NO_EXCEPTIONS +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    lconv* lc = localeconv_l(loc.get()); +#else +    lconv* lc = __localeconv_l(loc.get()); +#endif +    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 _WIN32 +    if (lc->p_sign_posn == 0) +#else // _WIN32 +    if (lc->int_p_sign_posn == 0) +#endif //_WIN32 +        __positive_sign_ = "()"; +    else +        __positive_sign_ = lc->positive_sign; +#if _WIN32 +    if(lc->n_sign_posn == 0) +#else // _WIN32 +    if (lc->int_n_sign_posn == 0) +#endif // _WIN32 +        __negative_sign_ = "()"; +    else +        __negative_sign_ = lc->negative_sign; +    // Assume the positive and negative formats will want spaces in +    // the same places in curr_symbol since there's no way to +    // represent anything else. +    string_type __dummy_curr_symbol = __curr_symbol_; +#if _WIN32 +    __init_pat(__pos_format_, __dummy_curr_symbol, true, +               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, ' '); +    __init_pat(__neg_format_, __curr_symbol_, true, +               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, ' '); +#else +    __init_pat(__pos_format_, __dummy_curr_symbol, true, +               lc->int_p_cs_precedes, lc->int_p_sep_by_space, +               lc->int_p_sign_posn, ' '); +    __init_pat(__neg_format_, __curr_symbol_, true, +               lc->int_n_cs_precedes, lc->int_n_sep_by_space, +               lc->int_n_sign_posn, ' '); +#endif // _WIN32 +} + +template<> +void +moneypunct_byname<wchar_t, false>::init(const char* nm) +{ +    typedef moneypunct<wchar_t, false> base; +    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (loc == nullptr) +        throw runtime_error("moneypunct_byname" +                            " failed to construct for " + string(nm)); +#endif  // _LIBCPP_NO_EXCEPTIONS +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    lconv* lc = localeconv_l(loc.get()); +#else +    lconv* lc = __localeconv_l(loc.get()); +#endif +    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; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#else +    size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#endif +    if (j == size_t(-1)) +        __throw_runtime_error("locale not supported"); +    wchar_t* wbe = wbuf + j; +    __curr_symbol_.assign(wbuf, wbe); +    if (lc->frac_digits != CHAR_MAX) +        __frac_digits_ = lc->frac_digits; +    else +        __frac_digits_ = base::do_frac_digits(); +    if (lc->p_sign_posn == 0) +        __positive_sign_ = L"()"; +    else +    { +        mb = mbstate_t(); +        bb = lc->positive_sign; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#else +        j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#endif +        if (j == size_t(-1)) +            __throw_runtime_error("locale not supported"); +        wbe = wbuf + j; +        __positive_sign_.assign(wbuf, wbe); +    } +    if (lc->n_sign_posn == 0) +        __negative_sign_ = L"()"; +    else +    { +        mb = mbstate_t(); +        bb = lc->negative_sign; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#else +        j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#endif +        if (j == size_t(-1)) +            __throw_runtime_error("locale not supported"); +        wbe = wbuf + j; +        __negative_sign_.assign(wbuf, wbe); +    } +    // Assume the positive and negative formats will want spaces in +    // the same places in curr_symbol since there's no way to +    // represent anything else. +    string_type __dummy_curr_symbol = __curr_symbol_; +    __init_pat(__pos_format_, __dummy_curr_symbol, false, +               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); +    __init_pat(__neg_format_, __curr_symbol_, false, +               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); +} + +template<> +void +moneypunct_byname<wchar_t, true>::init(const char* nm) +{ +    typedef moneypunct<wchar_t, true> base; +    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (loc == nullptr) +        throw runtime_error("moneypunct_byname" +                            " failed to construct for " + string(nm)); +#endif  // _LIBCPP_NO_EXCEPTIONS +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    lconv* lc = localeconv_l(loc.get()); +#else +    lconv* lc = __localeconv_l(loc.get()); +#endif +    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; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +    size_t j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#else +    size_t j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#endif +    if (j == size_t(-1)) +        __throw_runtime_error("locale not supported"); +    wchar_t* wbe = wbuf + j; +    __curr_symbol_.assign(wbuf, wbe); +    if (lc->int_frac_digits != CHAR_MAX) +        __frac_digits_ = lc->int_frac_digits; +    else +        __frac_digits_ = base::do_frac_digits(); +#if _WIN32 +    if (lc->p_sign_posn == 0) +#else // _WIN32 +    if (lc->int_p_sign_posn == 0) +#endif // _WIN32 +        __positive_sign_ = L"()"; +    else +    { +        mb = mbstate_t(); +        bb = lc->positive_sign; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#else +        j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#endif +        if (j == size_t(-1)) +            __throw_runtime_error("locale not supported"); +        wbe = wbuf + j; +        __positive_sign_.assign(wbuf, wbe); +    } +#if _WIN32 +    if (lc->n_sign_posn == 0) +#else // _WIN32 +    if (lc->int_n_sign_posn == 0) +#endif // _WIN32 +        __negative_sign_ = L"()"; +    else +    { +        mb = mbstate_t(); +        bb = lc->negative_sign; +#ifdef _LIBCPP_LOCALE__L_EXTENSIONS +        j = mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#else +        j = __mbsrtowcs_l(wbuf, &bb, sizeof(wbuf)/sizeof(wbuf[0]), &mb, loc.get()); +#endif +        if (j == size_t(-1)) +            __throw_runtime_error("locale not supported"); +        wbe = wbuf + j; +        __negative_sign_.assign(wbuf, wbe); +    } +    // Assume the positive and negative formats will want spaces in +    // the same places in curr_symbol since there's no way to +    // represent anything else. +    string_type __dummy_curr_symbol = __curr_symbol_; +#if _WIN32 +    __init_pat(__pos_format_, __dummy_curr_symbol, true, +               lc->p_cs_precedes, lc->p_sep_by_space, lc->p_sign_posn, L' '); +    __init_pat(__neg_format_, __curr_symbol_, true, +               lc->n_cs_precedes, lc->n_sep_by_space, lc->n_sign_posn, L' '); +#else // _WIN32 +    __init_pat(__pos_format_, __dummy_curr_symbol, true, +               lc->int_p_cs_precedes, lc->int_p_sep_by_space, +               lc->int_p_sign_posn, L' '); +    __init_pat(__neg_format_, __curr_symbol_, true, +               lc->int_n_cs_precedes, lc->int_n_sep_by_space, +               lc->int_n_sign_posn, L' '); +#endif // _WIN32 +} + +void __do_nothing(void*) {} + +void __throw_runtime_error(const char* msg) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    throw runtime_error(msg); +#endif +} + +template class collate<char>; +template class collate<wchar_t>; + +template class num_get<char>; +template class num_get<wchar_t>; + +template struct __num_get<char>; +template struct __num_get<wchar_t>; + +template class num_put<char>; +template class num_put<wchar_t>; + +template struct __num_put<char>; +template struct __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/contrib/libc++/src/memory.cpp b/contrib/libc++/src/memory.cpp new file mode 100644 index 000000000000..a892e75c86d0 --- /dev/null +++ b/contrib/libc++/src/memory.cpp @@ -0,0 +1,165 @@ +//===------------------------ memory.cpp ----------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "memory" + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace +{ + +template <class T> +inline T +increment(T& t) _NOEXCEPT +{ +    return __sync_add_and_fetch(&t, 1); +} + +template <class T> +inline T +decrement(T& t) _NOEXCEPT +{ +    return __sync_add_and_fetch(&t, -1); +} + +}  // namespace + +const allocator_arg_t allocator_arg = allocator_arg_t(); + +bad_weak_ptr::~bad_weak_ptr() _NOEXCEPT {} + +const char* +bad_weak_ptr::what() const _NOEXCEPT +{ +    return "bad_weak_ptr"; +} + +__shared_count::~__shared_count() +{ +} + +void +__shared_count::__add_shared() _NOEXCEPT +{ +    increment(__shared_owners_); +} + +bool +__shared_count::__release_shared() _NOEXCEPT +{ +    if (decrement(__shared_owners_) == -1) +    { +        __on_zero_shared(); +        return true; +    } +    return false; +} + +__shared_weak_count::~__shared_weak_count() +{ +} + +void +__shared_weak_count::__add_shared() _NOEXCEPT +{ +    __shared_count::__add_shared(); +} + +void +__shared_weak_count::__add_weak() _NOEXCEPT +{ +    increment(__shared_weak_owners_); +} + +void +__shared_weak_count::__release_shared() _NOEXCEPT +{ +    if (__shared_count::__release_shared()) +        __release_weak(); +} + +void +__shared_weak_count::__release_weak() _NOEXCEPT +{ +    if (decrement(__shared_weak_owners_) == -1) +        __on_zero_shared_weak(); +} + +__shared_weak_count* +__shared_weak_count::lock() _NOEXCEPT +{ +    long object_owners = __shared_owners_; +    while (object_owners != -1) +    { +        if (__sync_bool_compare_and_swap(&__shared_owners_, +                                         object_owners, +                                         object_owners+1)) +            return this; +        object_owners = __shared_owners_; +    } +    return 0; +} + +#ifndef _LIBCPP_NO_RTTI + +const void* +__shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT +{ +    return 0; +} + +#endif  // _LIBCPP_NO_RTTI + +void +declare_reachable(void*) +{ +} + +void +declare_no_pointers(char*, size_t) +{ +} + +void +undeclare_no_pointers(char*, size_t) +{ +} + +pointer_safety +get_pointer_safety() _NOEXCEPT +{ +    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); +        size_t d = static_cast<size_t>(p2 - p1); +        if (d <= space - size) +        { +            r = p2; +            ptr = r; +            space -= d; +        } +    } +    return r; +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/mutex.cpp b/contrib/libc++/src/mutex.cpp new file mode 100644 index 000000000000..9aa051be37f2 --- /dev/null +++ b/contrib/libc++/src/mutex.cpp @@ -0,0 +1,249 @@ +//===------------------------- mutex.cpp ----------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. 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() +{ +    pthread_mutex_destroy(&__m_); +} + +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_(0) +{ +} + +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_ = 0; +        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) +    { +#ifndef _LIBCPP_NO_EXCEPTIONS +        try +        { +#endif  // _LIBCPP_NO_EXCEPTIONS +            flag = 1; +            pthread_mutex_unlock(&mut); +            func(arg); +            pthread_mutex_lock(&mut); +            flag = ~0ul; +            pthread_mutex_unlock(&mut); +            pthread_cond_broadcast(&cv); +#ifndef _LIBCPP_NO_EXCEPTIONS +        } +        catch (...) +        { +            pthread_mutex_lock(&mut); +            flag = 0ul; +            pthread_mutex_unlock(&mut); +            pthread_cond_broadcast(&cv); +            throw; +        } +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    else +        pthread_mutex_unlock(&mut); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/new.cpp b/contrib/libc++/src/new.cpp new file mode 100644 index 000000000000..1c171a871b9b --- /dev/null +++ b/contrib/libc++/src/new.cpp @@ -0,0 +1,199 @@ +//===--------------------------- new.cpp ----------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdlib.h> + +#include "new" + +#if __APPLE__ +    #include <cxxabi.h> + +    #ifndef _LIBCPPABI_VERSION +        // On Darwin, there are two STL shared libraries and a lower level ABI +        // shared libray.  The global holding the current new handler is +        // in the ABI library and named __cxa_new_handler. +        #define __new_handler __cxxabiapple::__cxa_new_handler +    #endif +#else  // __APPLE__ +    static std::new_handler __new_handler; +#endif + +#if !defined (LIBCXXRT) // && !defined(_LIBCPPABI_VERSION) + +// Implement all new and delete operators as weak definitions +// in this shared library, so that they can be overriden by programs +// that define non-weak copies of the functions. + +__attribute__((__weak__, __visibility__("default"))) +void * +operator new(std::size_t size) +#if !__has_feature(cxx_noexcept) +    throw(std::bad_alloc) +#endif +{ +    if (size == 0) +        size = 1; +    void* p; +    while ((p = ::malloc(size)) == 0) +    { +        // If malloc fails and there is a new_handler, +        // call it to try free up memory. +        std::new_handler nh = std::get_new_handler(); +        if (nh) +            nh(); +        else +#ifndef _LIBCPP_NO_EXCEPTIONS +            throw std::bad_alloc(); +#else +            break; +#endif +    } +    return p; +} + +__attribute__((__weak__, __visibility__("default"))) +void* +operator new(size_t size, const std::nothrow_t&) _NOEXCEPT +{ +    void* p = 0; +#ifndef _LIBCPP_NO_EXCEPTIONS +    try +    { +#endif  // _LIBCPP_NO_EXCEPTIONS +        p = ::operator new(size); +#ifndef _LIBCPP_NO_EXCEPTIONS +    } +    catch (...) +    { +    } +#endif  // _LIBCPP_NO_EXCEPTIONS +    return p; +} + +__attribute__((__weak__, __visibility__("default"))) +void* +operator new[](size_t size) +#if !__has_feature(cxx_noexcept) +    throw(std::bad_alloc) +#endif +{ +    return ::operator new(size); +} + +__attribute__((__weak__, __visibility__("default"))) +void* +operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT +{ +    void* p = 0; +#ifndef _LIBCPP_NO_EXCEPTIONS +    try +    { +#endif  // _LIBCPP_NO_EXCEPTIONS +        p = ::operator new[](size); +#ifndef _LIBCPP_NO_EXCEPTIONS +    } +    catch (...) +    { +    } +#endif  // _LIBCPP_NO_EXCEPTIONS +    return p; +} + +__attribute__((__weak__, __visibility__("default"))) +void +operator delete(void* ptr) _NOEXCEPT +{ +    if (ptr) +        ::free(ptr); +} + +__attribute__((__weak__, __visibility__("default"))) +void +operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT +{ +    ::operator delete(ptr); +} + +__attribute__((__weak__, __visibility__("default"))) +void +operator delete[] (void* ptr) _NOEXCEPT +{ +    ::operator delete (ptr); +} + +__attribute__((__weak__, __visibility__("default"))) +void +operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT +{ +    ::operator delete[](ptr); +} + +#endif  // !_LIBCPPABI_VERSION && !LIBCXXRT + +namespace std +{ + +const nothrow_t nothrow = {}; + +#ifndef _LIBCPPABI_VERSION + +new_handler +set_new_handler(new_handler handler) _NOEXCEPT +{ +    return __sync_lock_test_and_set(&__new_handler, handler); +} + +new_handler +get_new_handler() _NOEXCEPT +{ +    return __sync_fetch_and_add(&__new_handler, (new_handler)0); +} + +#ifndef LIBCXXRT + +bad_alloc::bad_alloc() _NOEXCEPT +{ +} + +bad_alloc::~bad_alloc() _NOEXCEPT +{ +} + +const char* +bad_alloc::what() const _NOEXCEPT +{ +    return "std::bad_alloc"; +} + +bad_array_new_length::bad_array_new_length() _NOEXCEPT +{ +} + +bad_array_new_length::~bad_array_new_length() _NOEXCEPT +{ +} + +const char* +bad_array_new_length::what() const _NOEXCEPT +{ +    return "bad_array_new_length"; +} + +#endif +#endif //LIBCXXRT + +void +__throw_bad_alloc() +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    throw bad_alloc(); +#endif +} + +}  // std diff --git a/contrib/libc++/src/random.cpp b/contrib/libc++/src/random.cpp new file mode 100644 index 000000000000..6140b74ecb5f --- /dev/null +++ b/contrib/libc++/src/random.cpp @@ -0,0 +1,48 @@ +//===-------------------------- random.cpp --------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "random" +#include "system_error" + +#ifdef __sun__ +#define rename solaris_headers_are_broken +#endif +#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/contrib/libc++/src/regex.cpp b/contrib/libc++/src/regex.cpp new file mode 100644 index 000000000000..e3ec2810c774 --- /dev/null +++ b/contrib/libc++/src/regex.cpp @@ -0,0 +1,325 @@ +//===-------------------------- regex.cpp ---------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "regex" +#include "algorithm" +#include "iterator" + +_LIBCPP_BEGIN_NAMESPACE_STD + +static +const char* +make_error_type_string(regex_constants::error_type ecode) +{ +    switch (ecode) +    { +    case regex_constants::error_collate: +        return "The expression contained an invalid collating element name."; +    case regex_constants::error_ctype: +        return "The expression contained an invalid character class name."; +    case regex_constants::error_escape: +        return "The expression contained an invalid escaped character, or a " +               "trailing escape."; +    case regex_constants::error_backref: +        return "The expression contained an invalid back reference."; +    case regex_constants::error_brack: +        return "The expression contained mismatched [ and ]."; +    case regex_constants::error_paren: +        return "The expression contained mismatched ( and )."; +    case regex_constants::error_brace: +        return "The expression contained mismatched { and }."; +    case regex_constants::error_badbrace: +        return "The expression contained an invalid range in a {} expression."; +    case regex_constants::error_range: +        return "The expression contained an invalid character range, " +               "such as [b-a] in most encodings."; +    case regex_constants::error_space: +        return "There was insufficient memory to convert the expression into " +               "a finite state machine."; +    case regex_constants::error_badrepeat: +        return "One of *?+{ was not preceded by a valid regular expression."; +    case regex_constants::error_complexity: +        return "The complexity of an attempted match against a regular " +               "expression exceeded a pre-set level."; +    case regex_constants::error_stack: +        return "There was insufficient memory to determine whether the regular " +               "expression could match the specified character sequence."; +    case regex_constants::__re_err_grammar: +        return "An invalid regex grammar has been requested."; +    case regex_constants::__re_err_empty: +        return "An empty regex is not allowed in the POSIX grammar."; +    default: +        break; +    } +    return "Unknown error type"; +} + +regex_error::regex_error(regex_constants::error_type ecode) +    : runtime_error(make_error_type_string(ecode)), +      __code_(ecode) +{} + +regex_error::~regex_error() throw() {} + +namespace { + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" + +struct collationnames +{ +    const char* elem_; +    char char_; +}; + +#pragma clang diagnostic pop + +const collationnames collatenames[] = +{ +    {"A", 0x41}, +    {"B", 0x42}, +    {"C", 0x43}, +    {"D", 0x44}, +    {"E", 0x45}, +    {"F", 0x46}, +    {"G", 0x47}, +    {"H", 0x48}, +    {"I", 0x49}, +    {"J", 0x4a}, +    {"K", 0x4b}, +    {"L", 0x4c}, +    {"M", 0x4d}, +    {"N", 0x4e}, +    {"NUL", 0x00}, +    {"O", 0x4f}, +    {"P", 0x50}, +    {"Q", 0x51}, +    {"R", 0x52}, +    {"S", 0x53}, +    {"T", 0x54}, +    {"U", 0x55}, +    {"V", 0x56}, +    {"W", 0x57}, +    {"X", 0x58}, +    {"Y", 0x59}, +    {"Z", 0x5a}, +    {"a", 0x61}, +    {"alert", 0x07}, +    {"ampersand", 0x26}, +    {"apostrophe", 0x27}, +    {"asterisk", 0x2a}, +    {"b", 0x62}, +    {"backslash", 0x5c}, +    {"backspace", 0x08}, +    {"c", 0x63}, +    {"carriage-return", 0x0d}, +    {"circumflex", 0x5e}, +    {"circumflex-accent", 0x5e}, +    {"colon", 0x3a}, +    {"comma", 0x2c}, +    {"commercial-at", 0x40}, +    {"d", 0x64}, +    {"dollar-sign", 0x24}, +    {"e", 0x65}, +    {"eight", 0x38}, +    {"equals-sign", 0x3d}, +    {"exclamation-mark", 0x21}, +    {"f", 0x66}, +    {"five", 0x35}, +    {"form-feed", 0x0c}, +    {"four", 0x34}, +    {"full-stop", 0x2e}, +    {"g", 0x67}, +    {"grave-accent", 0x60}, +    {"greater-than-sign", 0x3e}, +    {"h", 0x68}, +    {"hyphen", 0x2d}, +    {"hyphen-minus", 0x2d}, +    {"i", 0x69}, +    {"j", 0x6a}, +    {"k", 0x6b}, +    {"l", 0x6c}, +    {"left-brace", 0x7b}, +    {"left-curly-bracket", 0x7b}, +    {"left-parenthesis", 0x28}, +    {"left-square-bracket", 0x5b}, +    {"less-than-sign", 0x3c}, +    {"low-line", 0x5f}, +    {"m", 0x6d}, +    {"n", 0x6e}, +    {"newline", 0x0a}, +    {"nine", 0x39}, +    {"number-sign", 0x23}, +    {"o", 0x6f}, +    {"one", 0x31}, +    {"p", 0x70}, +    {"percent-sign", 0x25}, +    {"period", 0x2e}, +    {"plus-sign", 0x2b}, +    {"q", 0x71}, +    {"question-mark", 0x3f}, +    {"quotation-mark", 0x22}, +    {"r", 0x72}, +    {"reverse-solidus", 0x5c}, +    {"right-brace", 0x7d}, +    {"right-curly-bracket", 0x7d}, +    {"right-parenthesis", 0x29}, +    {"right-square-bracket", 0x5d}, +    {"s", 0x73}, +    {"semicolon", 0x3b}, +    {"seven", 0x37}, +    {"six", 0x36}, +    {"slash", 0x2f}, +    {"solidus", 0x2f}, +    {"space", 0x20}, +    {"t", 0x74}, +    {"tab", 0x09}, +    {"three", 0x33}, +    {"tilde", 0x7e}, +    {"two", 0x32}, +    {"u", 0x75}, +    {"underscore", 0x5f}, +    {"v", 0x76}, +    {"vertical-line", 0x7c}, +    {"vertical-tab", 0x0b}, +    {"w", 0x77}, +    {"x", 0x78}, +    {"y", 0x79}, +    {"z", 0x7a}, +    {"zero", 0x30} +}; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" + +struct classnames +{ +    const char* elem_; +    ctype_base::mask mask_; +}; + +#pragma clang diagnostic pop + +const classnames ClassNames[] = +{ +    {"alnum",  ctype_base::alnum}, +    {"alpha",  ctype_base::alpha}, +    {"blank",  ctype_base::blank}, +    {"cntrl",  ctype_base::cntrl}, +    {"d",      ctype_base::digit}, +    {"digit",  ctype_base::digit}, +    {"graph",  ctype_base::graph}, +    {"lower",  ctype_base::lower}, +    {"print",  ctype_base::print}, +    {"punct",  ctype_base::punct}, +    {"s",      ctype_base::space}, +    {"space",  ctype_base::space}, +    {"upper",  ctype_base::upper}, +    {"w",      regex_traits<char>::__regex_word}, +    {"xdigit", ctype_base::xdigit} +}; + +struct use_strcmp +{ +    bool operator()(const collationnames& x, const char* y) +        {return strcmp(x.elem_, y) < 0;} +    bool operator()(const classnames& x, const char* y) +        {return strcmp(x.elem_, y) < 0;} +}; + +} + +string +__get_collation_name(const char* s) +{ +    const collationnames* i = +            _VSTD::lower_bound(begin(collatenames), end(collatenames), s, use_strcmp()); +    string r; +    if (i != end(collatenames) && strcmp(s, i->elem_) == 0) +        r = char(i->char_); +    return r; +} + +ctype_base::mask +__get_classname(const char* s, bool __icase) +{ +    const classnames* i = +            _VSTD::lower_bound(begin(ClassNames), end(ClassNames), s, use_strcmp()); +    ctype_base::mask r = 0; +    if (i != end(ClassNames) && strcmp(s, i->elem_) == 0) +    { +        r = i->mask_; +        if (r == regex_traits<char>::__regex_word) +            r |= ctype_base::alnum | ctype_base::upper | ctype_base::lower; +        else if (__icase) +        { +            if (r & (ctype_base::lower | ctype_base::upper)) +                r |= ctype_base::alpha; +        } +    } +    return r; +} + +template <> +void +__match_any_but_newline<char>::__exec(__state& __s) const +{ +    if (__s.__current_ != __s.__last_) +    { +        switch (*__s.__current_) +        { +        case '\r': +        case '\n': +            __s.__do_ = __state::__reject; +            __s.__node_ = nullptr; +            break; +        default: +            __s.__do_ = __state::__accept_and_consume; +            ++__s.__current_; +            __s.__node_ = this->first(); +            break; +        } +    } +    else +    { +        __s.__do_ = __state::__reject; +        __s.__node_ = nullptr; +    } +} + +template <> +void +__match_any_but_newline<wchar_t>::__exec(__state& __s) const +{ +    if (__s.__current_ != __s.__last_) +    { +        switch (*__s.__current_) +        { +        case '\r': +        case '\n': +        case 0x2028: +        case 0x2029: +            __s.__do_ = __state::__reject; +            __s.__node_ = nullptr; +            break; +        default: +            __s.__do_ = __state::__accept_and_consume; +            ++__s.__current_; +            __s.__node_ = this->first(); +            break; +        } +    } +    else +    { +        __s.__do_ = __state::__reject; +        __s.__node_ = nullptr; +    } +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/stdexcept.cpp b/contrib/libc++/src/stdexcept.cpp new file mode 100644 index 000000000000..b516b0ca68b3 --- /dev/null +++ b/contrib/libc++/src/stdexcept.cpp @@ -0,0 +1,187 @@ +//===------------------------ stdexcept.cpp -------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "stdexcept" +#include "new" +#include "string" +#include <cstdlib> +#include <cstring> +#include <cstdint> +#include <cstddef> +#include "system_error" +#include <cxxabi.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 _NOEXCEPT {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 _NOEXCEPT {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_) +{ +    __sync_add_and_fetch(&count(), 1); +} + +__libcpp_nmstr& +__libcpp_nmstr::operator=(const __libcpp_nmstr& s) +{ +    const char* p = str_; +    str_ = s.str_; +    __sync_add_and_fetch(&count(), 1); +    if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0) +        delete [] (p-offset); +    return *this; +} + +inline +__libcpp_nmstr::~__libcpp_nmstr() +{ +    if (__sync_add_and_fetch(&count(), -1) < 0) +        delete [] (str_ - offset); +} + +} + +#pragma GCC visibility 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) _NOEXCEPT +{ +    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; +    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); +} + +logic_error& +logic_error::operator=(const logic_error& le) _NOEXCEPT +{ +    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; +    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; +    s1 = s2; +    return *this; +} + +#ifndef _LIBCPPABI_VERSION + +logic_error::~logic_error() _NOEXCEPT +{ +    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; +    s.~__libcpp_nmstr(); +} + +const char* +logic_error::what() const _NOEXCEPT +{ +    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; +    return s.c_str(); +} + +#endif + +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) _NOEXCEPT +{ +    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; +    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); +} + +runtime_error& +runtime_error::operator=(const runtime_error& le) _NOEXCEPT +{ +    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; +    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; +    s1 = s2; +    return *this; +} + +#ifndef _LIBCPPABI_VERSION + +runtime_error::~runtime_error() _NOEXCEPT +{ +    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; +    s.~__libcpp_nmstr(); +} + +const char* +runtime_error::what() const _NOEXCEPT +{ +    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; +    return s.c_str(); +} + +domain_error::~domain_error() _NOEXCEPT {} +invalid_argument::~invalid_argument() _NOEXCEPT {} +length_error::~length_error() _NOEXCEPT {} +out_of_range::~out_of_range() _NOEXCEPT {} + +range_error::~range_error() _NOEXCEPT {} +overflow_error::~overflow_error() _NOEXCEPT {} +underflow_error::~underflow_error() _NOEXCEPT {} + +#endif + +}  // std diff --git a/contrib/libc++/src/string.cpp b/contrib/libc++/src/string.cpp new file mode 100644 index 000000000000..750ba284e366 --- /dev/null +++ b/contrib/libc++/src/string.cpp @@ -0,0 +1,679 @@ +//===------------------------- string.cpp ---------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "string" +#include "cstdlib" +#include "cwchar" +#include "cerrno" +#if _WIN32 +#include "support/win32/support.h" +#endif // _WIN32 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template class __basic_string_common<true>; + +template class basic_string<char>; +template class basic_string<wchar_t>; + +template +    string +    operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); + +int +stoi(const string& str, size_t* idx, int base) +{ +    char* ptr; +    const char* const p = str.c_str(); +    long r = strtol(p, &ptr, base); +    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) +        ptr = const_cast<char*>(p); +    if (ptr == p) +    { +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (r == 0) +            throw invalid_argument("stoi: no conversion"); +        throw out_of_range("stoi: out of range"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return static_cast<int>(r); +} + +int +stoi(const wstring& str, size_t* idx, int base) +{ +    wchar_t* ptr; +    const wchar_t* const p = str.c_str(); +    long r = wcstol(p, &ptr, base); +    if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) +        ptr = const_cast<wchar_t*>(p); +    if (ptr == p) +    { +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (r == 0) +            throw invalid_argument("stoi: no conversion"); +        throw out_of_range("stoi: out of range"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return static_cast<int>(r); +} + +long +stol(const string& str, size_t* idx, int base) +{ +    char* ptr; +    const char* const p = str.c_str(); +    long r = strtol(p, &ptr, base); +    if (ptr == p) +    { +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (r == 0) +            throw invalid_argument("stol: no conversion"); +        throw out_of_range("stol: out of range"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +long +stol(const wstring& str, size_t* idx, int base) +{ +    wchar_t* ptr; +    const wchar_t* const p = str.c_str(); +    long r = wcstol(p, &ptr, base); +    if (ptr == p) +    { +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (r == 0) +            throw invalid_argument("stol: no conversion"); +        throw out_of_range("stol: out of range"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +unsigned long +stoul(const string& str, size_t* idx, int base) +{ +    char* ptr; +    const char* const p = str.c_str(); +    unsigned long r = strtoul(p, &ptr, base); +    if (ptr == p) +    { +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (r == 0) +            throw invalid_argument("stoul: no conversion"); +        throw out_of_range("stoul: out of range"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +unsigned long +stoul(const wstring& str, size_t* idx, int base) +{ +    wchar_t* ptr; +    const wchar_t* const p = str.c_str(); +    unsigned long r = wcstoul(p, &ptr, base); +    if (ptr == p) +    { +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (r == 0) +            throw invalid_argument("stoul: no conversion"); +        throw out_of_range("stoul: out of range"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +long long +stoll(const string& str, size_t* idx, int base) +{ +    char* ptr; +    const char* const p = str.c_str(); +    long long r = strtoll(p, &ptr, base); +    if (ptr == p) +    { +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (r == 0) +            throw invalid_argument("stoll: no conversion"); +        throw out_of_range("stoll: out of range"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +long long +stoll(const wstring& str, size_t* idx, int base) +{ +    wchar_t* ptr; +    const wchar_t* const p = str.c_str(); +    long long r = wcstoll(p, &ptr, base); +    if (ptr == p) +    { +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (r == 0) +            throw invalid_argument("stoll: no conversion"); +        throw out_of_range("stoll: out of range"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +unsigned long long +stoull(const string& str, size_t* idx, int base) +{ +    char* ptr; +    const char* const p = str.c_str(); +    unsigned long long r = strtoull(p, &ptr, base); +    if (ptr == p) +    { +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (r == 0) +            throw invalid_argument("stoull: no conversion"); +        throw out_of_range("stoull: out of range"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +unsigned long long +stoull(const wstring& str, size_t* idx, int base) +{ +    wchar_t* ptr; +    const wchar_t* const p = str.c_str(); +    unsigned long long r = wcstoull(p, &ptr, base); +    if (ptr == p) +    { +#ifndef _LIBCPP_NO_EXCEPTIONS +        if (r == 0) +            throw invalid_argument("stoull: no conversion"); +        throw out_of_range("stoull: out of range"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    } +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +float +stof(const string& str, size_t* idx) +{ +    char* ptr; +    const char* const p = str.c_str(); +    int errno_save = errno; +    errno = 0; +    double r = strtod(p, &ptr); +    swap(errno, errno_save); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (errno_save == ERANGE) +        throw out_of_range("stof: out of range"); +    if (ptr == p) +        throw invalid_argument("stof: no conversion"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return static_cast<float>(r); +} + +float +stof(const wstring& str, size_t* idx) +{ +    wchar_t* ptr; +    const wchar_t* const p = str.c_str(); +    int errno_save = errno; +    errno = 0; +    double r = wcstod(p, &ptr); +    swap(errno, errno_save); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (errno_save == ERANGE) +        throw out_of_range("stof: out of range"); +    if (ptr == p) +        throw invalid_argument("stof: no conversion"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return static_cast<float>(r); +} + +double +stod(const string& str, size_t* idx) +{ +    char* ptr; +    const char* const p = str.c_str(); +    int errno_save = errno; +    errno = 0; +    double r = strtod(p, &ptr); +    swap(errno, errno_save); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (errno_save == ERANGE) +        throw out_of_range("stod: out of range"); +    if (ptr == p) +        throw invalid_argument("stod: no conversion"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +double +stod(const wstring& str, size_t* idx) +{ +    wchar_t* ptr; +    const wchar_t* const p = str.c_str(); +    int errno_save = errno; +    errno = 0; +    double r = wcstod(p, &ptr); +    swap(errno, errno_save); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (errno_save == ERANGE) +        throw out_of_range("stod: out of range"); +    if (ptr == p) +        throw invalid_argument("stod: no conversion"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +long double +stold(const string& str, size_t* idx) +{ +    char* ptr; +    const char* const p = str.c_str(); +    int errno_save = errno; +    errno = 0; +    long double r = strtold(p, &ptr); +    swap(errno, errno_save); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (errno_save == ERANGE) +        throw out_of_range("stold: out of range"); +    if (ptr == p) +        throw invalid_argument("stold: no conversion"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +long double +stold(const wstring& str, size_t* idx) +{ +    wchar_t* ptr; +    const wchar_t* const p = str.c_str(); +    int errno_save = errno; +    errno = 0; +    long double r = wcstold(p, &ptr); +    swap(errno, errno_save); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (errno_save == ERANGE) +        throw out_of_range("stold: out of range"); +    if (ptr == p) +        throw invalid_argument("stold: no conversion"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    if (idx) +        *idx = static_cast<size_t>(ptr - p); +    return r; +} + +string to_string(int val) +{ +    string s; +    s.resize(s.capacity()); +    while (true) +    { +        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%d", val)); +        if (n2 <= s.size()) +        { +            s.resize(n2); +            break; +        } +        s.resize(n2); +    } +    return s; +} + +string to_string(unsigned val) +{ +    string s; +    s.resize(s.capacity()); +    while (true) +    { +        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%u", val)); +        if (n2 <= s.size()) +        { +            s.resize(n2); +            break; +        } +        s.resize(n2); +    } +    return s; +} + +string to_string(long val) +{ +    string s; +    s.resize(s.capacity()); +    while (true) +    { +        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%ld", val)); +        if (n2 <= s.size()) +        { +            s.resize(n2); +            break; +        } +        s.resize(n2); +    } +    return s; +} + +string to_string(unsigned long val) +{ +    string s; +    s.resize(s.capacity()); +    while (true) +    { +        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%lu", val)); +        if (n2 <= s.size()) +        { +            s.resize(n2); +            break; +        } +        s.resize(n2); +    } +    return s; +} + +string to_string(long long val) +{ +    string s; +    s.resize(s.capacity()); +    while (true) +    { +        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%lld", val)); +        if (n2 <= s.size()) +        { +            s.resize(n2); +            break; +        } +        s.resize(n2); +    } +    return s; +} + +string to_string(unsigned long long val) +{ +    string s; +    s.resize(s.capacity()); +    while (true) +    { +        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%llu", val)); +        if (n2 <= s.size()) +        { +            s.resize(n2); +            break; +        } +        s.resize(n2); +    } +    return s; +} + +string to_string(float val) +{ +    string s; +    s.resize(s.capacity()); +    while (true) +    { +        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%f", val)); +        if (n2 <= s.size()) +        { +            s.resize(n2); +            break; +        } +        s.resize(n2); +    } +    return s; +} + +string to_string(double val) +{ +    string s; +    s.resize(s.capacity()); +    while (true) +    { +        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%f", val)); +        if (n2 <= s.size()) +        { +            s.resize(n2); +            break; +        } +        s.resize(n2); +    } +    return s; +} + +string to_string(long double val) +{ +    string s; +    s.resize(s.capacity()); +    while (true) +    { +        size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%Lf", val)); +        if (n2 <= s.size()) +        { +            s.resize(n2); +            break; +        } +        s.resize(n2); +    } +    return s; +} + +wstring to_wstring(int val) +{ +    const size_t n = (numeric_limits<int>::digits / 3) +          + ((numeric_limits<int>::digits % 3) != 0) +          + 1; +    wstring s(n, wchar_t()); +    s.resize(s.capacity()); +    while (true) +    { +        int n2 = swprintf(&s[0], s.size()+1, L"%d", val); +        if (n2 > 0) +        { +            s.resize(static_cast<size_t>(n2)); +            break; +        } +        s.resize(2*s.size()); +        s.resize(s.capacity()); +    } +    return s; +} + +wstring to_wstring(unsigned val) +{ +    const size_t n = (numeric_limits<unsigned>::digits / 3) +          + ((numeric_limits<unsigned>::digits % 3) != 0) +          + 1; +    wstring s(n, wchar_t()); +    s.resize(s.capacity()); +    while (true) +    { +        int n2 = swprintf(&s[0], s.size()+1, L"%u", val); +        if (n2 > 0) +        { +            s.resize(static_cast<size_t>(n2)); +            break; +        } +        s.resize(2*s.size()); +        s.resize(s.capacity()); +    } +    return s; +} + +wstring to_wstring(long val) +{ +    const size_t n = (numeric_limits<long>::digits / 3) +          + ((numeric_limits<long>::digits % 3) != 0) +          + 1; +    wstring s(n, wchar_t()); +    s.resize(s.capacity()); +    while (true) +    { +        int n2 = swprintf(&s[0], s.size()+1, L"%ld", val); +        if (n2 > 0) +        { +            s.resize(static_cast<size_t>(n2)); +            break; +        } +        s.resize(2*s.size()); +        s.resize(s.capacity()); +    } +    return s; +} + +wstring to_wstring(unsigned long val) +{ +    const size_t n = (numeric_limits<unsigned long>::digits / 3) +          + ((numeric_limits<unsigned long>::digits % 3) != 0) +          + 1; +    wstring s(n, wchar_t()); +    s.resize(s.capacity()); +    while (true) +    { +        int n2 = swprintf(&s[0], s.size()+1, L"%lu", val); +        if (n2 > 0) +        { +            s.resize(static_cast<size_t>(n2)); +            break; +        } +        s.resize(2*s.size()); +        s.resize(s.capacity()); +    } +    return s; +} + +wstring to_wstring(long long val) +{ +    const size_t n = (numeric_limits<long long>::digits / 3) +          + ((numeric_limits<long long>::digits % 3) != 0) +          + 1; +    wstring s(n, wchar_t()); +    s.resize(s.capacity()); +    while (true) +    { +        int n2 = swprintf(&s[0], s.size()+1, L"%lld", val); +        if (n2 > 0) +        { +            s.resize(static_cast<size_t>(n2)); +            break; +        } +        s.resize(2*s.size()); +        s.resize(s.capacity()); +    } +    return s; +} + +wstring to_wstring(unsigned long long val) +{ +    const size_t n = (numeric_limits<unsigned long long>::digits / 3) +          + ((numeric_limits<unsigned long long>::digits % 3) != 0) +          + 1; +    wstring s(n, wchar_t()); +    s.resize(s.capacity()); +    while (true) +    { +        int n2 = swprintf(&s[0], s.size()+1, L"%llu", val); +        if (n2 > 0) +        { +            s.resize(static_cast<size_t>(n2)); +            break; +        } +        s.resize(2*s.size()); +        s.resize(s.capacity()); +    } +    return s; +} + +wstring to_wstring(float val) +{ +    const size_t n = 20; +    wstring s(n, wchar_t()); +    s.resize(s.capacity()); +    while (true) +    { +        int n2 = swprintf(&s[0], s.size()+1, L"%f", val); +        if (n2 > 0) +        { +            s.resize(static_cast<size_t>(n2)); +            break; +        } +        s.resize(2*s.size()); +        s.resize(s.capacity()); +    } +    return s; +} + +wstring to_wstring(double val) +{ +    const size_t n = 20; +    wstring s(n, wchar_t()); +    s.resize(s.capacity()); +    while (true) +    { +        int n2 = swprintf(&s[0], s.size()+1, L"%f", val); +        if (n2 > 0) +        { +            s.resize(static_cast<size_t>(n2)); +            break; +        } +        s.resize(2*s.size()); +        s.resize(s.capacity()); +    } +    return s; +} + +wstring to_wstring(long double val) +{ +    const size_t n = 20; +    wstring s(n, wchar_t()); +    s.resize(s.capacity()); +    while (true) +    { +        int n2 = swprintf(&s[0], s.size()+1, L"%Lf", val); +        if (n2 > 0) +        { +            s.resize(static_cast<size_t>(n2)); +            break; +        } +        s.resize(2*s.size()); +        s.resize(s.capacity()); +    } +    return s; +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/strstream.cpp b/contrib/libc++/src/strstream.cpp new file mode 100644 index 000000000000..8cd19e6a353c --- /dev/null +++ b/contrib/libc++/src/strstream.cpp @@ -0,0 +1,327 @@ +//===------------------------ strstream.cpp -------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. 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 = static_cast<streamsize>(strlen(__gnext)); +    else if (__n < 0) +        __n = INT_MAX; +    if (__pbeg == nullptr) +        setg(__gnext, __gnext, __gnext + __n); +    else +    { +        setg(__gnext, __gnext, __pbeg); +        setp(__pbeg, __pbeg + __n); +    } +} + +strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg) +    : __strmode_(), +      __alsize_(__default_alsize), +      __palloc_(nullptr), +      __pfree_(nullptr) +{ +    __init(__gnext, __n, __pbeg); +} + +strstreambuf::strstreambuf(const char* __gnext, streamsize __n) +    : __strmode_(__constant), +      __alsize_(__default_alsize), +      __palloc_(nullptr), +      __pfree_(nullptr) +{ +    __init((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); +} + +strstreambuf::~strstreambuf() +{ +    if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0) +    { +        if (__pfree_) +            __pfree_(eback()); +        else +            delete [] eback(); +    } +} + +void +strstreambuf::swap(strstreambuf& __rhs) +{ +    streambuf::swap(__rhs); +    _VSTD::swap(__strmode_, __rhs.__strmode_); +    _VSTD::swap(__alsize_, __rhs.__alsize_); +    _VSTD::swap(__palloc_, __rhs.__palloc_); +    _VSTD::swap(__pfree_, __rhs.__pfree_); +} + +void +strstreambuf::freeze(bool __freezefl) +{ +    if (__strmode_ & __dynamic) +    { +        if (__freezefl) +            __strmode_ |= __frozen; +        else +            __strmode_ &= ~__frozen; +    } +} + +char* +strstreambuf::str() +{ +    if (__strmode_ & __dynamic) +        __strmode_ |= __frozen; +    return eback(); +} + +int +strstreambuf::pcount() const +{ +    return static_cast<int>(pptr() - pbase()); +} + +strstreambuf::int_type +strstreambuf::overflow(int_type __c) +{ +    if (__c == EOF) +        return int_type(0); +    if (pptr() == epptr()) +    { +        if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0) +            return int_type(EOF); +        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_(static_cast<size_t>(new_size))); +        else +            buf = new char[new_size]; +        if (buf == nullptr) +            return int_type(EOF); +        memcpy(buf, eback(), static_cast<size_t>(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(static_cast<int>(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, _VSTD::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, _VSTD::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/contrib/libc++/src/support/win32/locale_win32.cpp b/contrib/libc++/src/support/win32/locale_win32.cpp new file mode 100644 index 000000000000..02b5874e2944 --- /dev/null +++ b/contrib/libc++/src/support/win32/locale_win32.cpp @@ -0,0 +1,94 @@ +// -*- C++ -*- +//===-------------------- support/win32/locale_win32.cpp ------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "support/win32/locale_win32.h" + +#include <stdarg.h> // va_start, va_end + +// FIXME: base currently unused. Needs manual work to construct the new locale +locale_t newlocale( int mask, const char * locale, locale_t /*base*/ ) +{ +    return _create_locale( mask, locale ); +} +locale_t uselocale( locale_t newloc ) +{ +    locale_t old_locale = _get_current_locale(); +    // uselocale sets the thread's locale by definition, so unconditionally use thread-local locale +    _configthreadlocale( _ENABLE_PER_THREAD_LOCALE ); +    // uselocale sets all categories +    setlocale( LC_ALL, newloc->locinfo->lc_category[LC_ALL].locale ); +    // uselocale returns the old locale_t +    return old_locale; +} +lconv *localeconv_l( locale_t loc ) +{ +    __locale_raii __current( uselocale(loc), uselocale ); +    return localeconv(); +} +size_t mbrlen_l( const char *__restrict__ s, size_t n, +                 mbstate_t *__restrict__ ps, locale_t loc ) +{ +    __locale_raii __current( uselocale(loc), uselocale ); +    return mbrlen( s, n, ps ); +} +size_t mbsrtowcs_l( wchar_t *__restrict__ dst, const char **__restrict__ src, +                    size_t len, mbstate_t *__restrict__ ps, locale_t loc ) +{ +    __locale_raii __current( uselocale(loc), uselocale ); +    return mbsrtowcs( dst, src, len, ps ); +} +size_t wcrtomb_l( char *__restrict__ s, wchar_t wc, mbstate_t *__restrict__ ps, +                  locale_t loc ) +{ +    __locale_raii __current( uselocale(loc), uselocale ); +    return wcrtomb( s, wc, ps ); +} +size_t mbrtowc_l( wchar_t *__restrict__ pwc, const char *__restrict__ s, +                  size_t n, mbstate_t *__restrict__ ps, locale_t loc ) +{ +    __locale_raii __current( uselocale(loc), uselocale ); +    return mbrtowc( pwc, s, n, ps ); +} +size_t mbsnrtowcs_l( wchar_t *__restrict__ dst, const char **__restrict__ src, +                     size_t nms, size_t len, mbstate_t *__restrict__ ps, locale_t loc ) +{ +    __locale_raii __current( uselocale(loc), uselocale ); +    return mbsnrtowcs( dst, src, nms, len, ps ); +} +size_t wcsnrtombs_l( char *__restrict__ dst, const wchar_t **__restrict__ src, +                     size_t nwc, size_t len, mbstate_t *__restrict__ ps, locale_t loc ) +{ +    __locale_raii __current( uselocale(loc), uselocale ); +    return wcsnrtombs( dst, src, nwc, len, ps ); +} +wint_t btowc_l( int c, locale_t loc ) +{ +    __locale_raii __current( uselocale(loc), uselocale ); +    return btowc( c ); +} +int wctob_l( wint_t c, locale_t loc ) +{ +    __locale_raii __current( uselocale(loc), uselocale ); +    return wctob( c ); +} + +int asprintf_l( char **ret, locale_t loc, const char *format, ... ) +{ +    va_list ap; +    va_start( ap, format ); +    int result = vasprintf_l( ret, loc, format, ap ); +    va_end(ap); +    return result; +} +int vasprintf_l( char **ret, locale_t loc, const char *format, va_list ap ) +{ +    __locale_raii __current( uselocale(loc), uselocale ); +    return vasprintf( ret, format, ap ); +} diff --git a/contrib/libc++/src/support/win32/support.cpp b/contrib/libc++/src/support/win32/support.cpp new file mode 100644 index 000000000000..9e85077a7ada --- /dev/null +++ b/contrib/libc++/src/support/win32/support.cpp @@ -0,0 +1,70 @@ +// -*- C++ -*- +//===----------------------- support/win32/support.h ----------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <support/win32/support.h> +#include <stdarg.h> // va_start, va_end +#include <stddef.h> // size_t +#include <stdlib.h> // malloc +#include <stdio.h>  // vsprintf, vsnprintf +#include <string.h> // strcpy, wcsncpy + +int asprintf(char **sptr, const char *__restrict fmt, ...) +{ +    va_list ap; +    va_start(ap, fmt); +    int result = vasprintf(sptr, fmt, ap); +    va_end(ap); +    return result; +} +int vasprintf( char **sptr, const char *__restrict fmt, va_list ap ) +{ +    *sptr = NULL; +    int count = vsnprintf( *sptr, 0, fmt, ap ); +    if( (count >= 0) && ((*sptr = (char*)malloc(count+1)) != NULL) ) +    { +        vsprintf( *sptr, fmt, ap ); +        sptr[count] = '\0'; +    } + +    return count; +} + +// FIXME: use wcrtomb and avoid copy +// use mbsrtowcs which is available, first copy first nwc elements of src +size_t mbsnrtowcs( wchar_t *__restrict dst, const char **__restrict src, +                   size_t nmc, size_t len, mbstate_t *__restrict ps ) +{ +    char* local_src = new char[nmc+1]; +    char* nmcsrc = local_src; +    strncpy( nmcsrc, *src, nmc ); +    nmcsrc[nmc] = '\0'; +    const size_t result = mbsrtowcs( dst, const_cast<const char **>(&nmcsrc), len, ps ); +    // propagate error +    if( nmcsrc == NULL ) +        *src = NULL; +    delete[] local_src; +    return result; +} +// FIXME: use wcrtomb and avoid copy +// use wcsrtombs which is available, first copy first nwc elements of src +size_t wcsnrtombs( char *__restrict dst, const wchar_t **__restrict src, +                   size_t nwc, size_t len, mbstate_t *__restrict ps ) +{ +    wchar_t* local_src = new wchar_t[nwc]; +    wchar_t* nwcsrc = local_src; +    wcsncpy(nwcsrc, *src, nwc); +    nwcsrc[nwc] = '\0'; +    const size_t result = wcsrtombs( dst, const_cast<const wchar_t **>(&nwcsrc), len, ps ); +    // propogate error +    if( nwcsrc == NULL ) +        *src = NULL; +    delete[] nwcsrc; +    return result; +} diff --git a/contrib/libc++/src/system_error.cpp b/contrib/libc++/src/system_error.cpp new file mode 100644 index 000000000000..763d62c2a0b4 --- /dev/null +++ b/contrib/libc++/src/system_error.cpp @@ -0,0 +1,201 @@ +//===---------------------- system_error.cpp ------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "system_error" +#include "string" +#include "cstring" + +_LIBCPP_BEGIN_NAMESPACE_STD + +// class error_category + +error_category::error_category() _NOEXCEPT +{ +} + +error_category::~error_category() _NOEXCEPT +{ +} + +error_condition +error_category::default_error_condition(int ev) const _NOEXCEPT +{ +    return error_condition(ev, *this); +} + +bool +error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT +{ +    return default_error_condition(code) == condition; +} + +bool +error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT +{ +    return *this == code.category() && code.value() == condition; +} + +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 _NOEXCEPT; +    virtual string message(int ev) const; +}; + +const char* +__generic_error_category::name() const _NOEXCEPT +{ +    return "generic"; +} + +string +__generic_error_category::message(int ev) const +{ +#ifdef ELAST +    if (ev > ELAST) +      return string("unspecified generic_category error"); +#endif  // ELAST +    return __do_message::message(ev); +} + +const error_category& +generic_category() _NOEXCEPT +{ +    static __generic_error_category s; +    return s; +} + +class _LIBCPP_HIDDEN __system_error_category +    : public __do_message +{ +public: +    virtual const char* name() const _NOEXCEPT; +    virtual string message(int ev) const; +    virtual error_condition default_error_condition(int ev) const _NOEXCEPT; +}; + +const char* +__system_error_category::name() const _NOEXCEPT +{ +    return "system"; +} + +string +__system_error_category::message(int ev) const +{ +#ifdef ELAST +    if (ev > ELAST) +      return string("unspecified system_category error"); +#endif  // ELAST +    return __do_message::message(ev); +} + +error_condition +__system_error_category::default_error_condition(int ev) const _NOEXCEPT +{ +#ifdef ELAST +    if (ev > ELAST) +      return error_condition(ev, system_category()); +#endif  // ELAST +    return error_condition(ev, generic_category()); +} + +const error_category& +system_category() _NOEXCEPT +{ +    static __system_error_category s; +    return s; +} + +// error_condition + +string +error_condition::message() const +{ +    return __cat_->message(__val_); +} + +// error_code + +string +error_code::message() const +{ +    return __cat_->message(__val_); +} + +// system_error + +string +system_error::__init(const error_code& ec, string what_arg) +{ +    if (ec) +    { +        if (!what_arg.empty()) +            what_arg += ": "; +        what_arg += ec.message(); +    } +    return _VSTD::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() _NOEXCEPT +{ +} + +void +__throw_system_error(int ev, const char* what_arg) +{ +#ifndef _LIBCPP_NO_EXCEPTIONS +    throw system_error(error_code(ev, system_category()), what_arg); +#endif +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/thread.cpp b/contrib/libc++/src/thread.cpp new file mode 100644 index 000000000000..f27136a53d05 --- /dev/null +++ b/contrib/libc++/src/thread.cpp @@ -0,0 +1,183 @@ +//===------------------------- thread.cpp----------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "thread" +#include "exception" +#include "vector" +#include "future" +#include <sys/types.h> +#if !_WIN32 && !__sun__ +#include <sys/sysctl.h> +#endif // _WIN32 + +_LIBCPP_BEGIN_NAMESPACE_STD + +thread::~thread() +{ +    if (__t_ != 0) +        terminate(); +} + +void +thread::join() +{ +    int ec = pthread_join(__t_, 0); +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (ec) +        throw system_error(error_code(ec, system_category()), "thread::join failed"); +#endif  // _LIBCPP_NO_EXCEPTIONS +    __t_ = 0; +} + +void +thread::detach() +{ +    int ec = EINVAL; +    if (__t_ != 0) +    { +        ec = pthread_detach(__t_); +        if (ec == 0) +            __t_ = 0; +    } +#ifndef _LIBCPP_NO_EXCEPTIONS +    if (ec) +        throw system_error(error_code(ec, system_category()), "thread::detach failed"); +#endif  // _LIBCPP_NO_EXCEPTIONS +} + +unsigned +thread::hardware_concurrency() +{ +#if defined(CTL_HW) && defined(HW_NCPU) +    unsigned n; +    int mib[2] = {CTL_HW, HW_NCPU}; +    std::size_t s = sizeof(n); +    sysctl(mib, 2, &n, &s, 0, 0); +    return n; +#else  // defined(CTL_HW) && defined(HW_NCPU) +    // TODO: grovel through /proc or check cpuid on x86 and similar +    // instructions on other architectures. +    return 0;  // Means not computable [thread.thread.static] +#endif  // defined(CTL_HW) && defined(HW_NCPU) +} + +namespace this_thread +{ + +void +sleep_for(const chrono::nanoseconds& ns) +{ +    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 + +__thread_specific_ptr<__thread_struct>& +__thread_local_data() +{ +    static __thread_specific_ptr<__thread_struct> __p; +    return __p; +} + +// __thread_struct_imp + +template <class T> +class _LIBCPP_HIDDEN __hidden_allocator +{ +public: +    typedef T  value_type; +     +    T* allocate(size_t __n) +        {return static_cast<T*>(::operator new(__n * sizeof(T)));} +    void deallocate(T* __p, size_t) {::operator delete((void*)__p);} + +    size_t max_size() const {return size_t(~0) / sizeof(T);} +}; + +class _LIBCPP_HIDDEN __thread_struct_imp +{ +    typedef vector<__assoc_sub_state*, +                          __hidden_allocator<__assoc_sub_state*> > _AsyncStates; +    typedef vector<pair<condition_variable*, mutex*>, +               __hidden_allocator<pair<condition_variable*, mutex*> > > _Notify; + +    _AsyncStates async_states_; +    _Notify notify_; + +    __thread_struct_imp(const __thread_struct_imp&); +    __thread_struct_imp& operator=(const __thread_struct_imp&); +public: +    __thread_struct_imp() {} +    ~__thread_struct_imp(); + +    void notify_all_at_thread_exit(condition_variable* cv, mutex* m); +    void __make_ready_at_thread_exit(__assoc_sub_state* __s); +}; + +__thread_struct_imp::~__thread_struct_imp() +{ +    for (_Notify::iterator i = notify_.begin(), e = notify_.end(); +            i != e; ++i) +    { +        i->second->unlock(); +        i->first->notify_all(); +    } +    for (_AsyncStates::iterator i = async_states_.begin(), e = async_states_.end(); +            i != e; ++i) +    { +        (*i)->__make_ready(); +        (*i)->__release_shared(); +    } +} + +void +__thread_struct_imp::notify_all_at_thread_exit(condition_variable* cv, mutex* m) +{ +    notify_.push_back(pair<condition_variable*, mutex*>(cv, m)); +} + +void +__thread_struct_imp::__make_ready_at_thread_exit(__assoc_sub_state* __s) +{ +    async_states_.push_back(__s); +    __s->__add_shared(); +} + +// __thread_struct + +__thread_struct::__thread_struct() +    : __p_(new __thread_struct_imp) +{ +} + +__thread_struct::~__thread_struct() +{ +    delete __p_; +} + +void +__thread_struct::notify_all_at_thread_exit(condition_variable* cv, mutex* m) +{ +    __p_->notify_all_at_thread_exit(cv, m); +} + +void +__thread_struct::__make_ready_at_thread_exit(__assoc_sub_state* __s) +{ +    __p_->__make_ready_at_thread_exit(__s); +} + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/typeinfo.cpp b/contrib/libc++/src/typeinfo.cpp new file mode 100644 index 000000000000..cfc64ef57a61 --- /dev/null +++ b/contrib/libc++/src/typeinfo.cpp @@ -0,0 +1,53 @@ +//===------------------------- typeinfo.cpp -------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdlib.h> +#if __APPLE__ +#include <cxxabi.h> +#endif + +#include "typeinfo" + +#if !(defined(_LIBCPPABI_VERSION) || defined(LIBCXXRT)) + +std::bad_cast::bad_cast() _NOEXCEPT +{ +} + +std::bad_cast::~bad_cast() _NOEXCEPT +{ +} + +const char* +std::bad_cast::what() const _NOEXCEPT +{ +  return "std::bad_cast"; +} + +std::bad_typeid::bad_typeid() _NOEXCEPT +{ +} + +std::bad_typeid::~bad_typeid() _NOEXCEPT +{ +} + +const char* +std::bad_typeid::what() const _NOEXCEPT +{ +  return "std::bad_typeid"; +} + +#if __APPLE__ +  // On Darwin, the cxa_bad_* functions cannot be in the lower level library +  // because bad_cast and bad_typeid are defined in his higher level library +  void __cxxabiv1::__cxa_bad_typeid() { throw std::bad_typeid(); } +  void __cxxabiv1::__cxa_bad_cast() { throw std::bad_cast(); } +#endif + +#endif  // _LIBCPPABI_VERSION diff --git a/contrib/libc++/src/utility.cpp b/contrib/libc++/src/utility.cpp new file mode 100644 index 000000000000..7dccffb73e5a --- /dev/null +++ b/contrib/libc++/src/utility.cpp @@ -0,0 +1,16 @@ +//===------------------------ utility.cpp ---------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "utility" + +_LIBCPP_BEGIN_NAMESPACE_STD + +const piecewise_construct_t piecewise_construct = {}; + +_LIBCPP_END_NAMESPACE_STD diff --git a/contrib/libc++/src/valarray.cpp b/contrib/libc++/src/valarray.cpp new file mode 100644 index 000000000000..2d8db52ac36b --- /dev/null +++ b/contrib/libc++/src/valarray.cpp @@ -0,0 +1,54 @@ +//===------------------------ valarray.cpp --------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. 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  | 
