diff options
-rw-r--r-- | common/aloptional.h | 344 | ||||
-rw-r--r-- | core/cpu_caps.cpp | 1 | ||||
-rw-r--r-- | core/helpers.cpp | 18 | ||||
-rw-r--r-- | core/helpers.h | 14 |
4 files changed, 25 insertions, 352 deletions
diff --git a/common/aloptional.h b/common/aloptional.h index 6de16799..45b0cf8a 100644 --- a/common/aloptional.h +++ b/common/aloptional.h @@ -1,353 +1,17 @@ #ifndef AL_OPTIONAL_H #define AL_OPTIONAL_H -#include <initializer_list> -#include <type_traits> -#include <utility> - -#include "almalloc.h" +#include <optional> namespace al { -struct nullopt_t { }; -struct in_place_t { }; - -constexpr nullopt_t nullopt{}; -constexpr in_place_t in_place{}; - -#define NOEXCEPT_AS(...) noexcept(noexcept(__VA_ARGS__)) - -namespace detail_ { -/* Base storage struct for an optional. Defines a trivial destructor, for types - * that can be trivially destructed. - */ -template<typename T, bool = std::is_trivially_destructible<T>::value> -struct optstore_base { - bool mHasValue{false}; - union { - char mDummy{}; - T mValue; - }; - - constexpr optstore_base() noexcept { } - template<typename ...Args> - constexpr explicit optstore_base(in_place_t, Args&& ...args) - noexcept(std::is_nothrow_constructible<T, Args...>::value) - : mHasValue{true}, mValue{std::forward<Args>(args)...} - { } - ~optstore_base() = default; -}; - -/* Specialization needing a non-trivial destructor. */ -template<typename T> -struct optstore_base<T, false> { - bool mHasValue{false}; - union { - char mDummy{}; - T mValue; - }; - - constexpr optstore_base() noexcept { } - template<typename ...Args> - constexpr explicit optstore_base(in_place_t, Args&& ...args) - noexcept(std::is_nothrow_constructible<T, Args...>::value) - : mHasValue{true}, mValue{std::forward<Args>(args)...} - { } - ~optstore_base() { if(mHasValue) al::destroy_at(std::addressof(mValue)); } -}; - -/* Next level of storage, which defines helpers to construct and destruct the - * stored object. - */ -template<typename T> -struct optstore_helper : public optstore_base<T> { - using optstore_base<T>::optstore_base; - - template<typename... Args> - constexpr void construct(Args&& ...args) noexcept(std::is_nothrow_constructible<T, Args...>::value) - { - al::construct_at(std::addressof(this->mValue), std::forward<Args>(args)...); - this->mHasValue = true; - } - - constexpr void reset() noexcept - { - if(this->mHasValue) - al::destroy_at(std::addressof(this->mValue)); - this->mHasValue = false; - } - - constexpr void assign(const optstore_helper &rhs) - noexcept(std::is_nothrow_copy_constructible<T>::value - && std::is_nothrow_copy_assignable<T>::value) - { - if(!rhs.mHasValue) - this->reset(); - else if(this->mHasValue) - this->mValue = rhs.mValue; - else - this->construct(rhs.mValue); - } - - constexpr void assign(optstore_helper&& rhs) - noexcept(std::is_nothrow_move_constructible<T>::value - && std::is_nothrow_move_assignable<T>::value) - { - if(!rhs.mHasValue) - this->reset(); - else if(this->mHasValue) - this->mValue = std::move(rhs.mValue); - else - this->construct(std::move(rhs.mValue)); - } -}; - -/* Define copy and move constructors and assignment operators, which may or may - * not be trivial. - */ -template<typename T, bool trivial_copy = std::is_trivially_copy_constructible<T>::value, - bool trivial_move = std::is_trivially_move_constructible<T>::value, - /* Trivial assignment is dependent on trivial construction+destruction. */ - bool = trivial_copy && std::is_trivially_copy_assignable<T>::value - && std::is_trivially_destructible<T>::value, - bool = trivial_move && std::is_trivially_move_assignable<T>::value - && std::is_trivially_destructible<T>::value> -struct optional_storage; - -/* Some versions of GCC have issues with 'this' in the following noexcept(...) - * statements, so this macro is a workaround. - */ -#define _this std::declval<optional_storage*>() - -/* Completely trivial. */ -template<typename T> -struct optional_storage<T, true, true, true, true> : public optstore_helper<T> { - using optstore_helper<T>::optstore_helper; - constexpr optional_storage() noexcept = default; - constexpr optional_storage(const optional_storage&) = default; - constexpr optional_storage(optional_storage&&) = default; - constexpr optional_storage& operator=(const optional_storage&) = default; - constexpr optional_storage& operator=(optional_storage&&) = default; -}; - -/* Non-trivial move assignment. */ -template<typename T> -struct optional_storage<T, true, true, true, false> : public optstore_helper<T> { - using optstore_helper<T>::optstore_helper; - constexpr optional_storage() noexcept = default; - constexpr optional_storage(const optional_storage&) = default; - constexpr optional_storage(optional_storage&&) = default; - constexpr optional_storage& operator=(const optional_storage&) = default; - constexpr optional_storage& operator=(optional_storage&& rhs) NOEXCEPT_AS(_this->assign(std::move(rhs))) - { this->assign(std::move(rhs)); return *this; } -}; - -/* Non-trivial move construction. */ -template<typename T> -struct optional_storage<T, true, false, true, false> : public optstore_helper<T> { - using optstore_helper<T>::optstore_helper; - constexpr optional_storage() noexcept = default; - constexpr optional_storage(const optional_storage&) = default; - constexpr optional_storage(optional_storage&& rhs) NOEXCEPT_AS(_this->construct(std::move(rhs.mValue))) - { if(rhs.mHasValue) this->construct(std::move(rhs.mValue)); } - constexpr optional_storage& operator=(const optional_storage&) = default; - constexpr optional_storage& operator=(optional_storage&& rhs) NOEXCEPT_AS(_this->assign(std::move(rhs))) - { this->assign(std::move(rhs)); return *this; } -}; - -/* Non-trivial copy assignment. */ -template<typename T> -struct optional_storage<T, true, true, false, true> : public optstore_helper<T> { - using optstore_helper<T>::optstore_helper; - constexpr optional_storage() noexcept = default; - constexpr optional_storage(const optional_storage&) = default; - constexpr optional_storage(optional_storage&&) = default; - constexpr optional_storage& operator=(const optional_storage &rhs) NOEXCEPT_AS(_this->assign(rhs)) - { this->assign(rhs); return *this; } - constexpr optional_storage& operator=(optional_storage&&) = default; -}; - -/* Non-trivial copy construction. */ -template<typename T> -struct optional_storage<T, false, true, false, true> : public optstore_helper<T> { - using optstore_helper<T>::optstore_helper; - constexpr optional_storage() noexcept = default; - constexpr optional_storage(const optional_storage &rhs) NOEXCEPT_AS(_this->construct(rhs.mValue)) - { if(rhs.mHasValue) this->construct(rhs.mValue); } - constexpr optional_storage(optional_storage&&) = default; - constexpr optional_storage& operator=(const optional_storage &rhs) NOEXCEPT_AS(_this->assign(rhs)) - { this->assign(rhs); return *this; } - constexpr optional_storage& operator=(optional_storage&&) = default; -}; - -/* Non-trivial assignment. */ -template<typename T> -struct optional_storage<T, true, true, false, false> : public optstore_helper<T> { - using optstore_helper<T>::optstore_helper; - constexpr optional_storage() noexcept = default; - constexpr optional_storage(const optional_storage&) = default; - constexpr optional_storage(optional_storage&&) = default; - constexpr optional_storage& operator=(const optional_storage &rhs) NOEXCEPT_AS(_this->assign(rhs)) - { this->assign(rhs); return *this; } - constexpr optional_storage& operator=(optional_storage&& rhs) NOEXCEPT_AS(_this->assign(std::move(rhs))) - { this->assign(std::move(rhs)); return *this; } -}; - -/* Non-trivial assignment, non-trivial move construction. */ -template<typename T> -struct optional_storage<T, true, false, false, false> : public optstore_helper<T> { - using optstore_helper<T>::optstore_helper; - constexpr optional_storage() noexcept = default; - constexpr optional_storage(const optional_storage&) = default; - constexpr optional_storage(optional_storage&& rhs) NOEXCEPT_AS(_this->construct(std::move(rhs.mValue))) - { if(rhs.mHasValue) this->construct(std::move(rhs.mValue)); } - constexpr optional_storage& operator=(const optional_storage &rhs) NOEXCEPT_AS(_this->assign(rhs)) - { this->assign(rhs); return *this; } - constexpr optional_storage& operator=(optional_storage&& rhs) NOEXCEPT_AS(_this->assign(std::move(rhs))) - { this->assign(std::move(rhs)); return *this; } -}; - -/* Non-trivial assignment, non-trivial copy construction. */ -template<typename T> -struct optional_storage<T, false, true, false, false> : public optstore_helper<T> { - using optstore_helper<T>::optstore_helper; - constexpr optional_storage() noexcept = default; - constexpr optional_storage(const optional_storage &rhs) NOEXCEPT_AS(_this->construct(rhs.mValue)) - { if(rhs.mHasValue) this->construct(rhs.mValue); } - constexpr optional_storage(optional_storage&&) = default; - constexpr optional_storage& operator=(const optional_storage &rhs) NOEXCEPT_AS(_this->assign(rhs)) - { this->assign(rhs); return *this; } - constexpr optional_storage& operator=(optional_storage&& rhs) NOEXCEPT_AS(_this->assign(std::move(rhs))) - { this->assign(std::move(rhs)); return *this; } -}; +constexpr auto nullopt = std::nullopt; -/* Completely non-trivial. */ template<typename T> -struct optional_storage<T, false, false, false, false> : public optstore_helper<T> { - using optstore_helper<T>::optstore_helper; - constexpr optional_storage() noexcept = default; - constexpr optional_storage(const optional_storage &rhs) NOEXCEPT_AS(_this->construct(rhs.mValue)) - { if(rhs.mHasValue) this->construct(rhs.mValue); } - constexpr optional_storage(optional_storage&& rhs) NOEXCEPT_AS(_this->construct(std::move(rhs.mValue))) - { if(rhs.mHasValue) this->construct(std::move(rhs.mValue)); } - constexpr optional_storage& operator=(const optional_storage &rhs) NOEXCEPT_AS(_this->assign(rhs)) - { this->assign(rhs); return *this; } - constexpr optional_storage& operator=(optional_storage&& rhs) NOEXCEPT_AS(_this->assign(std::move(rhs))) - { this->assign(std::move(rhs)); return *this; } -}; - -#undef _this - -} // namespace detail_ - -#define REQUIRES(...) std::enable_if_t<(__VA_ARGS__),bool> = true - -template<typename T> -class optional { - using storage_t = detail_::optional_storage<T>; - - storage_t mStore{}; - -public: - using value_type = T; - - constexpr optional() = default; - constexpr optional(const optional&) = default; - constexpr optional(optional&&) = default; - constexpr optional(nullopt_t) noexcept { } - template<typename ...Args> - constexpr explicit optional(in_place_t, Args&& ...args) - NOEXCEPT_AS(storage_t{al::in_place, std::forward<Args>(args)...}) - : mStore{al::in_place, std::forward<Args>(args)...} - { } - template<typename U, REQUIRES(std::is_constructible<T, U&&>::value - && !std::is_same<std::decay_t<U>, al::in_place_t>::value - && !std::is_same<std::decay_t<U>, optional<T>>::value - && std::is_convertible<U&&, T>::value)> - constexpr optional(U&& rhs) NOEXCEPT_AS(storage_t{al::in_place, std::forward<U>(rhs)}) - : mStore{al::in_place, std::forward<U>(rhs)} - { } - template<typename U, REQUIRES(std::is_constructible<T, U&&>::value - && !std::is_same<std::decay_t<U>, al::in_place_t>::value - && !std::is_same<std::decay_t<U>, optional<T>>::value - && !std::is_convertible<U&&, T>::value)> - constexpr explicit optional(U&& rhs) NOEXCEPT_AS(storage_t{al::in_place, std::forward<U>(rhs)}) - : mStore{al::in_place, std::forward<U>(rhs)} - { } - ~optional() = default; - - constexpr optional& operator=(const optional&) = default; - constexpr optional& operator=(optional&&) = default; - constexpr optional& operator=(nullopt_t) noexcept { mStore.reset(); return *this; } - template<typename U=T> - constexpr std::enable_if_t<std::is_constructible<T, U>::value - && std::is_assignable<T&, U>::value - && !std::is_same<std::decay_t<U>, optional<T>>::value - && (!std::is_same<std::decay_t<U>, T>::value || !std::is_scalar<U>::value), - optional&> operator=(U&& rhs) - { - if(mStore.mHasValue) - mStore.mValue = std::forward<U>(rhs); - else - mStore.construct(std::forward<U>(rhs)); - return *this; - } - - constexpr const T* operator->() const { return std::addressof(mStore.mValue); } - constexpr T* operator->() { return std::addressof(mStore.mValue); } - constexpr const T& operator*() const& { return mStore.mValue; } - constexpr T& operator*() & { return mStore.mValue; } - constexpr const T&& operator*() const&& { return std::move(mStore.mValue); } - constexpr T&& operator*() && { return std::move(mStore.mValue); } - - constexpr explicit operator bool() const noexcept { return mStore.mHasValue; } - constexpr bool has_value() const noexcept { return mStore.mHasValue; } - - constexpr T& value() & { return mStore.mValue; } - constexpr const T& value() const& { return mStore.mValue; } - constexpr T&& value() && { return std::move(mStore.mValue); } - constexpr const T&& value() const&& { return std::move(mStore.mValue); } - - template<typename U> - constexpr T value_or(U&& defval) const& - { return bool(*this) ? **this : static_cast<T>(std::forward<U>(defval)); } - template<typename U> - constexpr T value_or(U&& defval) && - { return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(defval)); } - - template<typename ...Args> - constexpr T& emplace(Args&& ...args) - { - mStore.reset(); - mStore.construct(std::forward<Args>(args)...); - return mStore.mValue; - } - template<typename U, typename ...Args> - constexpr std::enable_if_t<std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, - T&> emplace(std::initializer_list<U> il, Args&& ...args) - { - mStore.reset(); - mStore.construct(il, std::forward<Args>(args)...); - return mStore.mValue; - } - - constexpr void reset() noexcept { mStore.reset(); } -}; - -template<typename T> -constexpr optional<std::decay_t<T>> make_optional(T&& arg) -{ return optional<std::decay_t<T>>{in_place, std::forward<T>(arg)}; } - -template<typename T, typename... Args> -constexpr optional<T> make_optional(Args&& ...args) -{ return optional<T>{in_place, std::forward<Args>(args)...}; } +using optional = std::optional<T>; -template<typename T, typename U, typename... Args> -constexpr optional<T> make_optional(std::initializer_list<U> il, Args&& ...args) -{ return optional<T>{in_place, il, std::forward<Args>(args)...}; } +using std::make_optional; -#undef REQUIRES -#undef NOEXCEPT_AS } // namespace al #endif /* AL_OPTIONAL_H */ diff --git a/core/cpu_caps.cpp b/core/cpu_caps.cpp index d4b4d86c..165edb24 100644 --- a/core/cpu_caps.cpp +++ b/core/cpu_caps.cpp @@ -17,6 +17,7 @@ #include <intrin.h> #endif +#include <algorithm> #include <array> #include <cctype> #include <string> diff --git a/core/helpers.cpp b/core/helpers.cpp index 99cf009c..71ddbc23 100644 --- a/core/helpers.cpp +++ b/core/helpers.cpp @@ -41,7 +41,7 @@ const PathNamePair &GetProcBinary() static al::optional<PathNamePair> procbin; if(procbin) return *procbin; - auto fullpath = al::vector<WCHAR>(256); + auto fullpath = std::vector<WCHAR>(256); DWORD len{GetModuleFileNameW(nullptr, fullpath.data(), static_cast<DWORD>(fullpath.size()))}; while(len == fullpath.size()) { @@ -75,7 +75,7 @@ const PathNamePair &GetProcBinary() namespace { -void DirectorySearch(const char *path, const char *ext, al::vector<std::string> *const results) +void DirectorySearch(const char *path, const char *ext, std::vector<std::string> *const results) { std::string pathstr{path}; pathstr += "\\*"; @@ -106,7 +106,7 @@ void DirectorySearch(const char *path, const char *ext, al::vector<std::string> } // namespace -al::vector<std::string> SearchDataFiles(const char *ext, const char *subdir) +std::vector<std::string> SearchDataFiles(const char *ext, const char *subdir) { auto is_slash = [](int c) noexcept -> int { return (c == '\\' || c == '/'); }; @@ -114,7 +114,7 @@ al::vector<std::string> SearchDataFiles(const char *ext, const char *subdir) std::lock_guard<std::mutex> _{search_lock}; /* If the path is absolute, use it directly. */ - al::vector<std::string> results; + std::vector<std::string> results; if(isalpha(subdir[0]) && subdir[1] == ':' && is_slash(subdir[2])) { std::string path{subdir}; @@ -212,7 +212,7 @@ const PathNamePair &GetProcBinary() static al::optional<PathNamePair> procbin; if(procbin) return *procbin; - al::vector<char> pathname; + std::vector<char> pathname; #ifdef __FreeBSD__ size_t pathlen; int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; @@ -295,7 +295,7 @@ const PathNamePair &GetProcBinary() namespace { -void DirectorySearch(const char *path, const char *ext, al::vector<std::string> *const results) +void DirectorySearch(const char *path, const char *ext, std::vector<std::string> *const results) { TRACE("Searching %s for *%s\n", path, ext); DIR *dir{opendir(path)}; @@ -331,12 +331,12 @@ void DirectorySearch(const char *path, const char *ext, al::vector<std::string> } // namespace -al::vector<std::string> SearchDataFiles(const char *ext, const char *subdir) +std::vector<std::string> SearchDataFiles(const char *ext, const char *subdir) { static std::mutex search_lock; std::lock_guard<std::mutex> _{search_lock}; - al::vector<std::string> results; + std::vector<std::string> results; if(subdir[0] == '/') { DirectorySearch(subdir, ext, &results); @@ -348,7 +348,7 @@ al::vector<std::string> SearchDataFiles(const char *ext, const char *subdir) DirectorySearch(localpath->c_str(), ext, &results); else { - al::vector<char> cwdbuf(256); + std::vector<char> cwdbuf(256); while(!getcwd(cwdbuf.data(), cwdbuf.size())) { if(errno != ERANGE) diff --git a/core/helpers.h b/core/helpers.h index f0bfcf1b..df51c116 100644 --- a/core/helpers.h +++ b/core/helpers.h @@ -1,18 +1,26 @@ #ifndef CORE_HELPERS_H #define CORE_HELPERS_H +#include <utility> #include <string> +#include <vector> -#include "vector.h" +struct PathNamePair { + std::string path, fname; -struct PathNamePair { std::string path, fname; }; + PathNamePair() = default; + template<typename T, typename U> + PathNamePair(T&& path_, U&& fname_) + : path{std::forward<T>(path_)}, fname{std::forward<U>(fname_)} + { } +}; const PathNamePair &GetProcBinary(void); extern int RTPrioLevel; extern bool AllowRTTimeLimit; void SetRTPriority(void); -al::vector<std::string> SearchDataFiles(const char *match, const char *subdir); +std::vector<std::string> SearchDataFiles(const char *match, const char *subdir); #endif /* CORE_HELPERS_H */ |