diff options
Diffstat (limited to 'contrib/libc++/src')
-rw-r--r-- | contrib/libc++/src/algorithm.cpp | 6 | ||||
-rw-r--r-- | contrib/libc++/src/bind.cpp | 21 | ||||
-rw-r--r-- | contrib/libc++/src/condition_variable.cpp | 10 | ||||
-rw-r--r-- | contrib/libc++/src/experimental/filesystem/directory_iterator.cpp | 256 | ||||
-rw-r--r-- | contrib/libc++/src/experimental/filesystem/operations.cpp | 794 | ||||
-rw-r--r-- | contrib/libc++/src/experimental/filesystem/path.cpp | 391 | ||||
-rw-r--r-- | contrib/libc++/src/experimental/memory_resource.cpp | 144 | ||||
-rw-r--r-- | contrib/libc++/src/locale.cpp | 233 | ||||
-rw-r--r-- | contrib/libc++/src/memory.cpp | 14 | ||||
-rw-r--r-- | contrib/libc++/src/mutex.cpp | 74 | ||||
-rw-r--r-- | contrib/libc++/src/regex.cpp | 18 | ||||
-rw-r--r-- | contrib/libc++/src/strstream.cpp | 9 | ||||
-rw-r--r-- | contrib/libc++/src/system_error.cpp | 57 | ||||
-rw-r--r-- | contrib/libc++/src/thread.cpp | 24 |
14 files changed, 1756 insertions, 295 deletions
diff --git a/contrib/libc++/src/algorithm.cpp b/contrib/libc++/src/algorithm.cpp index e548856..e9752b0 100644 --- a/contrib/libc++/src/algorithm.cpp +++ b/contrib/libc++/src/algorithm.cpp @@ -48,14 +48,14 @@ template bool __insertion_sort_incomplete<__less<long double>&, long double*>(lo template unsigned __sort5<__less<long double>&, long double*>(long double*, long double*, long double*, long double*, long double*, __less<long double>&); #ifndef _LIBCPP_HAS_NO_THREADS -static pthread_mutex_t __rs_mut = PTHREAD_MUTEX_INITIALIZER; +static __libcpp_mutex_t __rs_mut = _LIBCPP_MUTEX_INITIALIZER; #endif unsigned __rs_default::__c_ = 0; __rs_default::__rs_default() { #ifndef _LIBCPP_HAS_NO_THREADS - pthread_mutex_lock(&__rs_mut); + __libcpp_mutex_lock(&__rs_mut); #endif __c_ = 1; } @@ -69,7 +69,7 @@ __rs_default::~__rs_default() { #ifndef _LIBCPP_HAS_NO_THREADS if (--__c_ == 0) - pthread_mutex_unlock(&__rs_mut); + __libcpp_mutex_unlock(&__rs_mut); #else --__c_; #endif diff --git a/contrib/libc++/src/bind.cpp b/contrib/libc++/src/bind.cpp index cab0b7c..b318fc1 100644 --- a/contrib/libc++/src/bind.cpp +++ b/contrib/libc++/src/bind.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#define _LIBCPP_BUILDING_BIND #include "functional" _LIBCPP_BEGIN_NAMESPACE_STD @@ -14,16 +15,16 @@ _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; +const __ph<1> _1{}; +const __ph<2> _2{}; +const __ph<3> _3{}; +const __ph<4> _4{}; +const __ph<5> _5{}; +const __ph<6> _6{}; +const __ph<7> _7{}; +const __ph<8> _8{}; +const __ph<9> _9{}; +const __ph<10> _10{}; } // placeholders diff --git a/contrib/libc++/src/condition_variable.cpp b/contrib/libc++/src/condition_variable.cpp index 5fd5fc8..bfb4bf3 100644 --- a/contrib/libc++/src/condition_variable.cpp +++ b/contrib/libc++/src/condition_variable.cpp @@ -20,19 +20,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD condition_variable::~condition_variable() { - pthread_cond_destroy(&__cv_); + __libcpp_condvar_destroy(&__cv_); } void condition_variable::notify_one() _NOEXCEPT { - pthread_cond_signal(&__cv_); + __libcpp_condvar_signal(&__cv_); } void condition_variable::notify_all() _NOEXCEPT { - pthread_cond_broadcast(&__cv_); + __libcpp_condvar_broadcast(&__cv_); } void @@ -41,7 +41,7 @@ condition_variable::wait(unique_lock<mutex>& lk) _NOEXCEPT if (!lk.owns_lock()) __throw_system_error(EPERM, "condition_variable::wait: mutex not locked"); - int ec = pthread_cond_wait(&__cv_, lk.mutex()->native_handle()); + int ec = __libcpp_condvar_wait(&__cv_, lk.mutex()->native_handle()); if (ec) __throw_system_error(ec, "condition_variable wait failed"); } @@ -71,7 +71,7 @@ condition_variable::__do_timed_wait(unique_lock<mutex>& lk, ts.tv_sec = ts_sec_max; ts.tv_nsec = giga::num - 1; } - int ec = pthread_cond_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); + int ec = __libcpp_condvar_timedwait(&__cv_, lk.mutex()->native_handle(), &ts); if (ec != 0 && ec != ETIMEDOUT) __throw_system_error(ec, "condition_variable timed_wait failed"); } diff --git a/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp b/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp new file mode 100644 index 0000000..fa217ba --- /dev/null +++ b/contrib/libc++/src/experimental/filesystem/directory_iterator.cpp @@ -0,0 +1,256 @@ +#include "experimental/filesystem" +#include <dirent.h> +#include <errno.h> + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM + +namespace { namespace detail { + +inline error_code capture_errno() { + _LIBCPP_ASSERT(errno, "Expected errno to be non-zero"); + return error_code{errno, std::generic_category()}; +} + +template <class ...Args> +inline bool capture_error_or_throw(std::error_code* user_ec, + const char* msg, Args&&... args) +{ + std::error_code my_ec = capture_errno(); + if (user_ec) { + *user_ec = my_ec; + return true; + } + __libcpp_throw(filesystem_error(msg, std::forward<Args>(args)..., my_ec)); + return false; +} + +template <class ...Args> +inline bool set_or_throw(std::error_code& my_ec, + std::error_code* user_ec, + const char* msg, Args&&... args) +{ + if (user_ec) { + *user_ec = my_ec; + return true; + } + __libcpp_throw(filesystem_error(msg, std::forward<Args>(args)..., my_ec)); + return false; +} + +typedef path::string_type string_type; + + +inline string_type posix_readdir(DIR *dir_stream, error_code& ec) { + struct dirent* dir_entry_ptr = nullptr; + errno = 0; // zero errno in order to detect errors + if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) { + ec = capture_errno(); + return {}; + } else { + ec.clear(); + return dir_entry_ptr->d_name; + } +} + +}} // namespace detail + +using detail::set_or_throw; + +class __dir_stream { +public: + __dir_stream() = delete; + __dir_stream& operator=(const __dir_stream&) = delete; + + __dir_stream(__dir_stream&& other) noexcept + : __stream_(other.__stream_), __root_(std::move(other.__root_)), + __entry_(std::move(other.__entry_)) + { + other.__stream_ = nullptr; + } + + + __dir_stream(const path& root, directory_options opts, error_code& ec) + : __stream_(nullptr), + __root_(root) + { + if ((__stream_ = ::opendir(root.c_str())) == nullptr) { + ec = detail::capture_errno(); + const bool allow_eacess = + bool(opts & directory_options::skip_permission_denied); + if (allow_eacess && ec.value() == EACCES) + ec.clear(); + return; + } + advance(ec); + } + + ~__dir_stream() noexcept + { if (__stream_) close(); } + + bool good() const noexcept { return __stream_ != nullptr; } + + bool advance(error_code &ec) { + while (true) { + auto str = detail::posix_readdir(__stream_, ec); + if (str == "." || str == "..") { + continue; + } else if (ec || str.empty()) { + close(); + return false; + } else { + __entry_.assign(__root_ / str); + return true; + } + } + } +private: + std::error_code close() noexcept { + std::error_code m_ec; + if (::closedir(__stream_) == -1) + m_ec = detail::capture_errno(); + __stream_ = nullptr; + return m_ec; + } + + DIR * __stream_{nullptr}; +public: + path __root_; + directory_entry __entry_; +}; + +// directory_iterator + +directory_iterator::directory_iterator(const path& p, error_code *ec, + directory_options opts) +{ + std::error_code m_ec; + __imp_ = make_shared<__dir_stream>(p, opts, m_ec); + if (ec) *ec = m_ec; + if (!__imp_->good()) { + __imp_.reset(); + if (m_ec) + set_or_throw(m_ec, ec, + "directory_iterator::directory_iterator(...)", p); + } +} + +directory_iterator& directory_iterator::__increment(error_code *ec) +{ + _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator"); + std::error_code m_ec; + if (!__imp_->advance(m_ec)) { + __imp_.reset(); + if (m_ec) + set_or_throw(m_ec, ec, "directory_iterator::operator++()"); + } else { + if (ec) ec->clear(); + } + return *this; + +} + +directory_entry const& directory_iterator::__deref() const { + _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator"); + return __imp_->__entry_; +} + +// recursive_directory_iterator + +struct recursive_directory_iterator::__shared_imp { + stack<__dir_stream> __stack_; + directory_options __options_; +}; + +recursive_directory_iterator::recursive_directory_iterator(const path& p, + directory_options opt, error_code *ec) + : __imp_(nullptr), __rec_(true) +{ + if (ec) ec->clear(); + std::error_code m_ec; + __dir_stream new_s(p, opt, m_ec); + if (m_ec) set_or_throw(m_ec, ec, "recursive_directory_iterator", p); + if (m_ec || !new_s.good()) return; + + __imp_ = _VSTD::make_shared<__shared_imp>(); + __imp_->__options_ = opt; + __imp_->__stack_.push(_VSTD::move(new_s)); +} + +void recursive_directory_iterator::__pop(error_code* ec) +{ + _LIBCPP_ASSERT(__imp_, "Popping the end iterator"); + if (ec) ec->clear(); + __imp_->__stack_.pop(); + if (__imp_->__stack_.size() == 0) + __imp_.reset(); + else + __advance(ec); +} + +directory_options recursive_directory_iterator::options() const { + return __imp_->__options_; +} + +int recursive_directory_iterator::depth() const { + return __imp_->__stack_.size() - 1; +} + +const directory_entry& recursive_directory_iterator::__deref() const { + return __imp_->__stack_.top().__entry_; +} + +recursive_directory_iterator& +recursive_directory_iterator::__increment(error_code *ec) +{ + if (ec) ec->clear(); + if (recursion_pending()) { + if (__try_recursion(ec) || (ec && *ec)) + return *this; + } + __rec_ = true; + __advance(ec); + return *this; +} + +void recursive_directory_iterator::__advance(error_code* ec) { + // REQUIRES: ec must be cleared before calling this function. + const directory_iterator end_it; + auto& stack = __imp_->__stack_; + std::error_code m_ec; + while (stack.size() > 0) { + if (stack.top().advance(m_ec)) + return; + if (m_ec) break; + stack.pop(); + } + __imp_.reset(); + if (m_ec) + set_or_throw(m_ec, ec, "recursive_directory_iterator::operator++()"); +} + +bool recursive_directory_iterator::__try_recursion(error_code *ec) { + + bool rec_sym = + bool(options() & directory_options::follow_directory_symlink); + auto& curr_it = __imp_->__stack_.top(); + + if (is_directory(curr_it.__entry_.status()) && + (!is_symlink(curr_it.__entry_.symlink_status()) || rec_sym)) + { + std::error_code m_ec; + __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec); + if (new_it.good()) { + __imp_->__stack_.push(_VSTD::move(new_it)); + return true; + } + if (m_ec) { + __imp_.reset(); + set_or_throw(m_ec, ec, + "recursive_directory_iterator::operator++()"); + } + } + return false; +} + + +_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM diff --git a/contrib/libc++/src/experimental/filesystem/operations.cpp b/contrib/libc++/src/experimental/filesystem/operations.cpp new file mode 100644 index 0000000..369996f --- /dev/null +++ b/contrib/libc++/src/experimental/filesystem/operations.cpp @@ -0,0 +1,794 @@ +//===--------------------- filesystem/ops.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 "experimental/filesystem" +#include "iterator" +#include "fstream" +#include "type_traits" +#include "random" /* for unique_path */ +#include "cstdlib" +#include "climits" + +#include <unistd.h> +#include <sys/stat.h> +#include <sys/statvfs.h> +#include <fcntl.h> /* values for fchmodat */ +#if !defined(UTIME_OMIT) +#include <sys/time.h> // for ::utimes as used in __last_write_time +#endif + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM + +filesystem_error::~filesystem_error() {} + + +// POSIX HELPERS + +namespace detail { namespace { + +using value_type = path::value_type; +using string_type = path::string_type; + + + +inline std::error_code capture_errno() { + _LIBCPP_ASSERT(errno, "Expected errno to be non-zero"); + std::error_code m_ec(errno, std::generic_category()); + return m_ec; +} + +void set_or_throw(std::error_code const& m_ec, std::error_code* ec, + const char* msg, path const& p = {}, path const& p2 = {}) +{ + if (ec) { + *ec = m_ec; + } else { + string msg_s("std::experimental::filesystem::"); + msg_s += msg; + __libcpp_throw(filesystem_error(msg_s, p, p2, m_ec)); + } +} + +void set_or_throw(std::error_code* ec, const char* msg, + path const& p = {}, path const& p2 = {}) +{ + return set_or_throw(capture_errno(), ec, msg, p, p2); +} + +perms posix_get_perms(const struct ::stat & st) noexcept { + return static_cast<perms>(st.st_mode) & perms::mask; +} + +::mode_t posix_convert_perms(perms prms) { + return static_cast< ::mode_t>(prms & perms::mask); +} + +file_status create_file_status(std::error_code& m_ec, path const& p, + struct ::stat& path_stat, + std::error_code* ec) +{ + if (ec) *ec = m_ec; + if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { + return file_status(file_type::not_found); + } + else if (m_ec) { + set_or_throw(m_ec, ec, "posix_stat", p); + return file_status(file_type::none); + } + // else + + file_status fs_tmp; + auto const mode = path_stat.st_mode; + if (S_ISLNK(mode)) fs_tmp.type(file_type::symlink); + else if (S_ISREG(mode)) fs_tmp.type(file_type::regular); + else if (S_ISDIR(mode)) fs_tmp.type(file_type::directory); + else if (S_ISBLK(mode)) fs_tmp.type(file_type::block); + else if (S_ISCHR(mode)) fs_tmp.type(file_type::character); + else if (S_ISFIFO(mode)) fs_tmp.type(file_type::fifo); + else if (S_ISSOCK(mode)) fs_tmp.type(file_type::socket); + else fs_tmp.type(file_type::unknown); + + fs_tmp.permissions(detail::posix_get_perms(path_stat)); + return fs_tmp; +} + +file_status posix_stat(path const & p, struct ::stat& path_stat, + std::error_code* ec) +{ + std::error_code m_ec; + if (::stat(p.c_str(), &path_stat) == -1) + m_ec = detail::capture_errno(); + return create_file_status(m_ec, p, path_stat, ec); +} + +file_status posix_stat(path const & p, std::error_code* ec) { + struct ::stat path_stat; + return posix_stat(p, path_stat, ec); +} + +file_status posix_lstat(path const & p, struct ::stat & path_stat, + std::error_code* ec) +{ + std::error_code m_ec; + if (::lstat(p.c_str(), &path_stat) == -1) + m_ec = detail::capture_errno(); + return create_file_status(m_ec, p, path_stat, ec); +} + +file_status posix_lstat(path const & p, std::error_code* ec) { + struct ::stat path_stat; + return posix_lstat(p, path_stat, ec); +} + +bool stat_equivalent(struct ::stat& st1, struct ::stat& st2) { + return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); +} + +// DETAIL::MISC + + +bool copy_file_impl(const path& from, const path& to, perms from_perms, + std::error_code *ec) +{ + std::ifstream in(from.c_str(), std::ios::binary); + std::ofstream out(to.c_str(), std::ios::binary); + + if (in.good() && out.good()) { + using InIt = std::istreambuf_iterator<char>; + using OutIt = std::ostreambuf_iterator<char>; + InIt bin(in); + InIt ein; + OutIt bout(out); + std::copy(bin, ein, bout); + } + if (out.fail() || in.fail()) { + set_or_throw(make_error_code(errc::operation_not_permitted), + ec, "copy_file", from, to); + return false; + } + __permissions(to, from_perms, ec); + // TODO what if permissions fails? + return true; +} + +}} // end namespace detail + +using detail::set_or_throw; + +path __canonical(path const & orig_p, const path& base, std::error_code *ec) +{ + path p = absolute(orig_p, base); + char buff[PATH_MAX + 1]; + char *ret; + if ((ret = ::realpath(p.c_str(), buff)) == nullptr) { + set_or_throw(ec, "canonical", orig_p, base); + return {}; + } + if (ec) ec->clear(); + return {ret}; +} + +void __copy(const path& from, const path& to, copy_options options, + std::error_code *ec) +{ + const bool sym_status = bool(options & + (copy_options::create_symlinks | copy_options::skip_symlinks)); + + const bool sym_status2 = bool(options & + copy_options::copy_symlinks); + + std::error_code m_ec; + struct ::stat f_st = {}; + const file_status f = sym_status || sym_status2 + ? detail::posix_lstat(from, f_st, &m_ec) + : detail::posix_stat(from, f_st, &m_ec); + if (m_ec) + return set_or_throw(m_ec, ec, "copy", from, to); + + struct ::stat t_st = {}; + const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec) + : detail::posix_stat(to, t_st, &m_ec); + + if (not status_known(t)) + return set_or_throw(m_ec, ec, "copy", from, to); + + if (!exists(f) || is_other(f) || is_other(t) + || (is_directory(f) && is_regular_file(t)) + || detail::stat_equivalent(f_st, t_st)) + { + return set_or_throw(make_error_code(errc::function_not_supported), + ec, "copy", from, to); + } + + if (ec) ec->clear(); + + if (is_symlink(f)) { + if (bool(copy_options::skip_symlinks & options)) { + // do nothing + } else if (not exists(t)) { + __copy_symlink(from, to, ec); + } else { + set_or_throw(make_error_code(errc::file_exists), + ec, "copy", from, to); + } + return; + } + else if (is_regular_file(f)) { + if (bool(copy_options::directories_only & options)) { + // do nothing + } + else if (bool(copy_options::create_symlinks & options)) { + __create_symlink(from, to, ec); + } + else if (bool(copy_options::create_hard_links & options)) { + __create_hard_link(from, to, ec); + } + else if (is_directory(t)) { + __copy_file(from, to / from.filename(), options, ec); + } else { + __copy_file(from, to, options, ec); + } + return; + } + else if (is_directory(f)) { + if (not bool(copy_options::recursive & options) && + bool(copy_options::__in_recursive_copy & options)) + { + return; + } + + if (!exists(t)) { + // create directory to with attributes from 'from'. + __create_directory(to, from, ec); + if (ec && *ec) { return; } + } + directory_iterator it = ec ? directory_iterator(from, *ec) + : directory_iterator(from); + if (ec && *ec) { return; } + std::error_code m_ec; + for (; it != directory_iterator(); it.increment(m_ec)) { + if (m_ec) return set_or_throw(m_ec, ec, "copy", from, to); + __copy(it->path(), to / it->path().filename(), + options | copy_options::__in_recursive_copy, ec); + if (ec && *ec) { return; } + } + } +} + + +bool __copy_file(const path& from, const path& to, copy_options options, + std::error_code *ec) +{ + if (ec) ec->clear(); + + std::error_code m_ec; + auto from_st = detail::posix_stat(from, &m_ec); + if (not is_regular_file(from_st)) { + if (not m_ec) + m_ec = make_error_code(errc::not_supported); + set_or_throw(m_ec, ec, "copy_file", from, to); + return false; + } + + auto to_st = detail::posix_stat(to, &m_ec); + if (!status_known(to_st)) { + set_or_throw(m_ec, ec, "copy_file", from, to); + return false; + } + + const bool to_exists = exists(to_st); + if (to_exists && bool(copy_options::skip_existing & options)) { + return false; + } + else if (to_exists && bool(copy_options::update_existing & options)) { + auto from_time = __last_write_time(from, ec); + if (ec && *ec) { return false; } + auto to_time = __last_write_time(to, ec); + if (ec && *ec) { return false; } + if (from_time <= to_time) { + return false; + } + return detail::copy_file_impl(from, to, from_st.permissions(), ec); + } + else if (!to_exists || bool(copy_options::overwrite_existing & options)) { + return detail::copy_file_impl(from, to, from_st.permissions(), ec); + } + else { + set_or_throw(make_error_code(errc::file_exists), ec, "copy", from, to); + return false; + } +} + +void __copy_symlink(const path& existing_symlink, const path& new_symlink, + std::error_code *ec) +{ + const path real_path(__read_symlink(existing_symlink, ec)); + if (ec && *ec) { return; } + // NOTE: proposal says you should detect if you should call + // create_symlink or create_directory_symlink. I don't think this + // is needed with POSIX + __create_symlink(real_path, new_symlink, ec); +} + + +bool __create_directories(const path& p, std::error_code *ec) +{ + std::error_code m_ec; + auto const st = detail::posix_stat(p, &m_ec); + if (!status_known(st)) { + set_or_throw(m_ec, ec, "create_directories", p); + return false; + } + else if (is_directory(st)) { + if (ec) ec->clear(); + return false; + } + else if (exists(st)) { + set_or_throw(make_error_code(errc::file_exists), + ec, "create_directories", p); + return false; + } + + const path parent = p.parent_path(); + if (!parent.empty()) { + const file_status parent_st = status(parent, m_ec); + if (not status_known(parent_st)) { + set_or_throw(m_ec, ec, "create_directories", p); + return false; + } + if (not exists(parent_st)) { + __create_directories(parent, ec); + if (ec && *ec) { return false; } + } + } + return __create_directory(p, ec); +} + +bool __create_directory(const path& p, std::error_code *ec) +{ + if (ec) ec->clear(); + if (::mkdir(p.c_str(), static_cast<int>(perms::all)) == 0) + return true; + if (errno != EEXIST || !is_directory(p)) + set_or_throw(ec, "create_directory", p); + return false; +} + +bool __create_directory(path const & p, path const & attributes, + std::error_code *ec) +{ + struct ::stat attr_stat; + std::error_code mec; + auto st = detail::posix_stat(attributes, attr_stat, &mec); + if (!status_known(st)) { + set_or_throw(mec, ec, "create_directory", p, attributes); + return false; + } + if (ec) ec->clear(); + if (::mkdir(p.c_str(), attr_stat.st_mode) == 0) + return true; + if (errno != EEXIST || !is_directory(p)) + set_or_throw(ec, "create_directory", p, attributes); + return false; +} + +void __create_directory_symlink(path const & from, path const & to, + std::error_code *ec){ + if (::symlink(from.c_str(), to.c_str()) != 0) + set_or_throw(ec, "create_directory_symlink", from, to); + else if (ec) + ec->clear(); +} + +void __create_hard_link(const path& from, const path& to, std::error_code *ec){ + if (::link(from.c_str(), to.c_str()) == -1) + set_or_throw(ec, "create_hard_link", from, to); + else if (ec) + ec->clear(); +} + +void __create_symlink(path const & from, path const & to, std::error_code *ec) { + + if (::symlink(from.c_str(), to.c_str()) == -1) + set_or_throw(ec, "create_symlink", from, to); + else if (ec) + ec->clear(); +} + +path __current_path(std::error_code *ec) { + auto size = ::pathconf(".", _PC_PATH_MAX); + _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size"); + + auto buff = std::unique_ptr<char[]>(new char[size + 1]); + char* ret; + if ((ret = ::getcwd(buff.get(), static_cast<size_t>(size))) == nullptr) { + set_or_throw(ec, "current_path"); + return {}; + } + if (ec) ec->clear(); + return {buff.get()}; +} + +void __current_path(const path& p, std::error_code *ec) { + if (::chdir(p.c_str()) == -1) + set_or_throw(ec, "current_path", p); + else if (ec) + ec->clear(); +} + +bool __equivalent(const path& p1, const path& p2, std::error_code *ec) +{ + std::error_code ec1, ec2; + struct ::stat st1 = {}; + struct ::stat st2 = {}; + auto s1 = detail::posix_stat(p1.native(), st1, &ec1); + auto s2 = detail::posix_stat(p2.native(), st2, &ec2); + + if ((!exists(s1) && !exists(s2)) || (is_other(s1) && is_other(s2))) { + set_or_throw(make_error_code(errc::not_supported), ec, + "equivalent", p1, p2); + return false; + } + if (ec) ec->clear(); + return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); +} + + +std::uintmax_t __file_size(const path& p, std::error_code *ec) +{ + std::error_code m_ec; + struct ::stat st; + file_status fst = detail::posix_stat(p, st, &m_ec); + if (!exists(fst) || !is_regular_file(fst)) { + if (!m_ec) + m_ec = make_error_code(errc::not_supported); + set_or_throw(m_ec, ec, "file_size", p); + return static_cast<uintmax_t>(-1); + } + // is_regular_file(p) == true + if (ec) ec->clear(); + return static_cast<std::uintmax_t>(st.st_size); +} + +std::uintmax_t __hard_link_count(const path& p, std::error_code *ec) +{ + std::error_code m_ec; + struct ::stat st; + detail::posix_stat(p, st, &m_ec); + if (m_ec) { + set_or_throw(m_ec, ec, "hard_link_count", p); + return static_cast<std::uintmax_t>(-1); + } + if (ec) ec->clear(); + return static_cast<std::uintmax_t>(st.st_nlink); +} + + +bool __fs_is_empty(const path& p, std::error_code *ec) +{ + if (ec) ec->clear(); + std::error_code m_ec; + struct ::stat pst; + auto st = detail::posix_stat(p, pst, &m_ec); + if (is_directory(st)) + return directory_iterator(p) == directory_iterator{}; + else if (is_regular_file(st)) + return static_cast<std::uintmax_t>(pst.st_size) == 0; + // else + set_or_throw(m_ec, ec, "is_empty", p); + return false; +} + + +namespace detail { namespace { + +template <class CType, class ChronoType> +bool checked_set(CType* out, ChronoType time) { + using Lim = numeric_limits<CType>; + if (time > Lim::max() || time < Lim::min()) + return false; + *out = static_cast<CType>(time); + return true; +} + +constexpr long long min_seconds = file_time_type::duration::min().count() + / file_time_type::period::den; + +template <class SubSecDurT, class SubSecT> +bool set_times_checked(time_t* sec_out, SubSecT* subsec_out, file_time_type tp) { + using namespace chrono; + auto dur = tp.time_since_epoch(); + auto sec_dur = duration_cast<seconds>(dur); + auto subsec_dur = duration_cast<SubSecDurT>(dur - sec_dur); + // The tv_nsec and tv_usec fields must not be negative so adjust accordingly + if (subsec_dur.count() < 0) { + if (sec_dur.count() > min_seconds) { + + sec_dur -= seconds(1); + subsec_dur += seconds(1); + } else { + subsec_dur = SubSecDurT::zero(); + } + } + return checked_set(sec_out, sec_dur.count()) + && checked_set(subsec_out, subsec_dur.count()); +} + +}} // end namespace detail + + +file_time_type __last_write_time(const path& p, std::error_code *ec) +{ + std::error_code m_ec; + struct ::stat st; + detail::posix_stat(p, st, &m_ec); + if (m_ec) { + set_or_throw(m_ec, ec, "last_write_time", p); + return file_time_type::min(); + } + if (ec) ec->clear(); + return file_time_type::clock::from_time_t(st.st_mtime); +} + +void __last_write_time(const path& p, file_time_type new_time, + std::error_code *ec) +{ + using namespace std::chrono; + std::error_code m_ec; + + // We can use the presence of UTIME_OMIT to detect platforms that do not + // provide utimensat. +#if !defined(UTIME_OMIT) + // This implementation has a race condition between determining the + // last access time and attempting to set it to the same value using + // ::utimes + struct ::stat st; + file_status fst = detail::posix_stat(p, st, &m_ec); + if (m_ec && !status_known(fst)) { + set_or_throw(m_ec, ec, "last_write_time", p); + return; + } + struct ::timeval tbuf[2]; + tbuf[0].tv_sec = st.st_atime; + tbuf[0].tv_usec = 0; + const bool overflowed = !detail::set_times_checked<microseconds>( + &tbuf[1].tv_sec, &tbuf[1].tv_usec, new_time); + + if (overflowed) { + set_or_throw(make_error_code(errc::invalid_argument), ec, + "last_write_time", p); + return; + } + if (::utimes(p.c_str(), tbuf) == -1) { + m_ec = detail::capture_errno(); + } +#else + struct ::timespec tbuf[2]; + tbuf[0].tv_sec = 0; + tbuf[0].tv_nsec = UTIME_OMIT; + + const bool overflowed = !detail::set_times_checked<nanoseconds>( + &tbuf[1].tv_sec, &tbuf[1].tv_nsec, new_time); + if (overflowed) { + set_or_throw(make_error_code(errc::invalid_argument), + ec, "last_write_time", p); + return; + } + if (::utimensat(AT_FDCWD, p.c_str(), tbuf, 0) == -1) { + m_ec = detail::capture_errno(); + } +#endif + if (m_ec) + set_or_throw(m_ec, ec, "last_write_time", p); + else if (ec) + ec->clear(); +} + + +void __permissions(const path& p, perms prms, std::error_code *ec) +{ + + const bool resolve_symlinks = !bool(perms::symlink_nofollow & prms); + const bool add_perms = bool(perms::add_perms & prms); + const bool remove_perms = bool(perms::remove_perms & prms); + _LIBCPP_ASSERT(!(add_perms && remove_perms), + "Both add_perms and remove_perms are set"); + + bool set_sym_perms = false; + prms &= perms::mask; + if (!resolve_symlinks || (add_perms || remove_perms)) { + std::error_code m_ec; + file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec) + : detail::posix_lstat(p, &m_ec); + set_sym_perms = is_symlink(st); + if (m_ec) return set_or_throw(m_ec, ec, "permissions", p); + _LIBCPP_ASSERT(st.permissions() != perms::unknown, + "Permissions unexpectedly unknown"); + if (add_perms) + prms |= st.permissions(); + else if (remove_perms) + prms = st.permissions() & ~prms; + } + const auto real_perms = detail::posix_convert_perms(prms); + +# if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) + const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0; + if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { + return set_or_throw(ec, "permissions", p); + } +# else + if (set_sym_perms) + return set_or_throw(make_error_code(errc::operation_not_supported), + ec, "permissions", p); + if (::chmod(p.c_str(), real_perms) == -1) { + return set_or_throw(ec, "permissions", p); + } +# endif + if (ec) ec->clear(); +} + + +path __read_symlink(const path& p, std::error_code *ec) { + char buff[PATH_MAX + 1]; + std::error_code m_ec; + ::ssize_t ret; + if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) { + set_or_throw(ec, "read_symlink", p); + return {}; + } + _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO"); + _LIBCPP_ASSERT(ret > 0, "TODO"); + if (ec) ec->clear(); + buff[ret] = 0; + return {buff}; +} + + +bool __remove(const path& p, std::error_code *ec) { + if (ec) ec->clear(); + if (::remove(p.c_str()) == -1) { + set_or_throw(ec, "remove", p); + return false; + } + return true; +} + +namespace { + +std::uintmax_t remove_all_impl(path const & p, std::error_code& ec) +{ + const auto npos = static_cast<std::uintmax_t>(-1); + const file_status st = __symlink_status(p, &ec); + if (ec) return npos; + std::uintmax_t count = 1; + if (is_directory(st)) { + for (directory_iterator it(p, ec); !ec && it != directory_iterator(); + it.increment(ec)) { + auto other_count = remove_all_impl(it->path(), ec); + if (ec) return npos; + count += other_count; + } + if (ec) return npos; + } + if (!__remove(p, &ec)) return npos; + return count; +} + +} // end namespace + +std::uintmax_t __remove_all(const path& p, std::error_code *ec) { + std::error_code mec; + auto count = remove_all_impl(p, mec); + if (mec) { + set_or_throw(mec, ec, "remove_all", p); + return static_cast<std::uintmax_t>(-1); + } + if (ec) ec->clear(); + return count; +} + +void __rename(const path& from, const path& to, std::error_code *ec) { + if (::rename(from.c_str(), to.c_str()) == -1) + set_or_throw(ec, "rename", from, to); + else if (ec) + ec->clear(); +} + +void __resize_file(const path& p, std::uintmax_t size, std::error_code *ec) { + if (::truncate(p.c_str(), static_cast<long>(size)) == -1) + set_or_throw(ec, "resize_file", p); + else if (ec) + ec->clear(); +} + +space_info __space(const path& p, std::error_code *ec) { + space_info si; + struct statvfs m_svfs = {}; + if (::statvfs(p.c_str(), &m_svfs) == -1) { + set_or_throw(ec, "space", p); + si.capacity = si.free = si.available = + static_cast<std::uintmax_t>(-1); + return si; + } + if (ec) ec->clear(); + // Multiply with overflow checking. + auto do_mult = [&](std::uintmax_t& out, std::uintmax_t other) { + out = other * m_svfs.f_frsize; + if (out / other != m_svfs.f_frsize || other == 0) + out = static_cast<std::uintmax_t>(-1); + }; + do_mult(si.capacity, m_svfs.f_blocks); + do_mult(si.free, m_svfs.f_bfree); + do_mult(si.available, m_svfs.f_bavail); + return si; +} + +file_status __status(const path& p, std::error_code *ec) { + return detail::posix_stat(p, ec); +} + +file_status __symlink_status(const path& p, std::error_code *ec) { + return detail::posix_lstat(p, ec); +} + +path __system_complete(const path& p, std::error_code *ec) { + if (ec) ec->clear(); + return absolute(p, current_path()); +} + +path __temp_directory_path(std::error_code *ec) { + const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; + const char* ret = nullptr; + for (auto & ep : env_paths) { + if ((ret = std::getenv(ep))) + break; + } + path p(ret ? ret : "/tmp"); + std::error_code m_ec; + if (is_directory(p, m_ec)) { + if (ec) ec->clear(); + return p; + } + if (!m_ec || m_ec == make_error_code(errc::no_such_file_or_directory)) + m_ec = make_error_code(errc::not_a_directory); + set_or_throw(m_ec, ec, "temp_directory_path"); + return {}; +} + +// An absolute path is composed according to the table in [fs.op.absolute]. +path absolute(const path& p, const path& base) { + auto root_name = p.root_name(); + auto root_dir = p.root_directory(); + + if (!root_name.empty() && !root_dir.empty()) + return p; + + auto abs_base = base.is_absolute() ? base : absolute(base); + + /* !has_root_name && !has_root_dir */ + if (root_name.empty() && root_dir.empty()) + { + return abs_base / p; + } + else if (!root_name.empty()) /* has_root_name && !has_root_dir */ + { + return root_name / abs_base.root_directory() + / + abs_base.relative_path() / p.relative_path(); + } + else /* !has_root_name && has_root_dir */ + { + if (abs_base.has_root_name()) + return abs_base.root_name() / p; + // else p is absolute, return outside of block + } + return p; +} + +_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM diff --git a/contrib/libc++/src/experimental/filesystem/path.cpp b/contrib/libc++/src/experimental/filesystem/path.cpp new file mode 100644 index 0000000..38c4498 --- /dev/null +++ b/contrib/libc++/src/experimental/filesystem/path.cpp @@ -0,0 +1,391 @@ +//===--------------------- filesystem/path.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 "experimental/filesystem" +#include "experimental/string_view" +#include "utility" + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM + +_LIBCPP_CONSTEXPR path::value_type path::preferred_separator; + +namespace { namespace parser +{ + +using string_type = string_view; +using value_type = path::value_type; + +using string_view_pair = pair<string_view, string_view>; + +// status reporting +constexpr size_t npos = static_cast<size_t>(-1); + +inline bool good(size_t pos) { return pos != npos; } + +// lexical elements +constexpr value_type preferred_separator = path::preferred_separator; +constexpr value_type const * preferred_separator_str = "/"; +constexpr value_type const * dot = "."; + +// forward // +bool is_separator(string_type const &, size_t); +bool is_root_name(const string_type&, size_t); +bool is_root_directory(string_type const &, size_t); +bool is_trailing_separator(string_type const &, size_t); + +size_t start_of(string_type const &, size_t); +size_t end_of(string_type const &, size_t); + +size_t root_name_start(const string_type& s); +size_t root_name_end(const string_type&); + +size_t root_directory_start(string_type const &); +size_t root_directory_end(string_type const &); + +string_view_pair separate_filename(string_type const &); +string_view extract_raw(string_type const &, size_t); +string_view extract_preferred(string_type const &, size_t); + +inline bool is_separator(const string_type& s, size_t pos) { + return (pos < s.size() && s[pos] == preferred_separator); +} + +inline bool is_root_name(const string_type& s, size_t pos) { + return good(pos) && pos == 0 ? root_name_start(s) == pos : false; +} + +inline bool is_root_directory(const string_type& s, size_t pos) { + return good(pos) ? root_directory_start(s) == pos : false; +} + +inline bool is_trailing_separator(const string_type& s, size_t pos) { + return (pos < s.size() && is_separator(s, pos) && + end_of(s, pos) == s.size()-1 && + !is_root_directory(s, pos) && !is_root_name(s, pos)); +} + +size_t start_of(const string_type& s, size_t pos) { + if (pos >= s.size()) return npos; + bool in_sep = (s[pos] == preferred_separator); + while (pos - 1 < s.size() && + (s[pos-1] == preferred_separator) == in_sep) + { --pos; } + if (pos == 2 && !in_sep && s[0] == preferred_separator && + s[1] == preferred_separator) + { return 0; } + return pos; +} + +size_t end_of(const string_type& s, size_t pos) { + if (pos >= s.size()) return npos; + // special case for root name + if (pos == 0 && is_root_name(s, pos)) return root_name_end(s); + bool in_sep = (s[pos] == preferred_separator); + while (pos + 1 < s.size() && (s[pos+1] == preferred_separator) == in_sep) + { ++pos; } + return pos; +} + +inline size_t root_name_start(const string_type& s) { + return good(root_name_end(s)) ? 0 : npos; +} + +size_t root_name_end(const string_type& s) { + if (s.size() < 2 || s[0] != preferred_separator + || s[1] != preferred_separator) { + return npos; + } + if (s.size() == 2) { + return 1; + } + size_t index = 2; // current position + if (s[index] == preferred_separator) { + return npos; + } + while (index + 1 < s.size() && s[index+1] != preferred_separator) { + ++index; + } + return index; +} + +size_t root_directory_start(const string_type& s) { + size_t e = root_name_end(s); + if (!good(e)) + return is_separator(s, 0) ? 0 : npos; + return is_separator(s, e + 1) ? e + 1 : npos; +} + +size_t root_directory_end(const string_type& s) { + size_t st = root_directory_start(s); + if (!good(st)) return npos; + size_t index = st; + while (index + 1 < s.size() && s[index + 1] == preferred_separator) + { ++index; } + return index; +} + +string_view_pair separate_filename(string_type const & s) { + if (s == "." || s == ".." || s.empty()) return string_view_pair{s, ""}; + auto pos = s.find_last_of('.'); + if (pos == string_type::npos) return string_view_pair{s, string_view{}}; + return string_view_pair{s.substr(0, pos), s.substr(pos)}; +} + +inline string_view extract_raw(const string_type& s, size_t pos) { + size_t end_i = end_of(s, pos); + if (!good(end_i)) return string_view{}; + return string_view(s).substr(pos, end_i - pos + 1); +} + +string_view extract_preferred(const string_type& s, size_t pos) { + string_view raw = extract_raw(s, pos); + if (raw.empty()) + return raw; + if (is_trailing_separator(s, pos)) + return string_view{dot}; + if (is_separator(s, pos) && !is_root_name(s, pos)) + return string_view(preferred_separator_str); + return raw; +} + +}} // namespace parser + + +//////////////////////////////////////////////////////////////////////////////// +// path_view_iterator +//////////////////////////////////////////////////////////////////////////////// +namespace { + +struct path_view_iterator { + const string_view __s_; + size_t __pos_; + + explicit path_view_iterator(string_view const& __s) : __s_(__s), __pos_(__s_.empty() ? parser::npos : 0) {} + explicit path_view_iterator(string_view const& __s, size_t __p) : __s_(__s), __pos_(__p) {} + + string_view operator*() const { + return parser::extract_preferred(__s_, __pos_); + } + + path_view_iterator& operator++() { + increment(); + return *this; + } + + path_view_iterator& operator--() { + decrement(); + return *this; + } + + void increment() { + if (__pos_ == parser::npos) return; + while (! set_position(parser::end_of(__s_, __pos_)+1)) + ; + return; + } + + void decrement() { + if (__pos_ == 0) { + set_position(0); + } + else if (__pos_ == parser::npos) { + auto const str_size = __s_.size(); + set_position(parser::start_of( + __s_, str_size != 0 ? str_size - 1 : str_size)); + } else { + while (!set_position(parser::start_of(__s_, __pos_-1))) + ; + } + } + + bool set_position(size_t pos) { + if (pos >= __s_.size()) { + __pos_ = parser::npos; + } else { + __pos_ = pos; + } + return valid_iterator_position(); + } + + bool valid_iterator_position() const { + if (__pos_ == parser::npos) return true; // end position is valid + return (!parser::is_separator (__s_, __pos_) || + parser::is_root_directory (__s_, __pos_) || + parser::is_trailing_separator(__s_, __pos_) || + parser::is_root_name (__s_, __pos_)); + } + + bool is_end() const { return __pos_ == parser::npos; } + + inline bool operator==(path_view_iterator const& __p) { + return __pos_ == __p.__pos_; + } +}; + +path_view_iterator pbegin(path const& p) { + return path_view_iterator(p.native()); +} + +path_view_iterator pend(path const& p) { + path_view_iterator __p(p.native()); + __p.__pos_ = parser::npos; + return __p; +} + +} // end namespace +/////////////////////////////////////////////////////////////////////////////// +// path definitions +/////////////////////////////////////////////////////////////////////////////// + +path & path::replace_extension(path const & replacement) +{ + path p = extension(); + if (not p.empty()) { + __pn_.erase(__pn_.size() - p.native().size()); + } + if (!replacement.empty()) { + if (replacement.native()[0] != '.') { + __pn_ += "."; + } + __pn_.append(replacement.__pn_); + } + return *this; +} + +/////////////////////////////////////////////////////////////////////////////// +// path.decompose + +string_view path::__root_name() const +{ + return parser::is_root_name(__pn_, 0) + ? parser::extract_preferred(__pn_, 0) + : string_view{}; +} + +string_view path::__root_directory() const +{ + auto start_i = parser::root_directory_start(__pn_); + if(!parser::good(start_i)) { + return {}; + } + return parser::extract_preferred(__pn_, start_i); +} + +string_view path::__relative_path() const +{ + if (empty()) { + return {__pn_}; + } + auto end_i = parser::root_directory_end(__pn_); + if (not parser::good(end_i)) { + end_i = parser::root_name_end(__pn_); + } + if (not parser::good(end_i)) { + return {__pn_}; + } + return string_view(__pn_).substr(end_i+1); +} + +string_view path::__parent_path() const +{ + if (empty() || pbegin(*this) == --pend(*this)) { + return {}; + } + auto end_it = --(--pend(*this)); + auto end_i = parser::end_of(__pn_, end_it.__pos_); + return string_view(__pn_).substr(0, end_i+1); +} + +string_view path::__filename() const +{ + return empty() ? string_view{} : *--pend(*this); +} + +string_view path::__stem() const +{ + return parser::separate_filename(__filename()).first; +} + +string_view path::__extension() const +{ + return parser::separate_filename(__filename()).second; +} + +//////////////////////////////////////////////////////////////////////////// +// path.comparisons +int path::__compare(const value_type* __s) const { + path_view_iterator thisIter(this->native()); + path_view_iterator sIter(__s); + while (!thisIter.is_end() && !sIter.is_end()) { + int res = (*thisIter).compare(*sIter); + if (res != 0) return res; + ++thisIter; ++sIter; + } + if (thisIter.is_end() && sIter.is_end()) + return 0; + if (thisIter.is_end()) + return -1; + return 1; +} + +//////////////////////////////////////////////////////////////////////////// +// path.nonmembers +size_t hash_value(const path& __p) _NOEXCEPT { + path_view_iterator thisIter(__p.native()); + struct HashPairT { + size_t first; + size_t second; + }; + HashPairT hp = {0, 0}; + std::hash<string_view> hasher; + std::__scalar_hash<decltype(hp)> pair_hasher; + while (!thisIter.is_end()) { + hp.second = hasher(*thisIter); + hp.first = pair_hasher(hp); + ++thisIter; + } + return hp.first; +} + +//////////////////////////////////////////////////////////////////////////// +// path.itr +path::iterator path::begin() const +{ + path_view_iterator pit = pbegin(*this); + iterator it; + it.__path_ptr_ = this; + it.__pos_ = pit.__pos_; + it.__elem_.__assign_view(*pit); + return it; +} + +path::iterator path::end() const +{ + iterator it{}; + it.__path_ptr_ = this; + it.__pos_ = parser::npos; + return it; +} + +path::iterator& path::iterator::__increment() { + path_view_iterator it(__path_ptr_->native(), __pos_); + it.increment(); + __pos_ = it.__pos_; + __elem_.__assign_view(*it); + return *this; +} + +path::iterator& path::iterator::__decrement() { + path_view_iterator it(__path_ptr_->native(), __pos_); + it.decrement(); + __pos_ = it.__pos_; + __elem_.__assign_view(*it); + return *this; +} + +_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM diff --git a/contrib/libc++/src/experimental/memory_resource.cpp b/contrib/libc++/src/experimental/memory_resource.cpp new file mode 100644 index 0000000..c01eb08 --- /dev/null +++ b/contrib/libc++/src/experimental/memory_resource.cpp @@ -0,0 +1,144 @@ +//===------------------------ memory_resource.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 "experimental/memory_resource" + +#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER +#include "atomic" +#elif !defined(_LIBCPP_HAS_NO_THREADS) +#include "mutex" +#endif + +_LIBCPP_BEGIN_NAMESPACE_LFTS_PMR + +// memory_resource + +//memory_resource::~memory_resource() {} + +// new_delete_resource() + +class _LIBCPP_TYPE_VIS_ONLY __new_delete_memory_resource_imp + : public memory_resource +{ +public: + ~__new_delete_memory_resource_imp() = default; + +protected: + virtual void* do_allocate(size_t __size, size_t __align) + { return __allocate(__size); } + + virtual void do_deallocate(void * __p, size_t, size_t) + { __deallocate(__p); } + + virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT + { return &__other == this; } +}; + +// null_memory_resource() + +class _LIBCPP_TYPE_VIS_ONLY __null_memory_resource_imp + : public memory_resource +{ +public: + ~__null_memory_resource_imp() = default; + +protected: + virtual void* do_allocate(size_t, size_t) { +#ifndef _LIBCPP_NO_EXCEPTIONS + throw std::bad_alloc(); +#else + abort(); +#endif + } + virtual void do_deallocate(void *, size_t, size_t) {} + virtual bool do_is_equal(memory_resource const & __other) const _NOEXCEPT + { return &__other == this; } +}; + +namespace { + +union ResourceInitHelper { + struct { + __new_delete_memory_resource_imp new_delete_res; + __null_memory_resource_imp null_res; + } resources; + char dummy; + _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {} + ~ResourceInitHelper() {} +}; +// When compiled in C++14 this initialization should be a constant expression. +// Only in C++11 is "init_priority" needed to ensure initialization order. +ResourceInitHelper res_init __attribute__((init_priority (101))); + +} // end namespace + + +memory_resource * new_delete_resource() _NOEXCEPT { + return &res_init.resources.new_delete_res; +} + +memory_resource * null_memory_resource() _NOEXCEPT { + return &res_init.resources.null_res; +} + +// default_memory_resource() + +static memory_resource * +__default_memory_resource(bool set = false, memory_resource * new_res = nullptr) _NOEXCEPT +{ +#ifndef _LIBCPP_HAS_NO_ATOMIC_HEADER + static atomic<memory_resource*> __res = + ATOMIC_VAR_INIT(&res_init.resources.new_delete_res); + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + // TODO: Can a weaker ordering be used? + return _VSTD::atomic_exchange_explicit( + &__res, new_res, memory_order::memory_order_acq_rel); + } + else { + return _VSTD::atomic_load_explicit( + &__res, memory_order::memory_order_acquire); + } +#elif !defined(_LIBCPP_HAS_NO_THREADS) + static memory_resource * res = &res_init.resources.new_delete_res; + static mutex res_lock; + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + lock_guard<mutex> guard(res_lock); + memory_resource * old_res = res; + res = new_res; + return old_res; + } else { + lock_guard<mutex> guard(res_lock); + return res; + } +#else + static memory_resource* res = &res_init.resources.new_delete_res; + if (set) { + new_res = new_res ? new_res : new_delete_resource(); + memory_resource * old_res = res; + res = new_res; + return old_res; + } else { + return res; + } +#endif +} + +memory_resource * get_default_resource() _NOEXCEPT +{ + return __default_memory_resource(); +} + +memory_resource * set_default_resource(memory_resource * __new_res) _NOEXCEPT +{ + return __default_memory_resource(true, __new_res); +} + +_LIBCPP_END_NAMESPACE_LFTS_PMR
\ No newline at end of file diff --git a/contrib/libc++/src/locale.cpp b/contrib/libc++/src/locale.cpp index 6b04e78..da2fd11 100644 --- a/contrib/libc++/src/locale.cpp +++ b/contrib/libc++/src/locale.cpp @@ -123,11 +123,6 @@ const locale::category locale::time; const locale::category locale::messages; const locale::category locale::all; -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - class _LIBCPP_HIDDEN locale::__imp : public facet { @@ -163,10 +158,6 @@ private: template <class F> void install_from(const __imp& other); }; -#if defined(__clang__) -#pragma clang diagnostic pop -#endif - locale::__imp::__imp(size_t refs) : facet(refs), facets_(N), @@ -1409,33 +1400,21 @@ ctype_byname<wchar_t>::do_tolower(char_type* low, const char_type* high) const 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 + return __libcpp_btowc_l(c, __l); } const char* ctype_byname<wchar_t>::do_widen(const char* low, const char* high, char_type* dest) const { for (; low != high; ++low, ++dest) -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - *dest = btowc_l(*low, __l); -#else - *dest = __btowc_l(*low, __l); -#endif + *dest = __libcpp_btowc_l(*low, __l); 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 + int r = __libcpp_wctob_l(c, __l); return r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault; } @@ -1444,11 +1423,7 @@ ctype_byname<wchar_t>::do_narrow(const char_type* low, const char_type* high, ch { for (; low != high; ++low, ++dest) { -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - int r = wctob_l(*low, __l); -#else - int r = __wctob_l(*low, __l); -#endif + int r = __libcpp_wctob_l(*low, __l); *dest = r != static_cast<int>(WEOF) ? static_cast<char>(r) : dfault; } return low; @@ -1558,22 +1533,14 @@ codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st, { // save state in case it is needed to recover 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 + size_t n = __libcpp_wcsnrtombs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), + static_cast<size_t>(to_end-to), &st, __l); 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 + n = __libcpp_wcrtomb_l(to_nxt, *frm, &save_state, __l); if (n == size_t(-1)) break; to_nxt += n; @@ -1590,11 +1557,7 @@ codecvt<wchar_t, char, mbstate_t>::do_out(state_type& st, { // 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 + n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l); if (n == size_t(-1)) // on error return error; if (n > static_cast<size_t>(to_end-to_nxt)) // is there room? @@ -1627,23 +1590,15 @@ codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st, { // save state in case it is needed to recover 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 + size_t n = __libcpp_mbsnrtowcs_l(to, &frm_nxt, static_cast<size_t>(fend-frm), + static_cast<size_t>(to_end-to), &st, __l); 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 + n = __libcpp_mbrtowc_l(to_nxt, frm, static_cast<size_t>(fend-frm), + &save_state, __l); switch (n) { case 0: @@ -1671,11 +1626,7 @@ codecvt<wchar_t, char, mbstate_t>::do_in(state_type& st, 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 + n = __libcpp_mbrtowc_l(to_nxt, frm_nxt, 1, &st, __l); if (n != 0) // on error return error; ++to_nxt; @@ -1695,11 +1646,7 @@ codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st, { 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 + size_t n = __libcpp_wcrtomb_l(tmp, intern_type(), &st, __l); if (n == size_t(-1) || n == 0) // on error return error; --n; @@ -1713,21 +1660,11 @@ codecvt<wchar_t, char, mbstate_t>::do_unshift(state_type& st, int codecvt<wchar_t, char, mbstate_t>::do_encoding() const _NOEXCEPT { -#ifndef __CloudABI__ -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - if (mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0) -#else - if (__mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0) -#endif + if (__libcpp_mbtowc_l(nullptr, nullptr, MB_LEN_MAX, __l) != 0) return -1; -#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 + if (__l == 0 || __libcpp_mb_cur_max_l(__l) == 1) // there are no known constant length encodings return 1; // which take more than 1 char to form a wchar_t return 0; } @@ -1745,11 +1682,7 @@ codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st, 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 + size_t n = __libcpp_mbrlen_l(frm, static_cast<size_t>(frm_end-frm), &st, __l); switch (n) { case 0: @@ -1771,11 +1704,7 @@ codecvt<wchar_t, char, mbstate_t>::do_length(state_type& st, int codecvt<wchar_t, char, mbstate_t>::do_max_length() const _NOEXCEPT { -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - return __l == 0 ? 1 : static_cast<int>( MB_CUR_MAX_L(__l)); -#else - return __l == 0 ? 1 : static_cast<int>(__mb_cur_max_l(__l)); -#endif + return __l == 0 ? 1 : static_cast<int>(__libcpp_mb_cur_max_l(__l)); } // Valid UTF ranges @@ -2894,10 +2823,10 @@ ucs4_to_utf16le(const uint32_t* frm, const uint32_t* frm_end, const uint32_t*& f to_nxt = to; if (mode & generate_header) { - if (to_end-to_nxt < 2) + if (to_end - to_nxt < 2) return codecvt_base::partial; - *to_nxt++ = static_cast<uint8_t>(0xFF); - *to_nxt++ = static_cast<uint8_t>(0xFE); + *to_nxt++ = static_cast<uint8_t>(0xFF); + *to_nxt++ = static_cast<uint8_t>(0xFE); } for (; frm_nxt < frm_end; ++frm_nxt) { @@ -4333,11 +4262,7 @@ numpunct_byname<char>::__init(const char* nm) 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 + lconv* lc = __libcpp_localeconv_l(loc.get()); if (*lc->decimal_point) __decimal_point_ = *lc->decimal_point; if (*lc->thousands_sep) @@ -4376,11 +4301,7 @@ numpunct_byname<wchar_t>::__init(const char* nm) 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 + lconv* lc = __libcpp_localeconv_l(loc.get()); if (*lc->decimal_point) __decimal_point_ = *lc->decimal_point; if (*lc->thousands_sep) @@ -4981,11 +4902,7 @@ __time_get_storage<wchar_t>::__analyze(char fmt, const ctype<wchar_t>& ct) wchar_t* wbb = wbuf; mbstate_t mb = {0}; const char* bb = buf; -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - size_t j = mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_); -#else - size_t j = __mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_); -#endif + size_t j = __libcpp_mbsrtowcs_l( wbb, &bb, countof(wbuf), &mb, __loc_); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wchar_t* wbe = wbb + j; @@ -5165,11 +5082,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) strftime_l(buf, countof(buf), "%A", &t, __loc_); mb = mbstate_t(); const char* bb = buf; -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#else - size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#endif + size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; @@ -5177,11 +5090,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) strftime_l(buf, countof(buf), "%a", &t, __loc_); mb = mbstate_t(); bb = buf; -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#else - j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#endif + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; @@ -5194,11 +5103,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) strftime_l(buf, countof(buf), "%B", &t, __loc_); mb = mbstate_t(); const char* bb = buf; -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#else - size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#endif + size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; @@ -5206,11 +5111,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) strftime_l(buf, countof(buf), "%b", &t, __loc_); mb = mbstate_t(); bb = buf; -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#else - j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#endif + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; @@ -5221,11 +5122,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) strftime_l(buf, countof(buf), "%p", &t, __loc_); mb = mbstate_t(); const char* bb = buf; -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - size_t j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#else - size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#endif + size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; @@ -5234,11 +5131,7 @@ __time_get_storage<wchar_t>::init(const ctype<wchar_t>& ct) strftime_l(buf, countof(buf), "%p", &t, __loc_); mb = mbstate_t(); bb = buf; -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#else - j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); -#endif + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, __loc_); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; @@ -5513,11 +5406,7 @@ __time_put::__do_put(wchar_t* __wb, wchar_t*& __we, const tm* __tm, __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, countof(__wb, __we), &mb, __loc_); -#else - size_t j = __mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_); -#endif + size_t j = __libcpp_mbsrtowcs_l(__wb, &__nb, countof(__wb, __we), &mb, __loc_); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); __we = __wb + j; @@ -5908,11 +5797,7 @@ moneypunct_byname<char, false>::init(const char* nm) 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 + lconv* lc = __libcpp_localeconv_l(loc.get()); if (*lc->mon_decimal_point) __decimal_point_ = *lc->mon_decimal_point; else @@ -5956,11 +5841,7 @@ moneypunct_byname<char, true>::init(const char* nm) 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 + lconv* lc = __libcpp_localeconv_l(loc.get()); if (*lc->mon_decimal_point) __decimal_point_ = *lc->mon_decimal_point; else @@ -6021,11 +5902,7 @@ moneypunct_byname<wchar_t, false>::init(const char* nm) 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 + lconv* lc = __libcpp_localeconv_l(loc.get()); if (*lc->mon_decimal_point) __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point); else @@ -6038,11 +5915,7 @@ moneypunct_byname<wchar_t, false>::init(const char* nm) 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, countof(wbuf), &mb, loc.get()); -#else - size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); -#endif + size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wchar_t* wbe = wbuf + j; @@ -6057,11 +5930,7 @@ moneypunct_byname<wchar_t, false>::init(const char* nm) { mb = mbstate_t(); bb = lc->positive_sign; -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); -#else - j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); -#endif + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; @@ -6073,11 +5942,7 @@ moneypunct_byname<wchar_t, false>::init(const char* nm) { mb = mbstate_t(); bb = lc->negative_sign; -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); -#else - j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); -#endif + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; @@ -6104,11 +5969,7 @@ moneypunct_byname<wchar_t, true>::init(const char* nm) 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 + lconv* lc = __libcpp_localeconv_l(loc.get()); if (*lc->mon_decimal_point) __decimal_point_ = static_cast<wchar_t>(*lc->mon_decimal_point); else @@ -6121,11 +5982,7 @@ moneypunct_byname<wchar_t, true>::init(const char* nm) 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, countof(wbuf), &mb, loc.get()); -#else - size_t j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); -#endif + size_t j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wchar_t* wbe = wbuf + j; @@ -6144,11 +6001,7 @@ moneypunct_byname<wchar_t, true>::init(const char* nm) { mb = mbstate_t(); bb = lc->positive_sign; -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); -#else - j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); -#endif + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; @@ -6164,11 +6017,7 @@ moneypunct_byname<wchar_t, true>::init(const char* nm) { mb = mbstate_t(); bb = lc->negative_sign; -#ifdef _LIBCPP_LOCALE__L_EXTENSIONS - j = mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); -#else - j = __mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); -#endif + j = __libcpp_mbsrtowcs_l(wbuf, &bb, countof(wbuf), &mb, loc.get()); if (j == size_t(-1)) __throw_runtime_error("locale not supported"); wbe = wbuf + j; diff --git a/contrib/libc++/src/memory.cpp b/contrib/libc++/src/memory.cpp index 5b81f26..15e947f 100644 --- a/contrib/libc++/src/memory.cpp +++ b/contrib/libc++/src/memory.cpp @@ -124,15 +124,15 @@ __shared_weak_count::__get_deleter(const type_info&) const _NOEXCEPT #endif // _LIBCPP_NO_RTTI -#if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS) +#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) static const std::size_t __sp_mut_count = 16; -static pthread_mutex_t mut_back_imp[__sp_mut_count] = +static __libcpp_mutex_t mut_back_imp[__sp_mut_count] = { - PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, - PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, - PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, - PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER + _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, + _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, + _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, + _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER, _LIBCPP_MUTEX_INITIALIZER }; static mutex* mut_back = reinterpret_cast<std::mutex*>(mut_back_imp); @@ -177,7 +177,7 @@ __get_sp_mut(const void* p) return muts[hash<const void*>()(p) & (__sp_mut_count-1)]; } -#endif // defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS) +#endif // !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER) void declare_reachable(void*) diff --git a/contrib/libc++/src/mutex.cpp b/contrib/libc++/src/mutex.cpp index 127e67a..9f808ca 100644 --- a/contrib/libc++/src/mutex.cpp +++ b/contrib/libc++/src/mutex.cpp @@ -23,13 +23,13 @@ const adopt_lock_t adopt_lock = {}; mutex::~mutex() { - pthread_mutex_destroy(&__m_); + __libcpp_mutex_destroy(&__m_); } void mutex::lock() { - int ec = pthread_mutex_lock(&__m_); + int ec = __libcpp_mutex_lock(&__m_); if (ec) __throw_system_error(ec, "mutex lock failed"); } @@ -37,13 +37,13 @@ mutex::lock() bool mutex::try_lock() _NOEXCEPT { - return pthread_mutex_trylock(&__m_) == 0; + return __libcpp_mutex_trylock(&__m_) == 0; } void mutex::unlock() _NOEXCEPT { - int ec = pthread_mutex_unlock(&__m_); + int ec = __libcpp_mutex_unlock(&__m_); (void)ec; assert(ec == 0); } @@ -52,36 +52,14 @@ mutex::unlock() _NOEXCEPT recursive_mutex::recursive_mutex() { - pthread_mutexattr_t attr; - int ec = pthread_mutexattr_init(&attr); + int ec = __libcpp_recursive_mutex_init(&__m_); 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"); + __throw_system_error(ec, "recursive_mutex constructor failed"); } recursive_mutex::~recursive_mutex() { - int e = pthread_mutex_destroy(&__m_); + int e = __libcpp_mutex_destroy(&__m_); (void)e; assert(e == 0); } @@ -89,7 +67,7 @@ recursive_mutex::~recursive_mutex() void recursive_mutex::lock() { - int ec = pthread_mutex_lock(&__m_); + int ec = __libcpp_mutex_lock(&__m_); if (ec) __throw_system_error(ec, "recursive_mutex lock failed"); } @@ -97,7 +75,7 @@ recursive_mutex::lock() void recursive_mutex::unlock() _NOEXCEPT { - int e = pthread_mutex_unlock(&__m_); + int e = __libcpp_mutex_unlock(&__m_); (void)e; assert(e == 0); } @@ -105,7 +83,7 @@ recursive_mutex::unlock() _NOEXCEPT bool recursive_mutex::try_lock() _NOEXCEPT { - return pthread_mutex_trylock(&__m_) == 0; + return __libcpp_mutex_trylock(&__m_) == 0; } // timed_mutex @@ -165,9 +143,9 @@ recursive_timed_mutex::~recursive_timed_mutex() void recursive_timed_mutex::lock() { - pthread_t id = pthread_self(); + __libcpp_thread_id id = __libcpp_thread_get_current_id(); unique_lock<mutex> lk(__m_); - if (pthread_equal(id, __id_)) + if (__libcpp_thread_id_equal(id, __id_)) { if (__count_ == numeric_limits<size_t>::max()) __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached"); @@ -183,9 +161,9 @@ recursive_timed_mutex::lock() bool recursive_timed_mutex::try_lock() _NOEXCEPT { - pthread_t id = pthread_self(); + __libcpp_thread_id id = __libcpp_thread_get_current_id(); unique_lock<mutex> lk(__m_, try_to_lock); - if (lk.owns_lock() && (__count_ == 0 || pthread_equal(id, __id_))) + if (lk.owns_lock() && (__count_ == 0 || __libcpp_thread_id_equal(id, __id_))) { if (__count_ == numeric_limits<size_t>::max()) return false; @@ -217,8 +195,8 @@ recursive_timed_mutex::unlock() _NOEXCEPT // keep in sync with: 7741191. #ifndef _LIBCPP_HAS_NO_THREADS -static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t cv = PTHREAD_COND_INITIALIZER; +static __libcpp_mutex_t mut = _LIBCPP_MUTEX_INITIALIZER; +static __libcpp_condvar_t cv = _LIBCPP_CONDVAR_INITIALIZER; #endif /// NOTE: Changes to flag are done via relaxed atomic stores @@ -247,9 +225,9 @@ __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*)) #endif // _LIBCPP_NO_EXCEPTIONS } #else // !_LIBCPP_HAS_NO_THREADS - pthread_mutex_lock(&mut); + __libcpp_mutex_lock(&mut); while (flag == 1) - pthread_cond_wait(&cv, &mut); + __libcpp_condvar_wait(&cv, &mut); if (flag == 0) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -257,26 +235,26 @@ __call_once(volatile unsigned long& flag, void* arg, void(*func)(void*)) { #endif // _LIBCPP_NO_EXCEPTIONS __libcpp_relaxed_store(&flag, 1ul); - pthread_mutex_unlock(&mut); + __libcpp_mutex_unlock(&mut); func(arg); - pthread_mutex_lock(&mut); + __libcpp_mutex_lock(&mut); __libcpp_relaxed_store(&flag, ~0ul); - pthread_mutex_unlock(&mut); - pthread_cond_broadcast(&cv); + __libcpp_mutex_unlock(&mut); + __libcpp_condvar_broadcast(&cv); #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - pthread_mutex_lock(&mut); + __libcpp_mutex_lock(&mut); __libcpp_relaxed_store(&flag, 0ul); - pthread_mutex_unlock(&mut); - pthread_cond_broadcast(&cv); + __libcpp_mutex_unlock(&mut); + __libcpp_condvar_broadcast(&cv); throw; } #endif // _LIBCPP_NO_EXCEPTIONS } else - pthread_mutex_unlock(&mut); + __libcpp_mutex_unlock(&mut); #endif // !_LIBCPP_HAS_NO_THREADS } diff --git a/contrib/libc++/src/regex.cpp b/contrib/libc++/src/regex.cpp index 17dd6ea..a736359 100644 --- a/contrib/libc++/src/regex.cpp +++ b/contrib/libc++/src/regex.cpp @@ -69,21 +69,12 @@ regex_error::~regex_error() throw() {} namespace { -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - struct collationnames { const char* elem_; char char_; }; -#if defined(__clang__) -#pragma clang diagnostic pop -#endif - const collationnames collatenames[] = { {"A", 0x41}, @@ -199,21 +190,12 @@ const collationnames collatenames[] = {"zero", 0x30} }; -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" -#endif - struct classnames { const char* elem_; regex_traits<char>::char_class_type mask_; }; -#if defined(__clang__) -#pragma clang diagnostic pop -#endif - const classnames ClassNames[] = { {"alnum", ctype_base::alnum}, diff --git a/contrib/libc++/src/strstream.cpp b/contrib/libc++/src/strstream.cpp index ea72813..0e2d7ff 100644 --- a/contrib/libc++/src/strstream.cpp +++ b/contrib/libc++/src/strstream.cpp @@ -11,6 +11,7 @@ #include "algorithm" #include "climits" #include "cstring" +#include "__debug" _LIBCPP_BEGIN_NAMESPACE_STD @@ -167,11 +168,13 @@ strstreambuf::overflow(int_type __c) buf = new char[new_size]; if (buf == nullptr) return int_type(EOF); - memcpy(buf, eback(), static_cast<size_t>(old_size)); + if (old_size != 0) { + _LIBCPP_ASSERT(eback(), "overflow copying from NULL"); + memcpy(buf, eback(), static_cast<size_t>(old_size)); + } ptrdiff_t ninp = gptr() - eback(); ptrdiff_t einp = egptr() - eback(); ptrdiff_t nout = pptr() - pbase(); - ptrdiff_t eout = epptr() - pbase(); if (__strmode_ & __allocated) { if (__pfree_) @@ -180,7 +183,7 @@ strstreambuf::overflow(int_type __c) delete [] eback(); } setg(buf, buf + ninp, buf + einp); - setp(buf + einp, buf + einp + eout); + setp(buf + einp, buf + new_size); pbump(static_cast<int>(nout)); __strmode_ |= __allocated; } diff --git a/contrib/libc++/src/system_error.cpp b/contrib/libc++/src/system_error.cpp index 3023e20..87f35ae 100644 --- a/contrib/libc++/src/system_error.cpp +++ b/contrib/libc++/src/system_error.cpp @@ -13,8 +13,17 @@ #include "system_error" #include "include/config_elast.h" +#include "cerrno" #include "cstring" +#include "cstdio" +#include "cstdlib" +#include "cassert" #include "string" +#include "string.h" + +#if defined(__ANDROID__) +#include <android/api-level.h> +#endif _LIBCPP_BEGIN_NAMESPACE_STD @@ -46,10 +55,56 @@ error_category::equivalent(const error_code& code, int condition) const _NOEXCEP return *this == code.category() && code.value() == condition; } +namespace { + +// GLIBC also uses 1024 as the maximum buffer size internally. +constexpr size_t strerror_buff_size = 1024; + +string do_strerror_r(int ev); + +#if defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC) \ + && (!defined(__ANDROID__) || __ANDROID_API__ >= 23) +// GNU Extended version +string do_strerror_r(int ev) { + char buffer[strerror_buff_size]; + char* ret = ::strerror_r(ev, buffer, strerror_buff_size); + return string(ret); +} +#else +// POSIX version +string do_strerror_r(int ev) { + char buffer[strerror_buff_size]; + const int old_errno = errno; + int ret; + if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) { + // If `ret == -1` then the error is specified using `errno`, otherwise + // `ret` represents the error. + const int new_errno = ret == -1 ? errno : ret; + errno = old_errno; + if (new_errno == EINVAL) { + std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev); + return string(buffer); + } else { + assert(new_errno == ERANGE); + // FIXME maybe? 'strerror_buff_size' is likely to exceed the + // maximum error size so ERANGE shouldn't be returned. + std::abort(); + } + } + return string(buffer); +} +#endif + +} // end namespace + string __do_message::message(int ev) const { - return string(strerror(ev)); +#if defined(_LIBCPP_HAS_NO_THREADS) + return string(::strerror(ev)); +#else + return do_strerror_r(ev); +#endif } class _LIBCPP_HIDDEN __generic_error_category diff --git a/contrib/libc++/src/thread.cpp b/contrib/libc++/src/thread.cpp index bd27f28..467402b 100644 --- a/contrib/libc++/src/thread.cpp +++ b/contrib/libc++/src/thread.cpp @@ -16,10 +16,15 @@ #include "future" #include "limits" #include <sys/types.h> -#if !defined(_WIN32) -# if !defined(__sun__) && !defined(__linux__) && !defined(_AIX) && !defined(__native_client__) && !defined(__CloudABI__) + +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +# include <sys/param.h> +# if defined(BSD) # include <sys/sysctl.h> -# endif // !defined(__sun__) && !defined(__linux__) && !defined(_AIX) && !defined(__native_client__) && !defined(__CloudABI__) +# endif // defined(BSD) +#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) + +#if !defined(_WIN32) # include <unistd.h> #endif // !_WIN32 @@ -41,14 +46,17 @@ thread::~thread() void thread::join() { - int ec = pthread_join(__t_, 0); + int ec = EINVAL; + if (__t_ != 0) + { + ec = __libcpp_thread_join(&__t_); + if (ec == 0) + __t_ = 0; + } #ifndef _LIBCPP_NO_EXCEPTIONS if (ec) throw system_error(error_code(ec, system_category()), "thread::join failed"); -#else - (void)ec; #endif // _LIBCPP_NO_EXCEPTIONS - __t_ = 0; } void @@ -57,7 +65,7 @@ thread::detach() int ec = EINVAL; if (__t_ != 0) { - ec = pthread_detach(__t_); + ec = __libcpp_thread_detach(&__t_); if (ec == 0) __t_ = 0; } |