diff options
Diffstat (limited to 'include/cru/common')
42 files changed, 0 insertions, 3773 deletions
diff --git a/include/cru/common/Base.h b/include/cru/common/Base.h deleted file mode 100644 index 8a6a7634..00000000 --- a/include/cru/common/Base.h +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once -#include "PreConfig.h" // IWYU pragma: keep - -#include <cassert> -#include <cstddef> -#include <functional> -#include <memory> - -#ifdef CRU_PLATFORM_WINDOWS -#ifdef CRU_BASE_EXPORT_API -#define CRU_BASE_API __declspec(dllexport) -#else -#define CRU_BASE_API __declspec(dllimport) -#endif -#else -#define CRU_BASE_API -#endif - -#define CRU_UNUSED(entity) static_cast<void>(entity); - -#define CRU__CONCAT(a, b) a##b -#define CRU_MAKE_UNICODE_LITERAL(str) CRU__CONCAT(u, #str) - -#define CRU_DEFAULT_COPY(classname) \ - classname(const classname&) = default; \ - classname& operator=(const classname&) = default; - -#define CRU_DEFAULT_MOVE(classname) \ - classname(classname&&) = default; \ - classname& operator=(classname&&) = default; - -#define CRU_DELETE_COPY(classname) \ - classname(const classname&) = delete; \ - classname& operator=(const classname&) = delete; - -#define CRU_DELETE_MOVE(classname) \ - classname(classname&&) = delete; \ - classname& operator=(classname&&) = delete; - -#define CRU_DEFAULT_DESTRUCTOR(classname) ~classname() = default; - -#define CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(classname) \ - classname() = default; \ - ~classname() = default; - -#define CRU_DEFINE_COMPARE_OPERATORS(classname) \ - inline bool operator==(const classname& left, const classname& right) { \ - return left.Compare(right) == 0; \ - } \ - \ - inline bool operator!=(const classname& left, const classname& right) { \ - return left.Compare(right) != 0; \ - } \ - \ - inline bool operator<(const classname& left, const classname& right) { \ - return left.Compare(right) < 0; \ - } \ - \ - inline bool operator<=(const classname& left, const classname& right) { \ - return left.Compare(right) <= 0; \ - } \ - \ - inline bool operator>(const classname& left, const classname& right) { \ - return left.Compare(right) > 0; \ - } \ - \ - inline bool operator>=(const classname& left, const classname& right) { \ - return left.Compare(right) >= 0; \ - } - -namespace cru { -class CRU_BASE_API Object { - public: - Object() = default; - CRU_DEFAULT_COPY(Object) - CRU_DEFAULT_MOVE(Object) - virtual ~Object() = default; -}; - -struct CRU_BASE_API Interface { - Interface() = default; - CRU_DELETE_COPY(Interface) - CRU_DELETE_MOVE(Interface) - virtual ~Interface() = default; -}; - -[[noreturn]] void CRU_BASE_API UnreachableCode(); - -using Index = std::ptrdiff_t; - -inline void Expects(bool condition) { assert(condition); } -inline void Ensures(bool condition) { assert(condition); } -template <typename T> -inline void Expects(const std::shared_ptr<T>& ptr) { - assert(ptr != nullptr); -} -template <typename T> -inline void Ensures(const std::shared_ptr<T>& ptr) { - assert(ptr != nullptr); -} - -// https://www.boost.org/doc/libs/1_54_0/doc/html/hash/reference.html#boost.hash_combine -template <class T> -inline void hash_combine(std::size_t& s, const T& v) { - std::hash<T> h; - s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); -} - -#define CRU_DEFINE_CLASS_LOG_TAG(tag) \ - private: \ - constexpr static const char16_t* kLogTag = tag; -} // namespace cru diff --git a/include/cru/common/Bitmask.h b/include/cru/common/Bitmask.h deleted file mode 100644 index 9b6b8957..00000000 --- a/include/cru/common/Bitmask.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include <functional> - -namespace cru { -template <typename Tag, typename TUnderlying = unsigned> -struct Bitmask final { - using Underlying = TUnderlying; - - constexpr Bitmask() : value(0) {} - constexpr explicit Bitmask(TUnderlying value) : value(value) {} - - static constexpr Bitmask FromOffset(int offset) { - return Bitmask(static_cast<TUnderlying>(1u << offset)); - } - - constexpr bool Has(Bitmask rhs) const { return (value & rhs.value) != 0; } - - Bitmask operator|(Bitmask rhs) const { return Bitmask(value | rhs.value); } - Bitmask operator&(Bitmask rhs) const { return Bitmask(value & rhs.value); } - Bitmask operator^(Bitmask rhs) const { return Bitmask(value ^ rhs.value); } - Bitmask operator~() const { return Bitmask(~value); } - Bitmask& operator|=(Bitmask rhs) { - value |= rhs.value; - return *this; - } - Bitmask& operator&=(Bitmask rhs) { - value &= rhs.value; - return *this; - } - Bitmask& operator^=(Bitmask rhs) { - value ^= rhs.value; - return *this; - } - - bool operator==(Bitmask rhs) const { return this->value == rhs.value; } - bool operator!=(Bitmask rhs) const { return this->value != rhs.value; } - - explicit operator TUnderlying() const { return value; } - operator bool() const { return value != 0; } - - TUnderlying value; -}; -} // namespace cru - -namespace std { -template <typename Tag, typename TUnderlying> -struct hash<cru::Bitmask<Tag, TUnderlying>> { - using Bitmask = cru::Bitmask<Tag, TUnderlying>; - - std::size_t operator()(Bitmask bitmask) const { - return std::hash<TUnderlying>{}(bitmask.value); - } -}; -} // namespace std diff --git a/include/cru/common/Buffer.h b/include/cru/common/Buffer.h deleted file mode 100644 index bc2e2a26..00000000 --- a/include/cru/common/Buffer.h +++ /dev/null @@ -1,161 +0,0 @@ -#pragma once - -#include "Base.h" - -namespace cru { -class Buffer final { - friend void swap(Buffer& left, Buffer& right) noexcept; - - public: - Buffer(); - explicit Buffer(Index size); - - Buffer(const Buffer& other); - Buffer(Buffer&& other) noexcept; - - Buffer& operator=(const Buffer& other); - Buffer& operator=(Buffer&& other) noexcept; - - ~Buffer(); - - public: - Index GetBufferSize() const { return size_; } - Index GetUsedSize() const { return used_end_ - used_begin_; } - bool IsNull() const { return ptr_ == nullptr; } - bool IsUsedReachEnd() const { return used_end_ == size_; } - - Index GetFrontFree() const { return used_begin_; } - Index GetBackFree() const { return size_ - used_end_; } - - Index GetUsedBegin() const { return used_begin_; } - Index GetUsedEnd() const { return used_end_; } - - std::byte* GetPtr() { return GetPtrAt(0); } - const std::byte* GetPtr() const { return GetPtrAt(0); } - - std::byte* GetPtrAt(Index index) { return ptr_ + index; } - const std::byte* GetPtrAt(Index index) const { return ptr_ + index; } - - std::byte& GetRefAt(Index index) { return *GetPtrAt(index); } - const std::byte& GetRefAt(Index index) const { return *GetPtrAt(index); } - - std::byte* GetUsedBeginPtr() { return GetPtrAt(GetUsedBegin()); } - const std::byte* GetUsedBeginPtr() const { return GetPtrAt(GetUsedBegin()); } - std::byte* GetUsedEndPtr() { return GetPtrAt(GetUsedEnd()); } - const std::byte* GetUsedEndPtr() const { return GetPtrAt(GetUsedEnd()); } - - std::byte GetByteAt(Index index) const { return ptr_[index]; } - void SetByteAt(Index index, std::byte value) { ptr_[index] = value; } - - void AssignBytes(std::byte* src, Index src_size, bool use_memmove = false) { - return AssignBytes(0, src, 0, src_size, use_memmove); - } - void AssignBytes(Index dst_offset, std::byte* src, Index src_size, - bool use_memmove = false) { - return AssignBytes(dst_offset, src, 0, src_size, use_memmove); - } - void AssignBytes(Index dst_offset, std::byte* src, Index src_offset, - Index src_size, bool use_memmove = false); - - /** - * @brief Change the size of the buffer. - * - * Unless new size is the same as current size, the buffer is always released - * and a new one is allocated. If preserve_used is true, the used size and old - * data is copied to the new buffer. If new size is smaller than old used - * size, then exceeded data will be lost. - */ - void ResizeBuffer(Index new_size, bool preserve_used); - - /** - * @brief Append data to the front of used bytes and increase used size. - * @return The actual size of data saved. - * - * If there is no enough space left for new data, the rest space will be - * written and the size of it will be returned, leaving exceeded data not - * saved. - */ - Index PushFront(const std::byte* other, Index other_size, - bool use_memmove = false); - - bool PushBack(std::byte b); - - /** - * @brief Append data to the back of used bytes and increase used size. - * @return The actual size of data saved. - * - * If there is no enough space left for new data, the rest space will be - * written and the size of it will be returned, leaving exceeded data not - * saved. - */ - Index PushBack(const std::byte* other, Index other_size, - bool use_memmove = false); - - void PushBackCount(Index count); - - /** - * @brief Move forward the used-begin ptr. - * @return The actual size moved forward. - * - * If given size is bigger than current used size, the used size will be - * returned and set to 0. - */ - Index PopFront(Index size); - - /** - * @brief Pop front data of used bytes into another buffer. - * @return The actual size popped. - * - * If given size is bigger than current used size, then only current used size - * of bytes will be popped. If given size is smaller than current used size, - * then only given size of bytes will be popped. - */ - Index PopFront(std::byte* buffer, Index size, bool use_memmove = false); - - /** - * @brief Move backward the used-end ptr. - * @return The actual size moved backward. - * - * If given size is bigger than current used size, the used size will be - * returned and set to 0. - */ - Index PopEnd(Index size); - - /** - * @brief Pop back data of used bytes into another buffer. - * @return The actual size popped. - * - * If given size is bigger than current used size, then only current used size - * of bytes will be popped. If given size is smaller than current used size, - * then only given size of bytes will be popped. - */ - Index PopEnd(std::byte* buffer, Index size, bool use_memmove = false); - - operator std::byte*() { return GetPtr(); } - operator const std::byte*() const { return GetPtr(); } - - /** - * @brief Detach internal buffer and return it. - * @param size If not null, size of the buffer is written to it. - * @return The buffer pointer. May be nullptr. - * - * After detach, you are responsible to delete[] it. - */ - std::byte* Detach(Index* size = nullptr); - - private: - void Copy_(const Buffer& other); - void Move_(Buffer&& other) noexcept; - void Delete_() noexcept; - - void AssertValid(); - - private: - std::byte* ptr_; - Index size_; - Index used_begin_; - Index used_end_; -}; - -void swap(Buffer& left, Buffer& right) noexcept; -} // namespace cru diff --git a/include/cru/common/ClonablePtr.h b/include/cru/common/ClonablePtr.h deleted file mode 100644 index a2a88758..00000000 --- a/include/cru/common/ClonablePtr.h +++ /dev/null @@ -1,216 +0,0 @@ -#pragma once - -#include <cstddef> -#include <functional> -#include <memory> -#include <type_traits> - -namespace cru { -template <typename TClonable> -class ClonablePtr { - template <typename T> - friend class ClonablePtr; - - public: - using element_type = typename std::unique_ptr<TClonable>::element_type; - using pointer = typename std::unique_ptr<TClonable>::pointer; - - ClonablePtr() = default; - ClonablePtr(std::nullptr_t) noexcept : ptr_(nullptr) {} - explicit ClonablePtr(pointer p) noexcept : ptr_(p) {} - ClonablePtr(std::unique_ptr<element_type>&& p) noexcept - : ptr_(std::move(p)) {} - template <typename O, - std::enable_if_t<std::is_convertible_v< - typename ClonablePtr<O>::pointer, pointer>, - int> = 0> - ClonablePtr(std::unique_ptr<O>&& p) : ptr_(std::move(p)) {} - ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} - ClonablePtr(ClonablePtr&& other) = default; - template <typename O, - std::enable_if_t<std::is_convertible_v< - typename ClonablePtr<O>::pointer, pointer>, - int> = 0> - ClonablePtr(const ClonablePtr<O>& other) : ptr_(other.ptr_->Clone()) {} - template <typename O, - std::enable_if_t<std::is_convertible_v< - typename ClonablePtr<O>::pointer, pointer>, - int> = 0> - ClonablePtr(ClonablePtr<O>&& other) noexcept : ptr_(std::move(other.ptr_)) {} - ClonablePtr& operator=(std::nullptr_t) noexcept { - ptr_ = nullptr; - return *this; - } - ClonablePtr& operator=(std::unique_ptr<element_type>&& other) noexcept { - ptr_ = std::move(other); - return *this; - } - template <typename O, - std::enable_if_t<std::is_convertible_v< - typename ClonablePtr<O>::pointer, pointer>, - int> = 0> - ClonablePtr& operator=(std::unique_ptr<O>&& p) noexcept { - ptr_ = std::move(p); - return *this; - } - ClonablePtr& operator=(const ClonablePtr& other) { - if (this != &other) { - ptr_ = std::unique_ptr<element_type>(other.ptr_->Clone()); - } - return *this; - } - ClonablePtr& operator=(ClonablePtr&& other) = default; - template <typename O, - std::enable_if_t<std::is_convertible_v< - typename ClonablePtr<O>::pointer, pointer>, - int> = 0> - ClonablePtr& operator=(const ClonablePtr<O>& other) noexcept { - if (this != &other) { - ptr_ = std::unique_ptr<element_type>(other.ptr_->Clone()); - } - return *this; - } - template <typename O, - std::enable_if_t<std::is_convertible_v< - typename ClonablePtr<O>::pointer, pointer>, - int> = 0> - ClonablePtr& operator=(ClonablePtr<O>&& other) noexcept { - ptr_ = std::move(other.ptr_); - } - - ~ClonablePtr() = default; - - public: - pointer release() noexcept { return ptr_.release(); } - void reset(pointer p = pointer()) noexcept { ptr_.reset(p); } - void swap(ClonablePtr& other) noexcept { ptr_.swap(other.ptr_); } - - public: - pointer get() const noexcept { return ptr_.get(); } - - operator bool() const noexcept { return ptr_ != nullptr; } - - element_type& operator*() const noexcept { return *ptr_; } - pointer operator->() const noexcept { return ptr_.get(); } - - int Compare(const ClonablePtr& other) const noexcept { - if (ptr_ == other.ptr_) { - return 0; - } else if (ptr_ < other.ptr_) { - return -1; - } else { - return 1; - } - } - - int Compare(nullptr_t) const noexcept { return ptr_ ? 1 : 0; } - - private: - std::unique_ptr<element_type> ptr_; -}; - -template <typename T> -void swap(ClonablePtr<T>& left, ClonablePtr<T>& right) noexcept { - left.swap(right); -} - -template <typename T> -bool operator==(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { - return left.Compare(right) == 0; -} - -template <typename T> -bool operator!=(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { - return left.Compare(right) != 0; -} - -template <typename T> -bool operator<(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { - return left.Compare(right) < 0; -} - -template <typename T> -bool operator<=(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { - return left.Compare(right) <= 0; -} - -template <typename T> -bool operator>(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { - return left.Compare(right) > 0; -} - -template <typename T> -bool operator>=(const ClonablePtr<T>& left, const ClonablePtr<T>& right) { - return left.Compare(right) >= 0; -} - -template <typename T> -bool operator==(const ClonablePtr<T>& left, std::nullptr_t) { - return left.Compare(nullptr) == 0; -} - -template <typename T> -bool operator!=(const ClonablePtr<T>& left, std::nullptr_t) { - return left.Compare(nullptr) != 0; -} - -template <typename T> -bool operator<(const ClonablePtr<T>& left, std::nullptr_t) { - return left.Compare(nullptr) < 0; -} - -template <typename T> -bool operator<=(const ClonablePtr<T>& left, std::nullptr_t) { - return left.Compare(nullptr) <= 0; -} - -template <typename T> -bool operator>(const ClonablePtr<T>& left, std::nullptr_t) { - return left.Compare(nullptr) > 0; -} - -template <typename T> -bool operator>=(const ClonablePtr<T>& left, std::nullptr_t) { - return left.Compare(nullptr) >= 0; -} - -template <typename T> -bool operator==(std::nullptr_t, const ClonablePtr<T>& right) { - return right.Compare(nullptr) == 0; -} - -template <typename T> -bool operator!=(std::nullptr_t, const ClonablePtr<T>& right) { - return right.Compare(nullptr) != 0; -} - -template <typename T> -bool operator<(std::nullptr_t, const ClonablePtr<T>& right) { - return right.Compare(nullptr) > 0; -} - -template <typename T> -bool operator<=(std::nullptr_t, const ClonablePtr<T>& right) { - return right.Compare(nullptr) >= 0; -} - -template <typename T> -bool operator>(std::nullptr_t, const ClonablePtr<T>& right) { - return right.Compare(nullptr) < 0; -} - -template <typename T> -bool operator>=(std::nullptr_t, const ClonablePtr<T>& right) { - return right.Compare(nullptr) <= 0; -} - -} // namespace cru - -namespace std { -template <typename T> -struct hash<cru::ClonablePtr<T>> { - std::size_t operator()(const cru::ClonablePtr<T>& p) const { - return std::hash<typename cru::ClonablePtr<T>::pointer>(p.get()); - } -}; -} // namespace std diff --git a/include/cru/common/Event.h b/include/cru/common/Event.h deleted file mode 100644 index 18d2c570..00000000 --- a/include/cru/common/Event.h +++ /dev/null @@ -1,281 +0,0 @@ -#pragma once -#include "Base.h" - -#include "SelfResolvable.h" - -#include <algorithm> -#include <cassert> -#include <functional> -#include <memory> -#include <utility> -#include <vector> - -namespace cru { -class EventRevoker; - -namespace details { -template <class> -inline constexpr bool always_false_v = false; - -// Base class of all Event<T...>. -// It erases event args types and provides a -// unified form to create event revoker and -// revoke(remove) handler. -class EventBase : public SelfResolvable<EventBase> { - friend EventRevoker; - - protected: - using EventHandlerToken = long; - - EventBase() {} - CRU_DELETE_COPY(EventBase) - CRU_DEFAULT_MOVE(EventBase) - virtual ~EventBase() = default; - - // Remove the handler with the given token. If the token - // corresponds to no handler (which might have be revoked - // before), then nothing will be done. - virtual void RemoveHandler(EventHandlerToken token) = 0; - - // Create a revoker with the given token. - inline EventRevoker CreateRevoker(EventHandlerToken token); -}; -} // namespace details - -// A non-copyable and movable event revoker. -// Call function call operator to revoke the handler. -class EventRevoker { - friend details::EventBase; - - private: - EventRevoker(ObjectResolver<details::EventBase>&& resolver, - details::EventBase::EventHandlerToken token) - : resolver_(std::move(resolver)), token_(token) {} - - public: - EventRevoker(const EventRevoker& other) = default; - EventRevoker(EventRevoker&& other) = default; - EventRevoker& operator=(const EventRevoker& other) = default; - EventRevoker& operator=(EventRevoker&& other) = default; - ~EventRevoker() = default; - - // Revoke the registered handler. If the event has already - // been destroyed, then nothing will be done. If one of the - // copies calls this, then other copies's calls will have no - // effect. (They have the same token.) - void operator()() const { - if (const auto event = resolver_.Resolve()) { - event->RemoveHandler(token_); - } - } - - private: - ObjectResolver<details::EventBase> resolver_; - details::EventBase::EventHandlerToken token_; -}; - -inline EventRevoker details::EventBase::CreateRevoker(EventHandlerToken token) { - return EventRevoker(CreateResolver(), token); -} - -// int -> int -// Point -> const Point& -// int& -> int& -template <typename TRaw> -using DeducedEventArgs = std::conditional_t< - std::is_lvalue_reference_v<TRaw>, TRaw, - std::conditional_t<std::is_scalar_v<TRaw>, TRaw, const TRaw&>>; - -struct IBaseEvent { - protected: - IBaseEvent() = default; - CRU_DELETE_COPY(IBaseEvent) - CRU_DEFAULT_MOVE(IBaseEvent) - ~IBaseEvent() = default; // Note that user can't destroy a Event via IEvent. - // So destructor should be protected. - - using SpyOnlyHandler = std::function<void()>; - - public: - virtual EventRevoker AddSpyOnlyHandler(SpyOnlyHandler handler) = 0; -}; - -// Provides an interface of event. -// IEvent only allow to add handler but not to raise the event. You may -// want to create an Event object and expose IEvent only so users won't -// be able to emit the event. -template <typename TEventArgs> -struct IEvent : virtual IBaseEvent { - public: - using EventArgs = DeducedEventArgs<TEventArgs>; - using EventHandler = std::function<void(EventArgs)>; - using ShortCircuitHandler = std::function<bool(EventArgs)>; - - protected: - IEvent() = default; - CRU_DELETE_COPY(IEvent) - CRU_DEFAULT_MOVE(IEvent) - ~IEvent() = default; // Note that user can't destroy a Event via IEvent. So - // destructor should be protected. - - public: - virtual EventRevoker AddHandler(EventHandler handler) = 0; - virtual EventRevoker AddShortCircuitHandler(ShortCircuitHandler handler) = 0; - virtual EventRevoker PrependShortCircuitHandler( - ShortCircuitHandler handler) = 0; -}; - -// A non-copyable non-movable Event class. -// It stores a list of event handlers. -template <typename TEventArgs> -class Event : public details::EventBase, public IEvent<TEventArgs> { - using typename IEvent<TEventArgs>::EventArgs; - - using typename IBaseEvent::SpyOnlyHandler; - using typename IEvent<TEventArgs>::EventHandler; - using typename IEvent<TEventArgs>::ShortCircuitHandler; - - private: - struct HandlerData { - HandlerData(EventHandlerToken token, ShortCircuitHandler handler) - : token(token), handler(std::move(handler)) {} - EventHandlerToken token; - ShortCircuitHandler handler; - }; - - public: - Event() = default; - CRU_DELETE_COPY(Event) - CRU_DEFAULT_MOVE(Event) - ~Event() = default; - - EventRevoker AddSpyOnlyHandler(SpyOnlyHandler handler) override { - return AddShortCircuitHandler([handler = std::move(handler)](EventArgs) { - handler(); - return false; - }); - } - - EventRevoker AddHandler(EventHandler handler) override { - return AddShortCircuitHandler( - [handler = std::move(handler)](EventArgs args) { - handler(args); - return false; - }); - } - - // Handler return true to short circuit following handlers. - EventRevoker AddShortCircuitHandler(ShortCircuitHandler handler) override { - const auto token = current_token_++; - this->handler_data_list_.emplace_back(token, std::move(handler)); - return CreateRevoker(token); - } - - // Handler return true to short circuit following handlers. - EventRevoker PrependShortCircuitHandler( - ShortCircuitHandler handler) override { - const auto token = current_token_++; - this->handler_data_list_.emplace(this->handler_data_list_.cbegin(), token, - std::move(handler)); - return CreateRevoker(token); - } - - // This method will make a copy of all handlers. Because user might delete a - // handler in a handler, which may lead to seg fault as the handler is - // deleted while being executed. Thanks to this behavior, all handlers will - // be taken a snapshot when Raise is called, so even if you delete a handler - // during this period, all handlers in the snapshot will be executed. - void Raise(EventArgs args) { - std::vector<ShortCircuitHandler> handlers; - handlers.reserve(this->handler_data_list_.size()); - for (const auto& data : this->handler_data_list_) { - handlers.push_back(data.handler); - } - for (const auto& handler : handlers) { - auto short_circuit = handler(args); - if (short_circuit) return; - } - } - - protected: - void RemoveHandler(EventHandlerToken token) override { - const auto find_result = std::find_if( - this->handler_data_list_.cbegin(), this->handler_data_list_.cend(), - [token](const HandlerData& data) { return data.token == token; }); - if (find_result != this->handler_data_list_.cend()) { - this->handler_data_list_.erase(find_result); - } - } - - private: - std::vector<HandlerData> handler_data_list_; - EventHandlerToken current_token_ = 0; -}; - -namespace details { -struct EventRevokerDestroyer { - void operator()(EventRevoker* p) { - (*p)(); - delete p; - } -}; -} // namespace details - -// A guard class for event revoker. Automatically revoke it when destroyed. -class EventRevokerGuard { - public: - EventRevokerGuard() = default; - explicit EventRevokerGuard(EventRevoker&& revoker) - : revoker_(new EventRevoker(std::move(revoker))) {} - EventRevokerGuard(const EventRevokerGuard& other) = delete; - EventRevokerGuard(EventRevokerGuard&& other) = default; - EventRevokerGuard& operator=(const EventRevokerGuard& other) = delete; - EventRevokerGuard& operator=(EventRevokerGuard&& other) = default; - ~EventRevokerGuard() = default; - - EventRevoker Get() { - // revoker is only null when this is moved - // you shouldn't use a moved instance - assert(revoker_); - return *revoker_; - } - - EventRevoker Release() { return std::move(*revoker_.release()); } - - void Reset() { revoker_.reset(); } - - void Reset(EventRevoker&& revoker) { - revoker_.reset(new EventRevoker(std::move(revoker))); - } - - private: - std::unique_ptr<EventRevoker, details::EventRevokerDestroyer> revoker_; -}; - -class EventRevokerListGuard { - public: - EventRevokerListGuard() = default; - EventRevokerListGuard(const EventRevokerListGuard& other) = delete; - EventRevokerListGuard(EventRevokerListGuard&& other) = default; - EventRevokerListGuard& operator=(const EventRevokerListGuard& other) = delete; - EventRevokerListGuard& operator=(EventRevokerListGuard&& other) = default; - ~EventRevokerListGuard() = default; - - public: - void Add(EventRevoker&& revoker) { - event_revoker_guard_list_.push_back(EventRevokerGuard(std::move(revoker))); - } - - EventRevokerListGuard& operator+=(EventRevoker&& revoker) { - this->Add(std::move(revoker)); - return *this; - } - - void Clear() { event_revoker_guard_list_.clear(); } - - bool IsEmpty() const { return event_revoker_guard_list_.empty(); } - - private: - std::vector<EventRevokerGuard> event_revoker_guard_list_; -}; -} // namespace cru diff --git a/include/cru/common/Event2.h b/include/cru/common/Event2.h deleted file mode 100644 index 62fb366d..00000000 --- a/include/cru/common/Event2.h +++ /dev/null @@ -1,200 +0,0 @@ -#pragma once - -#include <cru/common/Bitmask.h> -#include <cru/common/SelfResolvable.h> - -#include <cstddef> -#include <functional> -#include <type_traits> -#include <utility> -#include <vector> - -namespace cru { -class Event2Base { - public: - virtual ~Event2Base() = default; - - virtual void RevokeHandler(int token_value) = 0; -}; - -template <typename TArgument, typename TResult> -class EventContext { - public: - EventContext() : argument_(), result_() {} - explicit EventContext(TArgument argument) - : argument_(std::move(argument)), result_() {} - EventContext(TArgument argument, TResult result) - : argument_(std::move(argument)), result_(std::move(result)) {} - - TArgument& GetArgument() { return argument_; } - const TArgument& GetArgument() const { return argument_; } - - TResult& GetResult() { return result_; } - const TResult& GetResult() const { return result_; } - void SetResult(const TResult& result) { result_ = result; } - void SetResult(TResult&& result) { result_ = std::move(result); } - TResult TakeResult() { return std::move(result_); } - - bool GetStopHandling() const { return stop_handling_; } - void SetStopHandling(bool stop = true) { stop_handling_ = stop; } - - private: - TArgument argument_; - TResult result_; - bool stop_handling_ = false; -}; - -template <typename TArgument, typename TResult> -class Event2; - -template <typename T> -constexpr bool is_event2_v = false; - -template <typename TArgument, typename TResult> -constexpr bool is_event2_v<Event2<TArgument, TResult>> = true; - -class EventHandlerToken { - public: - EventHandlerToken(ObjectResolver<Event2Base> event_resolver, int token_value) - : event_resolver_(std::move(event_resolver)), token_value_(token_value) {} - - ObjectResolver<Event2Base> GetEventResolver() const { - return event_resolver_; - } - int GetTokenValue() const { return token_value_; } - inline void RevokeHandler() const; - - private: - ObjectResolver<Event2Base> event_resolver_; - int token_value_; -}; - -namespace details { -struct Event2BehaviorFlagTag {}; -} // namespace details -using Event2BehaviorFlag = Bitmask<details::Event2BehaviorFlagTag>; - -struct Event2BehaviorFlags { - /** - * @brief Make a copy of handler list before invoking handlers. So the event - * object or its owner can be destroyed during running handlers. - */ - static constexpr Event2BehaviorFlag CopyHandlers = - Event2BehaviorFlag::FromOffset(1); -}; - -template <typename TArgument = std::nullptr_t, - typename TResult = std::nullptr_t> -class Event2 : public Event2Base, - public SelfResolvable<Event2<TArgument, TResult>> { - public: - using HandlerToken = EventHandlerToken; - using Context = EventContext<TArgument, TResult>; - using Handler = std::function<void(Context*)>; - using SpyOnlyHandler = std::function<void()>; - - template <typename TFunc> - static std::enable_if_t<std::invocable<TFunc>, Handler> WrapAsHandler( - TFunc&& handler) { - return Handler([h = std::forward<TFunc>(handler)](Context*) { h(); }); - } - - template <typename TFunc> - static std::enable_if_t<std::invocable<TFunc, Context*>, Handler> - WrapAsHandler(TFunc&& handler) { - return Handler(std::forward<TFunc>(handler)); - } - - private: - struct HandlerData { - int token_value; - Handler handler; - }; - - public: - explicit Event2(Event2BehaviorFlag flags = {}) : flags_(flags) {} - Event2(const Event2&) = delete; - Event2(Event2&&) = delete; - Event2& operator=(const Event2&) = delete; - Event2& operator=(Event2&&) = delete; - ~Event2() override = default; - - public: - template <typename TFunc> - HandlerToken AddHandler(TFunc&& handler) { - auto token = this->current_token_value_++; - auto real_handler = WrapAsHandler(std::forward<TFunc>(handler)); - HandlerData handler_data{token, std::move(real_handler)}; - this->handlers_.push_back(std::move(handler_data)); - return HandlerToken(this->CreateResolver(), token); - } - - void RevokeHandler(int token_value) override { - auto iter = this->handlers_.cbegin(); - auto end = this->handlers_.cend(); - for (; iter != end; ++iter) { - if (iter->token_value == token_value) { - this->handlers_.erase(iter); - break; - } - } - } - - void RevokeHandler(const HandlerToken& token) { - return RevokeHandler(token.GetTokenValue()); - } - - TResult Raise() { - Context context; - RunInContext(&context); - return context.TakeResult(); - } - - TResult Raise(TArgument argument) { - Context context(std::move(argument)); - RunInContext(&context); - return context.TakeResult(); - } - - TResult Raise(TArgument argument, TResult result) { - Context context(std::move(argument), std::move(result)); - RunInContext(&context); - return context.TakeResult(); - } - - private: - void RunInContext(Context* context) { - if (this->flags_ & Event2BehaviorFlags::CopyHandlers) { - std::vector<Handler> handlers_copy; - for (const auto& handler : this->handlers_) { - handlers_copy.push_back(handler.handler); - } - for (const auto& handler : handlers_copy) { - if (context->GetStopHandling()) { - break; - } - handler(context); - } - } else { - for (const auto& handler : this->handlers_) { - if (context->GetStopHandling()) { - break; - } - handler.handler(context); - } - } - } - - private: - int current_token_value_ = 1; - std::vector<HandlerData> handlers_; - Event2BehaviorFlag flags_; -}; - -inline void EventHandlerToken::RevokeHandler() const { - auto event = this->event_resolver_.Resolve(); - if (event) { - event->RevokeHandler(this->token_value_); - } -} -} // namespace cru diff --git a/include/cru/common/Exception.h b/include/cru/common/Exception.h deleted file mode 100644 index 609fd2c9..00000000 --- a/include/cru/common/Exception.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once -#include "String.h" - -#include <exception> -#include <optional> - -namespace cru { -#ifdef _MSC_VER -#pragma warning(disable : 4275) -#endif -class CRU_BASE_API Exception : public std::exception { - public: - explicit Exception(String message = {}, - std::unique_ptr<std::exception> inner = nullptr); - - ~Exception() override; - - public: - String GetMessage() const { return message_; } - - std::exception* GetInner() const noexcept { return inner_.get(); } - - const char* what() const noexcept override; - - protected: - void SetMessage(String message) { message_ = std::move(message); } - - void AppendMessage(StringView additional_message); - void AppendMessage(std::optional<StringView> additional_message); - - private: - String message_; - mutable std::string utf8_message_; - std::unique_ptr<std::exception> inner_; -}; - -class CRU_BASE_API TextEncodeException : public Exception { - public: - using Exception::Exception; -}; - -class ErrnoException : public Exception { - public: - /** - * @brief will retrieve errno automatically. - */ - explicit ErrnoException(String message = {}); - ErrnoException(String message, int errno_code); - - CRU_DELETE_COPY(ErrnoException) - CRU_DELETE_MOVE(ErrnoException) - - ~ErrnoException() override = default; - - int GetErrnoCode() const { return errno_code_; } - - private: - int errno_code_; -}; -} // namespace cru diff --git a/include/cru/common/Format.h b/include/cru/common/Format.h deleted file mode 100644 index d5c5ed99..00000000 --- a/include/cru/common/Format.h +++ /dev/null @@ -1,154 +0,0 @@ -#pragma once - -#include "Exception.h" -#include "String.h" - -#include <cassert> -#include <cstdio> -#include <type_traits> -#include <vector> - -namespace cru { -inline String ToString(bool value) { - return value ? String(u"true") : String(u"false"); -} - -template <typename T> -inline constexpr std::nullptr_t kPrintfFormatSpecifierOfType = nullptr; - -#define CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(type, specifier) \ - template <> \ - inline constexpr const char* kPrintfFormatSpecifierOfType<type> = specifier; - -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(signed char, "%c") -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(unsigned char, "%c") -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(signed short, "%hd") -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(unsigned short, "%hu") -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(signed int, "%d") -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(unsigned int, "%u") -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(signed long, "%ld") -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(unsigned long, "%lu") -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(signed long long, "%lld") -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(unsigned long long, "%llu") -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(float, "%f") -CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE(double, "%f") - -#undef CRU_DEFINE_PRINTF_FORMAT_SPECIFIER_OF_TYPE - -template <typename T> -std::enable_if_t< - !std::is_null_pointer_v<decltype(kPrintfFormatSpecifierOfType<T>)>, String> -ToString(T value) { - auto size = std::snprintf(nullptr, 0, kPrintfFormatSpecifierOfType<T>, value); - assert(size > 0); - std::vector<char> buffer(size + 1); - size = std::snprintf(buffer.data(), size + 1, kPrintfFormatSpecifierOfType<T>, - value); - assert(size > 0); - return String::FromUtf8(buffer.data(), size); -} - -template <typename T> -String ToString(const T& value, StringView option) { - CRU_UNUSED(option) - return ToString(value); -} - -inline String ToString(String value) { return value; } - -namespace details { -enum class FormatTokenType { PlaceHolder, Text }; -enum class FormatPlaceHolderType { None, Positioned, Named }; - -struct FormatToken { - static FormatToken Text() { - return FormatToken{FormatTokenType::Text, {}, {}, 0, {}, {}}; - } - - static FormatToken NonePlaceHolder(String option) { - return FormatToken(FormatTokenType::PlaceHolder, {}, - FormatPlaceHolderType::None, 0, {}, std::move(option)); - } - - static FormatToken PositionedPlaceHolder(int position, String option) { - return FormatToken(FormatTokenType::PlaceHolder, {}, - FormatPlaceHolderType::Positioned, position, {}, - std::move(option)); - } - - static FormatToken NamedPlaceHolder(String name, String option) { - return FormatToken(FormatTokenType::PlaceHolder, {}, - FormatPlaceHolderType::Named, 0, std::move(name), - std::move(option)); - } - - FormatToken(FormatTokenType type, String data, - FormatPlaceHolderType place_holder_type, - int place_holder_position, String place_holder_name, - String place_holder_option) - : type(type), - data(std::move(data)), - place_holder_type(place_holder_type), - place_holder_position(place_holder_position), - place_holder_name(std::move(place_holder_name)), - place_holder_option(std::move(place_holder_option)) {} - - CRU_DEFAULT_COPY(FormatToken) - CRU_DEFAULT_MOVE(FormatToken) - - CRU_DEFAULT_DESTRUCTOR(FormatToken) - - FormatTokenType type; - String data; - FormatPlaceHolderType place_holder_type; - int place_holder_position; - String place_holder_name; - String place_holder_option; -}; - -std::vector<FormatToken> CRU_BASE_API ParseToFormatTokenList(StringView str); - -void CRU_BASE_API FormatAppendFromFormatTokenList( - String& current, const std::vector<FormatToken>& format_token_list, - Index index); - -template <typename TA, typename... T> -void FormatAppendFromFormatTokenList( - String& current, const std::vector<FormatToken>& format_token_list, - Index index, TA&& args0, T&&... args) { - for (Index i = index; i < static_cast<Index>(format_token_list.size()); i++) { - const auto& token = format_token_list[i]; - if (token.type == FormatTokenType::PlaceHolder) { - if (token.place_holder_type == FormatPlaceHolderType::None) { - current += ToString(std::forward<TA>(args0), token.place_holder_option); - FormatAppendFromFormatTokenList(current, format_token_list, i + 1, - std::forward<T>(args)...); - - return; - } else { - throw Exception( - u"Currently do not support positional or named place holder."); - } - } else { - current += token.data; - } - } -} -} // namespace details - -template <typename... T> -String Format(StringView format, T&&... args) { - String result; - - details::FormatAppendFromFormatTokenList( - result, details::ParseToFormatTokenList(format), 0, - std::forward<T>(args)...); - - return result; -} - -template <typename... T> -String String::Format(T&&... args) const { - return cru::Format(*this, std::forward<T>(args)...); -} -} // namespace cru diff --git a/include/cru/common/Guard.h b/include/cru/common/Guard.h deleted file mode 100644 index 5a9f9c5d..00000000 --- a/include/cru/common/Guard.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include <functional> - -namespace cru { -struct Guard { - using ExitFunc = std::function<void()>; - - Guard() = default; - explicit Guard(const ExitFunc& f) : on_exit(f) {} - explicit Guard(ExitFunc&& f) : on_exit(std::move(f)) {} - Guard(const Guard&) = delete; - Guard(Guard&&) = default; - Guard& operator=(const Guard&) = delete; - Guard& operator=(Guard&&) = default; - ~Guard() { - if (on_exit) { - on_exit(); - } - } - - void Drop() { on_exit = {}; } - - ExitFunc on_exit; -}; -} // namespace cru diff --git a/include/cru/common/HandlerRegistry.h b/include/cru/common/HandlerRegistry.h deleted file mode 100644 index e405d1fd..00000000 --- a/include/cru/common/HandlerRegistry.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once -#include "Base.h" - -#include <algorithm> -#include <functional> -#include <utility> -#include <vector> - -namespace cru { - -template <typename T> -class HandlerRegistryIterator { - public: - using RawIterator = - typename std::vector<std::pair<int, std::function<T>>>::const_iterator; - - explicit HandlerRegistryIterator(RawIterator raw) : raw_(std::move(raw)) {} - - CRU_DELETE_COPY(HandlerRegistryIterator) - CRU_DELETE_MOVE(HandlerRegistryIterator) - - ~HandlerRegistryIterator() = default; - - const std::function<T>& operator*() const { return raw_->second; } - const std::function<T>* operator->() const { return &raw_->second; } - - HandlerRegistryIterator& operator++() { - ++raw_; - return *this; - } - - HandlerRegistryIterator operator++(int) { - auto c = *this; - this->operator++(); - return c; - } - - bool operator==(const HandlerRegistryIterator<T>& other) const { - return this->raw_ == other.raw_; - } - - bool operator!=(const HandlerRegistryIterator<T>& other) const { - return !this->operator==(other); - } - - private: - RawIterator raw_; -}; - -template <typename T> -class HandlerRegistry final { - public: - HandlerRegistry() = default; - CRU_DEFAULT_COPY(HandlerRegistry) - CRU_DEFAULT_MOVE(HandlerRegistry) - ~HandlerRegistry() = default; - - public: - int AddHandler(std::function<T> handler) { - auto id = current_id_++; - handler_list_.push_back({id, std::move(handler)}); - return id; - } - - void RemoveHandler(int id) { - auto result = std::find_if(handler_list_.cbegin(), handler_list_.cend(), - [id](const std::pair<int, std::function<T>>& d) { - return d.first == id; - }); - if (result != handler_list_.cend()) { - handler_list_.erase(result); - } - } - - HandlerRegistryIterator<T> begin() const { - return HandlerRegistryIterator<T>(handler_list_.begin()); - } - - HandlerRegistryIterator<T> end() const { - return HandlerRegistryIterator<T>(handler_list_.end()); - } - - private: - int current_id_ = 1; - std::vector<std::pair<int, std::function<T>>> handler_list_; -}; -} // namespace cru diff --git a/include/cru/common/PreConfig.h b/include/cru/common/PreConfig.h deleted file mode 100644 index 3f26c589..00000000 --- a/include/cru/common/PreConfig.h +++ /dev/null @@ -1,18 +0,0 @@ -// IWYU pragma: always_keep - -#pragma once - -#ifdef _MSC_VER -// disable the unnecessary warning about multi-inheritance -#pragma warning(disable : 4250) -// disable dll export template issue warning -#pragma warning(disable : 4251) -#endif - -#ifdef CRU_PLATFORM_WINDOWS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#if defined(CRU_PLATFORM_OSX) || defined(CRU_PLATFORM_LINUX) -#define CRU_PLATFORM_UNIX -#endif diff --git a/include/cru/common/PropertyTree.h b/include/cru/common/PropertyTree.h deleted file mode 100644 index 54e185b9..00000000 --- a/include/cru/common/PropertyTree.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include "Base.h" -#include "String.h" - -#include <unordered_map> - -namespace cru { -class PropertyTree; - -class CRU_BASE_API PropertySubTreeRef { - public: - static String CombineKey(StringView left, StringView right); - - explicit PropertySubTreeRef(PropertyTree* tree, String path = {}); - - CRU_DEFAULT_COPY(PropertySubTreeRef); - CRU_DEFAULT_MOVE(PropertySubTreeRef); - - CRU_DEFAULT_DESTRUCTOR(PropertySubTreeRef); - - public: - PropertyTree* GetTree() const { return tree_; } - - String GetPath() const { return path_; } - void SetPath(String path) { path_ = std::move(path); } - - PropertySubTreeRef GetParent() const; - PropertySubTreeRef GetChild(const String& key) const; - - String GetValue(const String& key) const; - void SetValue(const String& key, String value); - void DeleteValue(const String& key); - - private: - PropertyTree* tree_; - String path_; -}; - -class CRU_BASE_API PropertyTree { - public: - static String CombineKey(StringView left, StringView right); - - PropertyTree() = default; - explicit PropertyTree(std::unordered_map<String, String> values); - - CRU_DELETE_COPY(PropertyTree); - CRU_DELETE_MOVE(PropertyTree); - - CRU_DEFAULT_DESTRUCTOR(PropertyTree); - - public: - String GetValue(const String& key) const; - void SetValue(const String& key, String value); - void DeleteValue(const String& key); - - PropertySubTreeRef GetSubTreeRef(const String& path); - - private: - std::unordered_map<String, String> values_; -}; - -} // namespace cru diff --git a/include/cru/common/Range.h b/include/cru/common/Range.h deleted file mode 100644 index edc2ec55..00000000 --- a/include/cru/common/Range.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include "Base.h" - -namespace cru { -struct Range final { - constexpr static Range FromTwoSides(Index start, Index end) { - return Range(start, end - start); - } - - constexpr static Range FromTwoSides(Index start, Index end, Index offset) { - return Range(start + offset, end - start); - } - - constexpr Range() = default; - constexpr Range(const Index position, const Index count = 0) - : position(position), count(count) {} - - Index GetStart() const { return position; } - Index GetEnd() const { return position + count; } - - void ChangeEnd(Index new_end) { count = new_end - position; } - - Range Normalize() const { - auto result = *this; - if (result.count < 0) { - result.position += result.count; - result.count = -result.count; - } - return result; - } - - Range CoerceInto(Index min, Index max) const { - auto coerce = [min, max](Index index) { - return index > max ? max : (index < min ? min : index); - }; - return Range::FromTwoSides(coerce(GetStart()), coerce(GetEnd())); - } - - Index position = 0; - Index count = 0; -}; -} // namespace cru diff --git a/include/cru/common/SelfResolvable.h b/include/cru/common/SelfResolvable.h deleted file mode 100644 index 84fa54f6..00000000 --- a/include/cru/common/SelfResolvable.h +++ /dev/null @@ -1,153 +0,0 @@ -#pragma once - -#include <cassert> -#include <functional> -#include <memory> -#include <type_traits> - -namespace cru { -template <typename T> -class SelfResolvable; - -template <typename T> -class ObjectResolver { - friend SelfResolvable<T>; - template <typename U> - friend class ObjectResolver; - - private: - template <typename U> - using Accessor_ = std::function<U*(const std::shared_ptr<void*>&)>; - using ThisAccessor_ = Accessor_<T>; - - explicit ObjectResolver(T* o) - : shared_object_ptr_(new void*(o)), - accessor_([](const std::shared_ptr<void*>& ptr) { - return static_cast<T*>(*ptr); - }) {} - explicit ObjectResolver(std::shared_ptr<void*> ptr, ThisAccessor_ accessor) - : shared_object_ptr_(std::move(ptr)), accessor_(std::move(accessor)) {} - - template <typename U> - static ThisAccessor_ CreateAccessor(Accessor_<U> parent_accessor) { - return [parent_accessor = - std::move(parent_accessor)](const std::shared_ptr<void*>& ptr) { - return static_cast<T*>(parent_accessor(ptr)); - }; - } - - public: - template <typename U, - typename = std::enable_if_t<std::is_convertible_v<U*, T*>>> - ObjectResolver(const ObjectResolver<U>& other) - : shared_object_ptr_(other.shared_object_ptr_), - accessor_(CreateAccessor(other.accessor_)) {} - - template <typename U, - typename = std::enable_if_t<std::is_convertible_v<U*, T*>>> - ObjectResolver(ObjectResolver<U>&& other) - : shared_object_ptr_(std::move(other.shared_object_ptr_)), - accessor_(CreateAccessor(std::move(other.accessor_))) {} - - ObjectResolver(const ObjectResolver&) = default; - ObjectResolver& operator=(const ObjectResolver&) = default; - ObjectResolver(ObjectResolver&&) = default; - ObjectResolver& operator=(ObjectResolver&&) = default; - ~ObjectResolver() = default; - - template <typename U, - typename = std::enable_if_t<std::is_convertible_v<U*, T*>>> - ObjectResolver& operator=(const ObjectResolver<U>& other) { - if (this != &other) { - this->shared_object_ptr_ = other.shared_object_ptr_; - this->accessor_ = CreateAccessor(other.accessor_); - } - return *this; - } - - template <typename U, - typename = std::enable_if_t<std::is_convertible_v<U*, T*>>> - ObjectResolver& operator=(ObjectResolver<U>&& other) { - if (this != &other) { - this->shared_object_ptr_ = std::move(other.shared_object_ptr_); - this->accessor_ = CreateAccessor(std::move(other.shared_object_ptr_)); - } - return *this; - } - - bool IsValid() const { return this->shared_object_ptr_ != nullptr; } - - T* Resolve() const { - assert(IsValid()); - return this->accessor_(this->shared_object_ptr_); - } - - /** - * @remarks So this class can be used as a functor. - */ - T* operator()() const { return Resolve(); } - - template <typename U, - typename = std::enable_if_t<std::is_convertible_v<T*, U*>>> - operator ObjectResolver<U>() const { - return ObjectResolver<U>(*this); - } - - private: - void SetResolvedObject(T* o) { - assert(IsValid()); - *this->shared_object_ptr_ = o; - } - - private: - std::shared_ptr<void*> shared_object_ptr_; - std::function<T*(const std::shared_ptr<void*>&)> accessor_; -}; - -/** - * @remarks - * This class is not copyable and movable since subclass is polymorphic and - * copying is then nonsense. However, you can even delete move capability in - * subclass because it may also be nonsense for subclass. The move capability is - * optional. - * - * Whether this class needs to be thread-safe still has to be considered. - */ -template <typename T> -class SelfResolvable { - public: - SelfResolvable() : resolver_(CastToSubClass()) {} - SelfResolvable(const SelfResolvable&) = delete; - SelfResolvable& operator=(const SelfResolvable&) = delete; - - // Resolvers to old object will resolve to new object. - SelfResolvable(SelfResolvable&& other) - : resolver_(std::move(other.resolver_)) { - this->resolver_.SetResolvedObject(CastToSubClass()); - } - - // Old resolvers for this object will resolve to nullptr. - // Other's resolvers will now resolve to this. - SelfResolvable& operator=(SelfResolvable&& other) { - if (this != &other) { - this->resolver_ = std::move(other.resolver_); - this->resolver_.SetResolvedObject(CastToSubClass()); - } - return *this; - } - - virtual ~SelfResolvable() { - if (this->resolver_.IsValid()) { - this->resolver_.SetResolvedObject(nullptr); - } - } - - ObjectResolver<T> CreateResolver() { return resolver_; } - - private: - T* CastToSubClass() { return static_cast<T*>(this); } - - private: - ObjectResolver<T> resolver_; -}; -} // namespace cru diff --git a/include/cru/common/String.h b/include/cru/common/String.h deleted file mode 100644 index 21a3db51..00000000 --- a/include/cru/common/String.h +++ /dev/null @@ -1,492 +0,0 @@ -#pragma once -#include "Base.h" - -#include "Buffer.h" -#include "Range.h" -#include "StringToNumberConverter.h" -#include "StringUtil.h" - -#include <filesystem> -#include <initializer_list> -#include <iterator> -#include <string> -#include <string_view> -#include <type_traits> -#include <vector> - -namespace cru { -class StringView; - -class CRU_BASE_API String { - public: - using value_type = char16_t; - using size_type = Index; - using difference_type = Index; - using reference = value_type&; - using const_reference = const value_type&; - using pointer = value_type*; - using const_pointer = const value_type*; - using iterator = value_type*; - using const_iterator = const value_type*; - using reverse_iterator = std::reverse_iterator<iterator>; - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - - public: - static String FromUtf8(const char* str); - static String FromUtf8(const char* str, Index size); - static String FromUtf8(const std::byte* str, Index size); - static String FromUtf8(std::string_view str) { - return FromUtf8(str.data(), str.size()); - } - static String FromUtf8(const Buffer& buffer); - - static String FromUtf16(const char16_t* str) { return String(str); } - static String FromUtf16(const char16_t* str, Index size) { - return String(str, size); - } - static String FromUtf16(std::u16string_view str) { - return FromUtf16(str.data(), str.size()); - } - - static inline String From(StringView str); - - // Never use this if you don't know what this mean! - static String FromBuffer(pointer buffer, Index size, Index capacity) { - return String{from_buffer_tag{}, buffer, size, capacity}; - } - - static String FromStdPath(const std::filesystem::path& path); - -#ifdef CRU_PLATFORM_WINDOWS - static String FromUtf16(wchar_t* str) { return String(str); } - static String FromUtf16(wchar_t* str, Index size) { - return String(str, size); - } -#endif - - public: - String() = default; - - String(const_pointer str); - String(const_pointer str, size_type size); - - template <Index size> - String(const char16_t (&str)[size]) - : String(reinterpret_cast<const_pointer>(str), size - 1) {} - - template <typename Iter> - String(Iter start, Iter end) { - for (; start != end; start++) { - append(*start); - } - } - - String(size_type size, value_type ch = 0); - - String(std::initializer_list<value_type> l); - - explicit String(StringView str); - -#ifdef CRU_PLATFORM_WINDOWS - String(const wchar_t* str); - String(const wchar_t* str, Index size); - String(const std::wstring& str) : String(str.data(), str.size()) {} -#endif - - String(const String& other); - String(String&& other) noexcept; - - String& operator=(const String& other); - String& operator=(String&& other) noexcept; - - ~String(); - - private: - struct from_buffer_tag {}; - String(from_buffer_tag, pointer buffer, Index size, Index capacity); - - public: - bool empty() const { return this->size_ == 0; } - Index size() const { return this->size_; } - Index length() const { return this->size(); } - Index capacity() const { return this->capacity_; } - pointer data() { return this->buffer_; } - const_pointer data() const { return this->buffer_; } - - void resize(Index new_size); - void reserve(Index new_capacity); - void shrink_to_fit(); - - reference front() { return this->operator[](0); } - const_reference front() const { return this->operator[](0); } - - reference back() { return this->operator[](size_ - 1); } - const_reference back() const { return this->operator[](size_ - 1); } - - const_pointer c_str() const { return buffer_; } - - reference operator[](Index index) { return buffer_[index]; } - const_reference operator[](Index index) const { return buffer_[index]; } - - public: - iterator begin() { return this->buffer_; } - const_iterator begin() const { return this->buffer_; } - const_iterator cbegin() const { return this->buffer_; } - - iterator end() { return this->buffer_ + this->size_; } - const_iterator end() const { return this->buffer_ + this->size_; } - const_iterator cend() const { return this->buffer_ + this->size_; } - - reverse_iterator rbegin() { return reverse_iterator{end()}; } - const_reverse_iterator rbegin() const { - return const_reverse_iterator{end()}; - } - const_reverse_iterator crbegin() const { - return const_reverse_iterator{cend()}; - } - - reverse_iterator rend() { return reverse_iterator{begin()}; } - const_reverse_iterator rend() const { - return const_reverse_iterator{begin()}; - } - const_reverse_iterator crend() const { - return const_reverse_iterator{cbegin()}; - } - - public: - void clear(); - iterator insert(const_iterator pos, value_type value) { - return this->insert(pos, &value, 1); - } - iterator insert(const_iterator pos, const_iterator str, Index size); - iterator insert(const_iterator pos, StringView str); - iterator erase(const_iterator pos) { return this->erase(pos, pos + 1); } - iterator erase(const_iterator start, const_iterator end); - void push_back(value_type value) { this->append(value); } - void pop_back() { this->erase(cend() - 1); } - void append(value_type value) { this->insert(cend(), value); } - void append(const_iterator str, Index size) { - this->insert(cend(), str, size); - } - inline void append(StringView str); - - String substr(size_type start, size_type size = -1) const { - if (size == -1) { - size = this->size_ - start; - } - return String(this->buffer_ + start, size); - } - - String& operator+=(value_type value) { - this->append(value); - return *this; - } - String& operator+=(StringView other); - - public: - operator std::u16string_view() const { - return std::u16string_view(data(), size()); - } - - StringView View() const; - - public: - Index Find(value_type value, Index start = 0) const; - std::vector<String> Split(value_type separator, - bool remove_space_line = false) const; - std::vector<String> SplitToLines(bool remove_space_line = false) const; - - bool StartWith(StringView str) const; - bool EndWith(StringView str) const; - - String& TrimStart(); - String& TrimEnd(); - String& Trim(); - - public: - void AppendCodePoint(CodePoint code_point); - - Utf16CodePointIterator CodePointIterator() const { - return Utf16CodePointIterator(buffer_, size_); - } - - Index IndexFromCodeUnitToCodePoint(Index code_unit_index) const; - Index IndexFromCodePointToCodeUnit(Index code_point_index) const; - Range RangeFromCodeUnitToCodePoint(Range code_unit_range) const; - Range RangeFromCodePointToCodeUnit(Range code_point_range) const; - - template <typename TInteger> - std::enable_if_t<std::is_signed_v<TInteger>, TInteger> ParseToInteger( - Index* processed_characters_count, unsigned flags, int base) const; - - int ParseToInt(Index* processed_characters_count = nullptr, - StringToNumberFlag flags = {}, int base = 0) const; - long long ParseToLongLong(Index* processed_characters_count = nullptr, - StringToNumberFlag flags = {}, int base = 0) const; - - float ParseToFloat(Index* processed_characters_count = nullptr, - StringToNumberFlag flags = {}) const; - double ParseToDouble(Index* processed_characters_count = nullptr, - StringToNumberFlag flags = {}) const; - std::vector<float> ParseToFloatList(value_type separator = u' ') const; - std::vector<double> ParseToDoubleList(value_type separator = u' ') const; - -#ifdef CRU_PLATFORM_WINDOWS - const wchar_t* WinCStr() const { - return reinterpret_cast<const wchar_t*>(c_str()); - } -#endif - - template <typename... T> - String Format(T&&... args) const; - - std::string ToUtf8() const; - Buffer ToUtf8Buffer(bool end_zero = true) const; - - int Compare(const String& other) const; - int CaseInsensitiveCompare(const String& other) const; - bool CaseInsensitiveEqual(const String& other) const { - return CaseInsensitiveCompare(other) == 0; - } - - private: - static char16_t kEmptyBuffer[1]; - - private: - char16_t* buffer_ = kEmptyBuffer; - Index size_ = 0; // not including trailing '\0' - Index capacity_ = 0; // always 1 smaller than real buffer size -}; - -std::ostream& CRU_BASE_API operator<<(std::ostream& os, const String& value); - -class CRU_BASE_API StringView { - public: - using value_type = char16_t; - using size_type = Index; - using difference_type = Index; - using reference = value_type&; - using const_reference = const value_type&; - using pointer = value_type*; - using const_pointer = const value_type*; - using iterator = const value_type*; - using const_iterator = const value_type*; - using reverse_iterator = std::reverse_iterator<iterator>; - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - - StringView() = default; - - constexpr StringView(const_pointer ptr, Index size) - : ptr_(ptr), size_(size) {} - - template <Index size> - constexpr StringView(const value_type (&array)[size]) - : StringView(array, size - 1) {} - - StringView(const String& str) : StringView(str.data(), str.size()) {} - - CRU_DEFAULT_COPY(StringView) - CRU_DEFAULT_MOVE(StringView) - - ~StringView() = default; - - bool empty() const { return size_ == 0; } - Index size() const { return size_; } - const value_type* data() const { return ptr_; } - - public: - iterator begin() { return this->ptr_; } - const_iterator begin() const { return this->ptr_; } - const_iterator cbegin() const { return this->ptr_; } - - iterator end() { return this->ptr_ + this->size_; } - const_iterator end() const { return this->ptr_ + this->size_; } - const_iterator cend() const { return this->ptr_ + this->size_; } - - reverse_iterator rbegin() { return reverse_iterator{end()}; } - const_reverse_iterator rbegin() const { - return const_reverse_iterator{end()}; - } - const_reverse_iterator crbegin() const { - return const_reverse_iterator{cend()}; - } - - reverse_iterator rend() { return reverse_iterator{begin()}; } - const_reverse_iterator rend() const { - return const_reverse_iterator{begin()}; - } - const_reverse_iterator crend() const { - return const_reverse_iterator{cbegin()}; - } - - StringView substr(Index pos); - StringView substr(Index pos, Index size); - - value_type operator[](Index index) const { return ptr_[index]; } - - operator std::u16string_view() const { - return std::u16string_view(data(), size()); - } - - public: - int Compare(const StringView& other) const; - int CaseInsensitiveCompare(const StringView& other) const; - bool CaseInsensitiveEqual(const StringView& other) const { - return CaseInsensitiveCompare(other) == 0; - } - - String ToString() const { return String(ptr_, size_); } - - Utf16CodePointIterator CodePointIterator() const { - return Utf16CodePointIterator(ptr_, size_); - } - - Index Find(value_type value, Index start = 0) const; - std::vector<String> Split(value_type separator, - bool remove_space_line = false) const; - std::vector<String> SplitToLines(bool remove_space_line = false) const; - - bool StartWith(StringView str) const; - bool EndWith(StringView str) const; - - Index IndexFromCodeUnitToCodePoint(Index code_unit_index) const; - Index IndexFromCodePointToCodeUnit(Index code_point_index) const; - Range RangeFromCodeUnitToCodePoint(Range code_unit_range) const; - Range RangeFromCodePointToCodeUnit(Range code_point_range) const; - - template <typename TInteger> - std::enable_if_t<std::is_signed_v<TInteger>, TInteger> ParseToInteger( - Index* processed_characters_count, StringToNumberFlag flags, - int base) const { - auto utf8_string = ToUtf8(); - auto result = StringToIntegerConverter(flags, base) - .Parse(utf8_string.data(), utf8_string.size(), - processed_characters_count); - return result.negate ? -result.value : result.value; - } - - int ParseToInt(Index* processed_characters_count = nullptr, - StringToNumberFlag flags = {}, int base = 0) const; - long long ParseToLongLong(Index* processed_characters_count = nullptr, - StringToNumberFlag flags = {}, int base = 0) const; - - float ParseToFloat(Index* processed_characters_count = nullptr, - StringToNumberFlag flags = {}) const; - double ParseToDouble(Index* processed_characters_count = nullptr, - StringToNumberFlag flags = {}) const; - std::vector<float> ParseToFloatList(value_type separator = u' ') const; - std::vector<double> ParseToDoubleList(value_type separator = u' ') const; - - std::string ToUtf8() const; - Buffer ToUtf8Buffer(bool end_zero = true) const; - - private: - const char16_t* ptr_; - Index size_; -}; - -CRU_DEFINE_COMPARE_OPERATORS(String) - -inline String operator+(const String& left, const String& right) { - String result; - result += left; - result += right; - return result; -} - -inline String operator+(String::value_type left, const String& right) { - String result; - result += left; - result += right; - return result; -} - -inline String operator+(const String& left, String::value_type right) { - String result; - result += left; - result += right; - return result; -} - -CRU_DEFINE_COMPARE_OPERATORS(StringView) - -inline String::iterator String::insert(const_iterator pos, StringView str) { - return insert(pos, str.data(), str.size()); -} - -inline void String::append(StringView str) { - this->append(str.data(), str.size()); -} - -inline String String::From(StringView str) { return str.ToString(); } - -inline String::String(StringView str) : String(str.data(), str.size()) {} - -inline String ToString(StringView value) { return value.ToString(); } - -inline CodePoint Utf16PreviousCodePoint(StringView str, Index current, - Index* previous_position) { - return Utf16PreviousCodePoint(str.data(), str.size(), current, - previous_position); -} - -inline CodePoint Utf16NextCodePoint(StringView str, Index current, - Index* next_position) { - return Utf16NextCodePoint(str.data(), str.size(), current, next_position); -} - -inline bool Utf16IsValidInsertPosition(StringView str, Index position) { - return Utf16IsValidInsertPosition(str.data(), str.size(), position); -} - -// Return position after the character making predicate returns true or 0 if no -// character doing so. -inline Index CRU_BASE_API -Utf16BackwardUntil(StringView str, Index position, - const std::function<bool(CodePoint)>& predicate) { - return Utf16BackwardUntil(str.data(), str.size(), position, predicate); -} -// Return position before the character making predicate returns true or -// str.size() if no character doing so. -inline Index CRU_BASE_API -Utf16ForwardUntil(StringView str, Index position, - const std::function<bool(CodePoint)>& predicate) { - return Utf16ForwardUntil(str.data(), str.size(), position, predicate); -} - -inline Index Utf16PreviousWord(StringView str, Index position, - bool* is_space = nullptr) { - return Utf16PreviousWord(str.data(), str.size(), position, is_space); -} - -inline Index Utf16NextWord(StringView str, Index position, - bool* is_space = nullptr) { - return Utf16NextWord(str.data(), str.size(), position, is_space); -} - -String CRU_BASE_API ToLower(StringView s); -String CRU_BASE_API ToUpper(StringView s); - -template <typename TInteger> -std::enable_if_t<std::is_signed_v<TInteger>, TInteger> String::ParseToInteger( - Index* processed_characters_count, unsigned flags, int base) const { - View().ParseToInteger<TInteger>(processed_characters_count, flags, base); -} - -} // namespace cru - -template <> -struct std::hash<cru::String> { - std::size_t operator()(const cru::String& value) const { - return std::hash<std::u16string_view>{}(std::u16string_view( - reinterpret_cast<const char16_t*>(value.data()), value.size())); - } -}; - -template <> -struct std::hash<cru::StringView> { - std::size_t operator()(const cru::StringView& value) const { - return std::hash<std::u16string_view>{}(std::u16string_view( - reinterpret_cast<const char16_t*>(value.data()), value.size())); - } -}; diff --git a/include/cru/common/StringToNumberConverter.h b/include/cru/common/StringToNumberConverter.h deleted file mode 100644 index 758b26c8..00000000 --- a/include/cru/common/StringToNumberConverter.h +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once -#include "Base.h" -#include "Bitmask.h" - -#include <cstddef> -#include <ostream> - -namespace cru { -namespace details { -struct StringToNumberFlagTag {}; -} // namespace details - -using StringToNumberFlag = Bitmask<details::StringToNumberFlagTag>; - -struct StringToNumberFlags { - constexpr static StringToNumberFlag kAllowLeadingSpaces = - StringToNumberFlag::FromOffset(0); - constexpr static StringToNumberFlag kAllowTrailingSpaces = - StringToNumberFlag::FromOffset(1); - constexpr static StringToNumberFlag kAllowTrailingJunk = - StringToNumberFlag::FromOffset(2); - constexpr static StringToNumberFlag kAllowLeadingZeroForInteger = - StringToNumberFlag::FromOffset(3); - constexpr static StringToNumberFlag kThrowOnError = - StringToNumberFlag::FromOffset(4); -}; - -template <typename TResult> -struct IStringToNumberConverter : virtual Interface { - virtual TResult Parse(const char* str, Index size, - Index* processed_characters_count) const = 0; - - template <std::size_t Size> - TResult Parse(const char (&str)[Size], - Index* processed_characters_count) const { - return Parse(str, Size - 1, processed_characters_count); - } -}; - -struct CRU_BASE_API StringToIntegerResult { - StringToIntegerResult() = default; - StringToIntegerResult(bool negate, unsigned long long value) - : negate(negate), value(value) {} - - bool negate; - unsigned long long value; -}; - -inline bool CRU_BASE_API operator==(const StringToIntegerResult& left, - const StringToIntegerResult& right) { - return left.negate == right.negate && left.value == right.value; -} - -inline bool CRU_BASE_API operator!=(const StringToIntegerResult& left, - const StringToIntegerResult& right) { - return !(left == right); -} - -inline std::ostream& CRU_BASE_API -operator<<(std::ostream& stream, const StringToIntegerResult& result) { - return stream << "StringToIntegerConverterImplResult(" - << (result.negate ? "-" : "") << result.value << ")"; -} - -/** - * \brief A converter that convert number into long long. - */ -struct CRU_BASE_API StringToIntegerConverter - : IStringToNumberConverter<StringToIntegerResult> { - public: - explicit StringToIntegerConverter(StringToNumberFlag flags, int base = 0) - : flags(flags), base(base) {} - - bool CheckParams() const; - - /** - * \brief Convert string to long long. - * \param str The string to convert. - * \param size The size of the string. - * \param processed_characters_count The number of characters that were - * processed. Or nullptr to not retrieve. - */ - StringToIntegerResult Parse(const char* str, Index size, - Index* processed_characters_count) const override; - using IStringToNumberConverter<StringToIntegerResult>::Parse; - - StringToNumberFlag flags; - /** - * \brief The base of the number used for parse or 0 for auto detect. - * \remarks Base can only be of range [2, 36] or 0. If base is 0, decimal is - * assumed by default ,or if str is started with "0x" or "0X" hexadecimal is - * assumed, or if str is started with a single "0" octoral is assumed, or if - * str is started with "0b" or "0B" binary is assumed. Otherwise it is an - * error. - */ - int base; -}; - -struct CRU_BASE_API StringToFloatConverter { - StringToFloatConverter(StringToNumberFlag flags) : flags(flags) {} - - double Parse(const char* str, Index size, - Index* processed_characters_count) const; - - StringToNumberFlag flags; -}; -} // namespace cru diff --git a/include/cru/common/StringUtil.h b/include/cru/common/StringUtil.h deleted file mode 100644 index 8f085283..00000000 --- a/include/cru/common/StringUtil.h +++ /dev/null @@ -1,226 +0,0 @@ -#pragma once -#include "Base.h" - -#include <functional> -#include <type_traits> - -namespace cru { -using CodePoint = std::int32_t; -constexpr CodePoint k_invalid_code_point = -1; - -inline bool IsUtf16SurrogatePairCodeUnit(char16_t c) { - return c >= 0xD800 && c <= 0xDFFF; -} - -inline bool IsUtf16SurrogatePairLeading(char16_t c) { - return c >= 0xD800 && c <= 0xDBFF; -} - -inline bool IsUtf16SurrogatePairTrailing(char16_t c) { - return c >= 0xDC00 && c <= 0xDFFF; -} - -CodePoint CRU_BASE_API Utf8NextCodePoint(const char* ptr, Index size, - Index current, Index* next_position); - -CodePoint CRU_BASE_API Utf16NextCodePoint(const char16_t* ptr, Index size, - Index current, Index* next_position); -CodePoint CRU_BASE_API Utf16PreviousCodePoint(const char16_t* ptr, Index size, - Index current, - Index* previous_position); - -template <typename CharType> -using NextCodePointFunctionType = CodePoint (*)(const CharType*, Index, Index, - Index*); - -template <typename CharType, - NextCodePointFunctionType<CharType> NextCodePointFunction> -class CodePointIterator { - public: - using difference_type = Index; - using value_type = CodePoint; - using pointer = void; - using reference = value_type; - using iterator_category = std::forward_iterator_tag; - - public: - struct past_end_tag_t {}; - - explicit CodePointIterator(const CharType* ptr, Index size, Index current = 0) - : ptr_(ptr), size_(size), position_(current) {} - explicit CodePointIterator(const CharType* ptr, Index size, past_end_tag_t) - : ptr_(ptr), size_(size), position_(size) {} - - CRU_DEFAULT_COPY(CodePointIterator) - CRU_DEFAULT_MOVE(CodePointIterator) - - ~CodePointIterator() = default; - - public: - const CharType* GetPtr() const { return ptr_; } - Index GetSize() const { return size_; } - Index GetPosition() const { return position_; } - - bool IsPastEnd() const { return position_ == static_cast<Index>(size_); } - - public: - CodePointIterator begin() const { return *this; } - CodePointIterator end() const { - return CodePointIterator{ptr_, size_, past_end_tag_t{}}; - } - - public: - bool operator==(const CodePointIterator& other) const { - // You should compare iterator that iterate on the same string. - Expects(this->ptr_ == other.ptr_ && this->size_ == other.size_); - return this->position_ == other.position_; - } - bool operator!=(const CodePointIterator& other) const { - return !this->operator==(other); - } - - CodePointIterator& operator++() { - Expects(!IsPastEnd()); - Forward(); - return *this; - } - - CodePointIterator operator++(int) { - Expects(!IsPastEnd()); - CodePointIterator old = *this; - Forward(); - return old; - } - - CodePoint operator*() const { - return NextCodePointFunction(ptr_, size_, position_, &next_position_cache_); - } - - private: - void Forward() { - if (next_position_cache_ > position_) { - position_ = next_position_cache_; - } else { - NextCodePointFunction(ptr_, size_, position_, &position_); - } - } - - private: - const CharType* ptr_; - Index size_; - Index position_; - mutable Index next_position_cache_ = 0; -}; - -using Utf8CodePointIterator = CodePointIterator<char, &Utf8NextCodePoint>; - -using Utf16CodePointIterator = CodePointIterator<char16_t, &Utf16NextCodePoint>; - -namespace details { -template <typename UInt, int number_of_bit, typename ReturnType> -inline std::enable_if_t<std::is_unsigned_v<UInt>, ReturnType> ExtractBits( - UInt n) { - return static_cast<ReturnType>(n & ((1u << number_of_bit) - 1)); -} -} // namespace details - -template <typename CharWriter> -std::enable_if_t<std::is_invocable_v<CharWriter, char>, bool> -Utf8EncodeCodePointAppend(CodePoint code_point, CharWriter&& writer) { - auto write_continue_byte = [&writer](std::uint8_t byte6) { - writer((1u << 7) + (((1u << 6) - 1) & byte6)); - }; - - if (code_point >= 0 && code_point <= 0x007F) { - writer(static_cast<char>(code_point)); - return true; - } else if (code_point >= 0x0080 && code_point <= 0x07FF) { - std::uint32_t unsigned_code_point = code_point; - writer( - static_cast<char>(details::ExtractBits<std::uint32_t, 5, std::uint8_t>( - (unsigned_code_point >> 6)) + - 0b11000000)); - write_continue_byte(details::ExtractBits<std::uint32_t, 6, std::uint8_t>( - unsigned_code_point)); - return true; - } else if (code_point >= 0x0800 && code_point <= 0xFFFF) { - std::uint32_t unsigned_code_point = code_point; - writer( - static_cast<char>(details::ExtractBits<std::uint32_t, 4, std::uint8_t>( - (unsigned_code_point >> (6 * 2))) + - 0b11100000)); - write_continue_byte(details::ExtractBits<std::uint32_t, 6, std::uint8_t>( - unsigned_code_point >> 6)); - write_continue_byte(details::ExtractBits<std::uint32_t, 6, std::uint8_t>( - unsigned_code_point)); - return true; - } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { - std::uint32_t unsigned_code_point = code_point; - writer( - static_cast<char>(details::ExtractBits<std::uint32_t, 3, std::uint8_t>( - (unsigned_code_point >> (6 * 3))) + - 0b11110000)); - write_continue_byte(details::ExtractBits<std::uint32_t, 6, std::uint8_t>( - unsigned_code_point >> (6 * 2))); - write_continue_byte(details::ExtractBits<std::uint32_t, 6, std::uint8_t>( - unsigned_code_point >> 6)); - write_continue_byte(details::ExtractBits<std::uint32_t, 6, std::uint8_t>( - unsigned_code_point)); - return true; - } else { - return false; - } -} - -template <typename CharWriter> -std::enable_if_t<std::is_invocable_v<CharWriter, char16_t>, bool> -Utf16EncodeCodePointAppend(CodePoint code_point, CharWriter&& writer) { - if ((code_point >= 0 && code_point <= 0xD7FF) || - (code_point >= 0xE000 && code_point <= 0xFFFF)) { - writer(static_cast<char16_t>(code_point)); - return true; - } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { - std::uint32_t u = code_point - 0x10000; - writer(static_cast<char16_t>( - details::ExtractBits<std::uint32_t, 10, std::uint32_t>(u >> 10) + - 0xD800u)); - writer(static_cast<char16_t>( - details::ExtractBits<std::uint32_t, 10, std::uint32_t>(u) + 0xDC00u)); - return true; - } else { - return false; - } -} - -// If given s is not a valid utf16 string, return value is UD. -bool CRU_BASE_API Utf16IsValidInsertPosition(const char16_t* ptr, Index size, - Index position); - -// Return position after the character making predicate returns true or 0 if no -// character doing so. -Index CRU_BASE_API -Utf16BackwardUntil(const char16_t* ptr, Index size, Index position, - const std::function<bool(CodePoint)>& predicate); -// Return position before the character making predicate returns true or -// str.size() if no character doing so. -Index CRU_BASE_API -Utf16ForwardUntil(const char16_t* ptr, Index size, Index position, - const std::function<bool(CodePoint)>& predicate); - -Index CRU_BASE_API Utf16PreviousWord(const char16_t* ptr, Index size, - Index position, bool* is_space = nullptr); -Index CRU_BASE_API Utf16NextWord(const char16_t* ptr, Index size, - Index position, bool* is_space = nullptr); - -char16_t CRU_BASE_API ToLower(char16_t c); -char16_t CRU_BASE_API ToUpper(char16_t c); - -bool CRU_BASE_API IsWhitespace(char16_t c); -bool CRU_BASE_API IsDigit(char16_t c); - -Utf8CodePointIterator CRU_BASE_API CreateUtf8Iterator(const std::byte* buffer, - Index size); -Utf8CodePointIterator CRU_BASE_API -CreateUtf8Iterator(const std::vector<std::byte>& buffer); - -} // namespace cru diff --git a/include/cru/common/SubProcess.h b/include/cru/common/SubProcess.h deleted file mode 100644 index fbe8ad2b..00000000 --- a/include/cru/common/SubProcess.h +++ /dev/null @@ -1,258 +0,0 @@ -#pragma once -#include "Base.h" -#include "Exception.h" -#include "String.h" -#include "io/Stream.h" - -#include <chrono> -#include <condition_variable> -#include <mutex> -#include <optional> -#include <unordered_map> -#include <vector> - -namespace cru { -enum class SubProcessStatus { - /** - * @brief The process has not been created and started. - */ - Prepare, - /** - * @brief The process is failed to start. - */ - FailedToStart, - /** - * @brief The process is running now. - */ - Running, - /** - * @brief The process has been exited. - */ - Exited, -}; - -class CRU_BASE_API SubProcessException : public Exception { - public: - using Exception::Exception; -}; - -class CRU_BASE_API SubProcessFailedToStartException - : public SubProcessException { - public: - using SubProcessException::SubProcessException; -}; - -class CRU_BASE_API SubProcessInternalException : public SubProcessException { - public: - using SubProcessException::SubProcessException; -}; - -struct SubProcessStartInfo { - String program; - std::vector<String> arguments; - std::unordered_map<String, String> environments; -}; - -enum class SubProcessExitType { - Unknown, - Normal, - Signal, -}; - -struct SubProcessExitResult { - SubProcessExitType exit_type; - int exit_code; - int exit_signal; - bool has_core_dump; - - bool IsSuccess() const { - return exit_type == SubProcessExitType::Normal && exit_code == 0; - } - - static SubProcessExitResult Unknown() { - return {SubProcessExitType::Unknown, 0, 0, false}; - } - - static SubProcessExitResult Normal(int exit_code) { - return {SubProcessExitType::Normal, exit_code, 0, false}; - } - - static SubProcessExitResult Signal(int exit_signal, bool has_core_dump) { - return {SubProcessExitType::Normal, 0, exit_signal, has_core_dump}; - } -}; - -struct IPlatformSubProcessImpl : virtual Interface { - /** - * @brief Create and start a real process. - * - * If the program can't be created or start, an exception should be - * thrown. - * - * Implementation should fill internal data of the new process and start - * it. - * - * This method will be called only once in first call of `Start` on this - * thread with lock holdDefaultConstructible. - */ - virtual void PlatformCreateProcess(const SubProcessStartInfo& start_info) = 0; - - /** - * @brief Wait for the created process forever and return the exit result - * when process stops. - * - * Implementation should wait for the real process forever, after that, - * fill internal data and returns exit result. - * - * This method will be called only once on another thread after - * `PlatformCreateProcess` returns successfully - */ - virtual SubProcessExitResult PlatformWaitForProcess() = 0; - - /** - * @brief Kill the process immediately. - * - * This method will be called only once on this thread given - * `PlatformCreateProcess` returns successfully. There will be a window - * that the window already exits but the status has not been updated and - * this is called. So handle this gracefully and write to internal data - * carefully. - */ - virtual void PlatformKillProcess() = 0; - - virtual io::Stream* GetStdinStream() = 0; - virtual io::Stream* GetStdoutStream() = 0; - virtual io::Stream* GetStderrStream() = 0; -}; - -/** - * @brief A wrapper platform process. It is one-time, which means it - * starts and exits and can't start again. - * - * TODO: Current implementation has a problem. If the process does not exit for - * a long time, the resource related to it will not be released. It may cause a - * leak. - */ -class PlatformSubProcess : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"PlatformSubProcess") - - private: - struct State { - explicit State(SubProcessStartInfo start_info, - std::shared_ptr<IPlatformSubProcessImpl> impl) - : start_info(std::move(start_info)), impl(std::move(impl)) {} - - std::mutex mutex; - std::condition_variable condition_variable; - SubProcessStartInfo start_info; - SubProcessExitResult exit_result; - SubProcessStatus status = SubProcessStatus::Prepare; - bool killed = false; - std::shared_ptr<IPlatformSubProcessImpl> impl; - }; - - public: - PlatformSubProcess(SubProcessStartInfo start_info, - std::shared_ptr<IPlatformSubProcessImpl> impl); - - ~PlatformSubProcess() override; - - /** - * @brief Create and start a real process. If the process can't be created or - * start, `SubProcessFailedToStartException` will be thrown. If this function - * is already called once, `SubProcessException` will be thrown. Ensure only - * call this method once. - */ - void Start(); - - /** - * @brief Wait for the process to exit optionally for at most `wait_time`. If - * the process already exits, it will return immediately. If the process has - * not started or failed to start, `SubProcessException` will be thrown. - * Ensure `Start` is called and does not throw before calling this. - * - * @remarks You may wish this returns bool to indicate whether it is timeout - * or the process exits. But no, even if it is timeout, the process may also - * have exited due to task schedule. - */ - void Wait(std::optional<std::chrono::milliseconds> wait_time); - - /** - * @brief kill the process if it is running. If the process already exits, - * nothing will happen. If the process has not started or failed to start, - * `SubProcessException` will be throw. Ensure `Start` is called and does not - * throw before calling this. - */ - void Kill(); - - /** - * @brief Get the status of the process. - * 1. If the process has tried to start, aka `Start` is called, then this - * method will return one of `Running`, `FailedToStart`, `Exited`. - * 2. If it returns `Prepare`, `Start` is not called. - * 3. It does NOT guarantee that this return `Running` and the process is - * actually running. Because there might be a window that the process exits - * already but status is not updated. - */ - SubProcessStatus GetStatus(); - - /** - * @brief Get the exit result. If the process is not started, failed to start - * or running, `SubProcessException` will be thrown. - */ - SubProcessExitResult GetExitResult(); - - io::Stream* GetStdinStream(); - io::Stream* GetStdoutStream(); - io::Stream* GetStderrStream(); - - private: - std::shared_ptr<State> state_; - std::unique_lock<std::mutex> lock_; -}; - -class CRU_BASE_API SubProcess : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"SubProcess") - - public: - static SubProcess Create( - String program, std::vector<String> arguments = {}, - std::unordered_map<String, String> environments = {}); - - static SubProcessExitResult Call( - String program, std::vector<String> arguments = {}, - std::unordered_map<String, String> environments = {}); - - public: - SubProcess(SubProcessStartInfo start_info); - - CRU_DELETE_COPY(SubProcess) - - SubProcess(SubProcess&& other) = default; - SubProcess& operator=(SubProcess&& other) = default; - - ~SubProcess() override; - - public: - void Wait(std::optional<std::chrono::milliseconds> wait_time = std::nullopt); - void Kill(); - - SubProcessStatus GetStatus(); - SubProcessExitResult GetExitResult(); - - io::Stream* GetStdinStream(); - io::Stream* GetStdoutStream(); - io::Stream* GetStderrStream(); - - void Detach(); - - bool IsValid() const { return platform_process_ != nullptr; } - explicit operator bool() const { return IsValid(); } - - private: - void CheckValid() const; - - private: - std::unique_ptr<PlatformSubProcess> platform_process_; -}; -} // namespace cru diff --git a/include/cru/common/concurrent/ConcurrentQueue.h b/include/cru/common/concurrent/ConcurrentQueue.h deleted file mode 100644 index e311d5f9..00000000 --- a/include/cru/common/concurrent/ConcurrentQueue.h +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once -#include <condition_variable> -#include <mutex> -#include <optional> -#include <utility> - -namespace cru::concurrent { -namespace details { -template <typename T> -struct ConcurrentQueueNode { - ConcurrentQueueNode(T&& value, ConcurrentQueueNode* next = nullptr) - : value(std::move(value)), next(next) {} - - T value; - ConcurrentQueueNode* next; -}; -} // namespace details - -template <typename T> -class ConcurrentQueue { - public: - ConcurrentQueue() {} - - ConcurrentQueue(const ConcurrentQueue&) = delete; - ConcurrentQueue& operator=(const ConcurrentQueue&) = delete; - - ~ConcurrentQueue() { - if (head_) { - auto node = head_; - while (node) { - auto next = node->next; - delete node; - node = next; - } - } - } - - public: - void Push(T&& value) { - std::unique_lock<std::mutex> lock(mutex_); - if (head_ == nullptr) { - head_ = tail_ = new details::ConcurrentQueueNode<T>(std::move(value)); - condition_variable_.notify_one(); - } else { - tail_->next = new details::ConcurrentQueueNode<T>(std::move(value)); - tail_ = tail_->next; - } - } - - T Pull() { - std::unique_lock<std::mutex> lock(mutex_); - if (head_ == nullptr) { - condition_variable_.wait(lock); - } - assert(head_ != nullptr); - auto value = std::move(head_->value); - auto next = head_->next; - delete head_; - head_ = next; - if (next == nullptr) { - tail_ = nullptr; - } - return value; - } - - std::optional<T> Poll() { - std::unique_lock<std::mutex> lock(mutex_); - if (head_ == nullptr) { - return std::nullopt; - } - auto value = std::move(head_->value); - auto next = head_->next; - delete head_; - head_ = next; - if (next == nullptr) { - tail_ = nullptr; - } - return value; - } - - private: - details::ConcurrentQueueNode<T>* head_ = nullptr; - details::ConcurrentQueueNode<T>* tail_ = nullptr; - - std::mutex mutex_; - std::condition_variable condition_variable_; -}; -} // namespace cru::concurrent diff --git a/include/cru/common/io/AutoReadStream.h b/include/cru/common/io/AutoReadStream.h deleted file mode 100644 index 759d5026..00000000 --- a/include/cru/common/io/AutoReadStream.h +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include "BufferStream.h" -#include "Stream.h" - -#include <mutex> -#include <thread> - -namespace cru::io { -struct AutoReadStreamOptions { - /** - * @brief Will be passed to BufferStreamOptions::block_size. - */ - Index block_size = 0; - - /** - * @brief Will be passed to BufferStreamOptions::total_size_limit. - */ - Index total_size_limit = 0; - - BufferStreamOptions GetBufferStreamOptions() const { - BufferStreamOptions options; - options.block_size = block_size; - options.total_size_limit = total_size_limit; - return options; - } -}; - -/** - * @brief A stream that wraps another stream and auto read it into a buffer in a - * background thread. - */ -class CRU_BASE_API AutoReadStream : public Stream { - public: - /** - * @brief Wrap a stream and auto read it in background. - * @param stream The stream to auto read. - * @param auto_delete Whether to delete the stream object in destructor. - * @param options Options to modify the behavior. - */ - AutoReadStream( - Stream* stream, bool auto_delete, - const AutoReadStreamOptions& options = AutoReadStreamOptions()); - - ~AutoReadStream() override; - - public: - CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE - - void BeginToDrop(bool auto_delete = true); - - protected: - Index DoRead(std::byte* buffer, Index offset, Index size) override; - Index DoWrite(const std::byte* buffer, Index offset, Index size) override; - void DoFlush() override; - - private: - void DoClose(); - - void BackgroundThreadRun(); - - private: - Stream* stream_; - bool auto_delete_; - - Index size_per_read_; - std::unique_ptr<BufferStream> buffer_stream_; - std::mutex buffer_stream_mutex_; - - std::thread background_thread_; -}; -} // namespace cru::io diff --git a/include/cru/common/io/BufferStream.h b/include/cru/common/io/BufferStream.h deleted file mode 100644 index 5ebff546..00000000 --- a/include/cru/common/io/BufferStream.h +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once - -#include "../Buffer.h" -#include "../Exception.h" -#include "Stream.h" - -#include <condition_variable> -#include <list> -#include <mutex> - -namespace cru::io { -class WriteAfterEofException : public Exception { - public: - using Exception::Exception; - ~WriteAfterEofException() override = default; -}; - -struct BufferStreamOptions { - /** - * Actually I have no ideas about the best value for this. May change it later - * when I get some ideas. - */ - constexpr static Index kDefaultBlockSize = 1024; - - /** - * @brief The size of a single buffer allocated each time new space is needed. - * Use default value if <= 0. - * - * When current buffer is full and there is no space for following data, a new - * buffer will be allocated and appended to the buffer list. Note if sum size - * of all buffers reaches the total_buffer_limit, no more buffer will be - * allocated but wait. - */ - Index block_size = 0; - - /** - * @brief Total size limit of saved data in buffer. No limit if <= 0. - * - * The size will be floor(total_size_limit / block_size). When the buffer is - * filled, it will block and wait for user to read to get free space of buffer - * to continue read. - */ - Index total_size_limit = 0; - - Index GetBlockSizeOrDefault() const { - return block_size <= 0 ? kDefaultBlockSize : block_size; - } - - Index GetMaxBlockCount() const { - return total_size_limit / GetBlockSizeOrDefault(); - } -}; - -/** - * @brief SPSC (Single Producer Single Consumer) buffer stream. - * - * If used by multiple producer or multiple consumer, the behavior is undefined. - */ -class BufferStream : public Stream { - public: - BufferStream(const BufferStreamOptions& options); - ~BufferStream() override; - - CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE - - void SetEof(); - - protected: - Index DoRead(std::byte* buffer, Index offset, Index size) override; - Index DoWrite(const std::byte* buffer, Index offset, Index size) override; - - private: - void DoClose(); - - private: - Index block_size_; - Index max_block_count_; - - std::list<Buffer> buffer_list_; - bool eof_; - - std::mutex mutex_; - std::condition_variable condition_variable_; -}; -} // namespace cru::io diff --git a/include/cru/common/io/CFileStream.h b/include/cru/common/io/CFileStream.h deleted file mode 100644 index 0b58bdc9..00000000 --- a/include/cru/common/io/CFileStream.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "Stream.h" - -#include <cstdio> - -namespace cru::io { -class CRU_BASE_API CFileStream : public Stream { - public: - CFileStream(const char* path, const char* mode); - explicit CFileStream(std::FILE* file, bool readable = true, - bool writable = true, bool auto_close = true); - - CRU_DELETE_COPY(CFileStream) - CRU_DELETE_MOVE(CFileStream) - - ~CFileStream() override; - - public: - CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE - - std::FILE* GetHandle() const; - - protected: - Index DoSeek(Index offset, SeekOrigin origin) override; - Index DoTell() override; - void DoRewind() override; - Index DoRead(std::byte* buffer, Index offset, Index size) override; - Index DoWrite(const std::byte* buffer, Index offset, Index size) override; - void DoFlush() override; - - private: - void DoClose(); - - private: - std::FILE* file_; - bool auto_close_; -}; -} // namespace cru::io diff --git a/include/cru/common/io/MemoryStream.h b/include/cru/common/io/MemoryStream.h deleted file mode 100644 index a1f90c3b..00000000 --- a/include/cru/common/io/MemoryStream.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "Stream.h" - -#include <functional> - -namespace cru::io { -class CRU_BASE_API MemoryStream : public Stream { - public: - MemoryStream( - std::byte* buffer, Index size, bool read_only = false, - std::function<void(std::byte* buffer, Index size)> release_func = {}); - - ~MemoryStream() override; - - public: - void Close() override; - - std::byte* GetBuffer() const { return buffer_; } - - protected: - Index DoSeek(Index offset, SeekOrigin origin) override; - Index DoGetSize() override { return size_; } - Index DoRead(std::byte* buffer, Index offset, Index size) override; - Index DoWrite(const std::byte* buffer, Index offset, Index size) override; - - private: - void DoClose(); - - private: - std::byte* buffer_; - Index size_; - Index position_; - std::function<void(std::byte* buffer, Index size)> release_func_; -}; -} // namespace cru::io diff --git a/include/cru/common/io/OpenFileFlag.h b/include/cru/common/io/OpenFileFlag.h deleted file mode 100644 index 4a5789fb..00000000 --- a/include/cru/common/io/OpenFileFlag.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "../Bitmask.h" - -namespace cru::io { -namespace details { -struct OpenFileFlagTag {}; -} // namespace details -using OpenFileFlag = Bitmask<details::OpenFileFlagTag>; - -struct OpenFileFlags { - /** - * \brief for reading - * If the file does not exist, FileNotExistException should be thrown. - */ - static constexpr OpenFileFlag Read{0x1}; - - /** - * \brief for writing - * If the file does not exist and Create is not specified, - * FileNotExistException should be thrown. - */ - static constexpr OpenFileFlag Write{0x2}; - - /** - * \brief when writing, seek to end first - * Only effective for writing. - */ - static constexpr OpenFileFlag Append{0x4}; - - /** - * \brief when writing, truncate the file to empty - * Only effective for writing. - * So the content is erased! Be careful! - */ - static constexpr OpenFileFlag Truncate{0x8}; - - /** - * \brief when writing, if the file does not exist, create one - * Only effective for writing. When file does not exist, FileNotExistException - * will NOT be thrown and a new file will be created. - */ - static constexpr OpenFileFlag Create{0x10}; - - /** - * TODO: ??? - */ - static constexpr OpenFileFlag Exclusive{0x20}; -}; - -/** - * Append, Truncate, Create must be used with Write. - * Append and Truncate must not be used together. - */ -bool CheckOpenFileFlag(OpenFileFlag flags); -} // namespace cru::io diff --git a/include/cru/common/io/ProxyStream.h b/include/cru/common/io/ProxyStream.h deleted file mode 100644 index 42ec9dfd..00000000 --- a/include/cru/common/io/ProxyStream.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "Stream.h" - -#include <functional> - -namespace cru::io { -struct ProxyStreamHandlers { - std::function<Index(Index offset, Stream::SeekOrigin origin)> seek; - std::function<Index(std::byte* buffer, Index offset, Index size)> read; - std::function<Index(const std::byte* buffer, Index offset, Index size)> write; - std::function<void()> flush; - - /** - * @brief This method will be only called once when `Close` is called or the - * stream is destructed. - */ - std::function<void()> close; -}; - -class ProxyStream : public Stream { - public: - explicit ProxyStream(ProxyStreamHandlers handlers); - - ~ProxyStream() override; - - public: - CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE - - protected: - Index DoSeek(Index offset, SeekOrigin origin) override; - Index DoRead(std::byte* buffer, Index offset, Index size) override; - Index DoWrite(const std::byte* buffer, Index offset, Index size) override; - void DoFlush() override; - - private: - void DoClose(); - - private: - ProxyStreamHandlers handlers_; -}; -} // namespace cru::io diff --git a/include/cru/common/io/Resource.h b/include/cru/common/io/Resource.h deleted file mode 100644 index 1d5313a6..00000000 --- a/include/cru/common/io/Resource.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "../Base.h" - -#include <filesystem> - -namespace cru::io { -std::filesystem::path CRU_BASE_API GetResourceDir(); -} diff --git a/include/cru/common/io/Stream.h b/include/cru/common/io/Stream.h deleted file mode 100644 index e0b61627..00000000 --- a/include/cru/common/io/Stream.h +++ /dev/null @@ -1,126 +0,0 @@ -#pragma once - -#include "../Base.h" - -#include "../Exception.h" -#include "../String.h" - -#include <cstddef> - -namespace cru::io { -class CRU_BASE_API StreamOperationNotSupportedException : public Exception { - public: - explicit StreamOperationNotSupportedException(String operation); - - CRU_DEFAULT_DESTRUCTOR(StreamOperationNotSupportedException) - - public: - String GetOperation() const { return operation_; } - - public: - static void CheckSeek(bool seekable); - static void CheckRead(bool readable); - static void CheckWrite(bool writable); - - private: - String operation_; -}; - -class CRU_BASE_API StreamAlreadyClosedException : public Exception { - public: - StreamAlreadyClosedException(); - - CRU_DEFAULT_DESTRUCTOR(StreamAlreadyClosedException) - - static void Check(bool closed); -}; - -#define CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE \ - void Close() override { DoClose(); } - -#define CRU_STREAM_BEGIN_CLOSE \ - if (GetClosed()) return; \ - CloseGuard close_guard(this); - -/** - * All stream is thread-unsafe by default unless being documented. - */ -class CRU_BASE_API Stream : public Object { - protected: - struct SupportedOperations { - std::optional<bool> can_seek; - std::optional<bool> can_read; - std::optional<bool> can_write; - }; - - struct CloseGuard { - explicit CloseGuard(Stream* stream) : stream(stream) {} - ~CloseGuard() { stream->SetClosed(true); } - Stream* stream; - }; - - protected: - explicit Stream(SupportedOperations supported_operations = {}); - Stream(std::optional<bool> can_seek, std::optional<bool> can_read, - std::optional<bool> can_write); - - public: - enum class SeekOrigin { Current, Begin, End }; - - CRU_DELETE_COPY(Stream) - CRU_DELETE_MOVE(Stream) - - ~Stream() override = default; - - public: - bool CanSeek(); - Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current); - Index Tell(); - void Rewind(); - Index GetSize(); - - bool CanRead(); - Index Read(std::byte* buffer, Index offset, Index size); - Index Read(std::byte* buffer, Index size); - Index Read(char* buffer, Index offset, Index size); - Index Read(char* buffer, Index size); - - bool CanWrite(); - Index Write(const std::byte* buffer, Index offset, Index size); - Index Write(const std::byte* buffer, Index size); - Index Write(const char* buffer, Index offset, Index size); - Index Write(const char* buffer, Index size); - - void Flush(); - virtual void Close() = 0; - - virtual Buffer ReadToEnd(Index grow_size = 256); - - // Utf8 encoding. - String ReadToEndAsUtf8String(); - - protected: - virtual bool DoCanSeek(); - virtual bool DoCanRead(); - virtual bool DoCanWrite(); - virtual Index DoSeek(Index offset, SeekOrigin origin); - virtual Index DoTell(); - virtual void DoRewind(); - virtual Index DoGetSize(); - virtual Index DoRead(std::byte* buffer, Index offset, Index size); - virtual Index DoWrite(const std::byte* buffer, Index offset, Index size); - virtual void DoFlush(); - - void SetSupportedOperations(SupportedOperations supported_operations) { - supported_operations_ = std::move(supported_operations); - } - - bool GetClosed() { return closed_; } - void SetClosed(bool closed) { closed_ = closed; } - void CheckClosed() { StreamAlreadyClosedException::Check(closed_); } - - private: - std::optional<SupportedOperations> supported_operations_; - bool closed_; -}; -} // namespace cru::io diff --git a/include/cru/common/log/Logger.h b/include/cru/common/log/Logger.h deleted file mode 100644 index 25735e14..00000000 --- a/include/cru/common/log/Logger.h +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once -#include "../Base.h" - -#include "../Format.h" -#include "../String.h" -#include "../concurrent/ConcurrentQueue.h" - -#include <memory> -#include <mutex> -#include <thread> -#include <vector> - -namespace cru::log { -enum class LogLevel { Debug, Info, Warn, Error }; - -struct CRU_BASE_API LogInfo { - LogInfo(LogLevel level, String tag, String message) - : level(level), tag(std::move(tag)), message(std::move(message)) {} - - CRU_DEFAULT_COPY(LogInfo) - CRU_DEFAULT_MOVE(LogInfo) - - ~LogInfo() = default; - - LogLevel level; - String tag; - String message; -}; - -struct CRU_BASE_API ILogTarget : virtual Interface { - // Write the string s. LogLevel is just a helper. It has no effect on the - // content to write. - virtual void Write(LogLevel level, StringView s) = 0; -}; - -class CRU_BASE_API Logger : public Object { - public: - static Logger* GetInstance(); - - public: - Logger(); - - CRU_DELETE_COPY(Logger) - CRU_DELETE_MOVE(Logger) - - ~Logger() override; - - public: - void AddLogTarget(std::unique_ptr<ILogTarget> source); - void RemoveLogTarget(ILogTarget* source); - - public: - void Log(LogLevel level, String tag, String message) { - Log(LogInfo(level, std::move(tag), std::move(message))); - } - void Log(LogInfo log_info); - - template <typename... Args> - void FormatLog(LogLevel level, String tag, StringView format, - Args&&... args) { - Log(level, std::move(tag), Format(format, std::forward<Args>(args)...)); - } - - private: - concurrent::ConcurrentQueue<LogInfo> log_queue_; - - std::mutex target_list_mutex_; - std::vector<std::unique_ptr<ILogTarget>> target_list_; - - std::thread log_thread_; -}; -} // namespace cru::log - -#define CRU_LOG_DEBUG(...) \ - cru::log::Logger::GetInstance()->FormatLog(cru::log::LogLevel::Debug, \ - kLogTag, __VA_ARGS__) - -#define CRU_LOG_INFO(...) \ - cru::log::Logger::GetInstance()->FormatLog(cru::log::LogLevel::Info, \ - kLogTag, __VA_ARGS__) - -#define CRU_LOG_WARN(...) \ - cru::log::Logger::GetInstance()->FormatLog(cru::log::LogLevel::Warn, \ - kLogTag, __VA_ARGS__) - -#define CRU_LOG_ERROR(...) \ - cru::log::Logger::GetInstance()->FormatLog(cru::log::LogLevel::Error, \ - kLogTag, __VA_ARGS__) diff --git a/include/cru/common/log/StdioLogTarget.h b/include/cru/common/log/StdioLogTarget.h deleted file mode 100644 index 4123766b..00000000 --- a/include/cru/common/log/StdioLogTarget.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "Logger.h" - -namespace cru::log { -class StdioLogTarget : public Object, public virtual log::ILogTarget { - public: - explicit StdioLogTarget(); - - CRU_DELETE_COPY(StdioLogTarget) - CRU_DELETE_MOVE(StdioLogTarget) - - ~StdioLogTarget() override; - - public: - void Write(log::LogLevel level, StringView s) override; -}; -} // namespace cru::log diff --git a/include/cru/common/platform/Exception.h b/include/cru/common/platform/Exception.h deleted file mode 100644 index 74dd6ad4..00000000 --- a/include/cru/common/platform/Exception.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include "../Base.h" -#include "../Exception.h" - -namespace cru::platform { -class CRU_BASE_API PlatformException : public Exception { - public: - using Exception::Exception; // inherit constructors - - CRU_DEFAULT_DESTRUCTOR(PlatformException) -}; -} // namespace cru::platform diff --git a/include/cru/common/platform/osx/Convert.h b/include/cru/common/platform/osx/Convert.h deleted file mode 100644 index 395cbbae..00000000 --- a/include/cru/common/platform/osx/Convert.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "../../PreConfig.h" - -#ifndef CRU_PLATFORM_OSX -#error "This file can only be included on osx." -#endif - -#include "../../String.h" - -#include <CoreFoundation/CoreFoundation.h> - -namespace cru::platform::osx { -CFStringRef Convert(const String& string); -String Convert(CFStringRef string); - -CFRange Convert(const Range& range); -Range Convert(const CFRange& range); -} // namespace cru::platform::osx diff --git a/include/cru/common/platform/osx/Exception.h b/include/cru/common/platform/osx/Exception.h deleted file mode 100644 index 5ab14ebd..00000000 --- a/include/cru/common/platform/osx/Exception.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "../../PreConfig.h" - -#ifndef CRU_PLATFORM_OSX -#error "This file can only be included on osx." -#endif - -#include "../Exception.h" - -namespace cru::platform::osx { -class OsxException : public PlatformException { - public: - using PlatformException::PlatformException; -}; -} // namespace cru::platform::osx diff --git a/include/cru/common/platform/unix/PosixSpawnSubProcess.h b/include/cru/common/platform/unix/PosixSpawnSubProcess.h deleted file mode 100644 index ee4e912a..00000000 --- a/include/cru/common/platform/unix/PosixSpawnSubProcess.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "../../PreConfig.h" - -#ifndef CRU_PLATFORM_UNIX -#error "This file can only be included on unix." -#endif - -#include "../../Base.h" -#include "../../SubProcess.h" -#include "../../io/AutoReadStream.h" - -#include "UnixFileStream.h" -#include "UnixPipe.h" - -#include <spawn.h> - -namespace cru::platform::unix { -class PosixSpawnSubProcessImpl : public Object, - public virtual IPlatformSubProcessImpl { - CRU_DEFINE_CLASS_LOG_TAG(u"PosixSpawnSubProcess") - - public: - explicit PosixSpawnSubProcessImpl(); - ~PosixSpawnSubProcessImpl(); - - void PlatformCreateProcess(const SubProcessStartInfo& start_info) override; - SubProcessExitResult PlatformWaitForProcess() override; - void PlatformKillProcess() override; - - io::Stream* GetStdinStream() override; - io::Stream* GetStdoutStream() override; - io::Stream* GetStderrStream() override; - - private: - pid_t pid_; - int exit_code_; - - UnixPipe stdin_pipe_; - UnixPipe stdout_pipe_; - UnixPipe stderr_pipe_; - - std::unique_ptr<UnixFileStream> stdin_stream_; - std::unique_ptr<UnixFileStream> stdout_stream_; - std::unique_ptr<UnixFileStream> stderr_stream_; - - std::unique_ptr<io::AutoReadStream> stdout_buffer_stream_; - std::unique_ptr<io::AutoReadStream> stderr_buffer_stream_; -}; -} // namespace cru::platform::unix diff --git a/include/cru/common/platform/unix/UnixFileStream.h b/include/cru/common/platform/unix/UnixFileStream.h deleted file mode 100644 index 8021f21a..00000000 --- a/include/cru/common/platform/unix/UnixFileStream.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "../../PreConfig.h" - -#ifndef CRU_PLATFORM_UNIX -#error "This file can only be included on unix." -#endif - -#include "../../io/Stream.h" - -namespace cru::platform::unix { -class UnixFileStream : public io::Stream { - private: - static constexpr auto kLogTag = u"cru::platform::unix::UnixFileStream"; - - public: - UnixFileStream(const char* path, int oflag, mode_t mode = 0660); - UnixFileStream(int fd, bool can_seek, bool can_read, bool can_write, - bool auto_close); - ~UnixFileStream() override; - - public: - CRU_STREAM_IMPLEMENT_CLOSE_BY_DO_CLOSE - - int GetFileDescriptor() const { return file_descriptor_; } - - protected: - Index DoSeek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; - Index DoRead(std::byte* buffer, Index offset, Index size) override; - Index DoWrite(const std::byte* buffer, Index offset, Index size) override; - - private: - void DoClose(); - - private: - int file_descriptor_; // -1 for no file descriptor - bool auto_close_; -}; -} // namespace cru::platform::unix diff --git a/include/cru/common/platform/unix/UnixPipe.h b/include/cru/common/platform/unix/UnixPipe.h deleted file mode 100644 index cf35fb11..00000000 --- a/include/cru/common/platform/unix/UnixPipe.h +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once - -#include "../../PreConfig.h" - -#ifndef CRU_PLATFORM_UNIX -#error "This file can only be included on unix." -#endif - -#include "../../Base.h" -#include "../../Bitmask.h" - -namespace cru::platform::unix { -namespace details { -struct UnixPipeFlagTag; -} -using UnixPipeFlag = Bitmask<details::UnixPipeFlagTag>; -struct UnixPipeFlags { - constexpr static auto NonBlock = UnixPipeFlag::FromOffset(1); -}; - -/** - * @brief an unix pipe, commonly for communication of parent process and child - * process. - * - * There are two types of pipes sorted by its usage. For stdin, parent process - * SEND data to child process. For stdout and stderr, parent process RECEIVE - * data from child process. Each pipe has two ends, one for read and the other - * for write. But for send and receive, they are reversed. It is a little - * confused to consider which end should be used by parent and which end should - * be used by child. So this class help you make it clear. You specify SEND or - * RECEIVE, and this class give you a parent used end and a child used end. - * - * This class will only close the end used by parent when it is destructed. It - * is the user's duty to close the one used by child. - */ -class UnixPipe : public Object { - private: - constexpr static auto kLogTag = u"cru::platform::unix::UnixPipe"; - - public: - enum class Usage { - Send, - Receive, - }; - - explicit UnixPipe(Usage usage, bool auto_close, UnixPipeFlag flags = {}); - - CRU_DELETE_COPY(UnixPipe) - CRU_DELETE_MOVE(UnixPipe) - - ~UnixPipe(); - - /** - * @brief aka, the one used by parent process. - */ - int GetSelfFileDescriptor(); - - /** - * @brief aka, the one used by child process. - */ - int GetOtherFileDescriptor(); - - private: - Usage usage_; - bool auto_close_; - UnixPipeFlag flags_; - int read_fd_; - int write_fd_; -}; -} // namespace cru::platform::unix diff --git a/include/cru/common/platform/web/WebException.h b/include/cru/common/platform/web/WebException.h deleted file mode 100644 index d98b8943..00000000 --- a/include/cru/common/platform/web/WebException.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "../../PreConfig.h" - -#ifdef CRU_PLATFORM_EMSCRIPTEN - -#include "../Exception.h" - -namespace cru::platform::web { -class WebException : public PlatformException { - public: - using PlatformException::PlatformException; -}; -} // namespace cru::platform::web - -#endif diff --git a/include/cru/common/platform/win/ComAutoInit.h b/include/cru/common/platform/win/ComAutoInit.h deleted file mode 100644 index cc968e4b..00000000 --- a/include/cru/common/platform/win/ComAutoInit.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "../../PreConfig.h" -#ifdef CRU_PLATFORM_WINDOWS - -#include "WinPreConfig.h" -#include "cru/common/Base.h" - -namespace cru::platform::win { -class CRU_BASE_API ComAutoInit { - public: - ComAutoInit(); - - CRU_DELETE_COPY(ComAutoInit) - CRU_DELETE_MOVE(ComAutoInit) - - ~ComAutoInit(); -}; -} // namespace cru::platform::win - -#endif diff --git a/include/cru/common/platform/win/DebugLogTarget.h b/include/cru/common/platform/win/DebugLogTarget.h deleted file mode 100644 index 8257f637..00000000 --- a/include/cru/common/platform/win/DebugLogTarget.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include "../../PreConfig.h" -#ifdef CRU_PLATFORM_WINDOWS - -#include "WinPreConfig.h" - -#include "../../log/Logger.h" - -namespace cru::platform::win { - -class CRU_BASE_API WinDebugLogTarget : public ::cru::log::ILogTarget { - public: - WinDebugLogTarget() = default; - - CRU_DELETE_COPY(WinDebugLogTarget) - CRU_DELETE_MOVE(WinDebugLogTarget) - - ~WinDebugLogTarget() = default; - - void Write(::cru::log::LogLevel level, StringView s) override; -}; -} // namespace cru::platform::win - -#endif diff --git a/include/cru/common/platform/win/Exception.h b/include/cru/common/platform/win/Exception.h deleted file mode 100644 index 3e63b191..00000000 --- a/include/cru/common/platform/win/Exception.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include "../../PreConfig.h" -#ifdef CRU_PLATFORM_WINDOWS - -#include "WinPreConfig.h" - -#include "../Exception.h" - -#include <stdexcept> -#include <string_view> - -namespace cru::platform::win { -class CRU_BASE_API HResultError : public platform::PlatformException { - public: - explicit HResultError(HRESULT h_result); - explicit HResultError(HRESULT h_result, std::string_view message); - - CRU_DEFAULT_COPY(HResultError) - CRU_DEFAULT_MOVE(HResultError) - - ~HResultError() override = default; - - HRESULT GetHResult() const { return h_result_; } - - private: - HRESULT h_result_; -}; - -inline void ThrowIfFailed(const HRESULT h_result) { - if (FAILED(h_result)) throw HResultError(h_result); -} - -inline void ThrowIfFailed(const HRESULT h_result, std::string_view message) { - if (FAILED(h_result)) throw HResultError(h_result, message); -} - -class CRU_BASE_API Win32Error : public platform::PlatformException { - public: - // ::GetLastError is automatically called to get the error code. - // The same as Win32Error(::GetLastError(), message) - explicit Win32Error(String message); - Win32Error(DWORD error_code, String message); - - CRU_DEFAULT_COPY(Win32Error) - CRU_DEFAULT_MOVE(Win32Error) - - ~Win32Error() override = default; - - DWORD GetErrorCode() const { return error_code_; } - - private: - DWORD error_code_; -}; -} // namespace cru::platform::win - -#endif diff --git a/include/cru/common/platform/win/StreamConvert.h b/include/cru/common/platform/win/StreamConvert.h deleted file mode 100644 index 3499604a..00000000 --- a/include/cru/common/platform/win/StreamConvert.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "../../PreConfig.h" - -#ifdef CRU_PLATFORM_WINDOWS - -#include "../../io/Stream.h" - -#include <objidlbase.h> - -namespace cru::platform::win { -CRU_BASE_API IStream* ConvertStreamToComStream(io::Stream* stream); -} - -#endif diff --git a/include/cru/common/platform/win/Win32FileStream.h b/include/cru/common/platform/win/Win32FileStream.h deleted file mode 100644 index 06656466..00000000 --- a/include/cru/common/platform/win/Win32FileStream.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "../../PreConfig.h" - -#ifdef CRU_PLATFORM_WINDOWS - -#include "../../String.h" -#include "../../io/OpenFileFlag.h" -#include "../../io/Stream.h" - -namespace cru::platform::win { -namespace details { -class Win32FileStreamPrivate; -} - -class CRU_BASE_API Win32FileStream : public io::Stream { - public: - Win32FileStream(String path, io::OpenFileFlag flags); - - CRU_DELETE_COPY(Win32FileStream) - CRU_DELETE_MOVE(Win32FileStream) - - ~Win32FileStream() override; - - public: - bool CanSeek() override; - Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) override; - - bool CanRead() override; - Index Read(std::byte* buffer, Index offset, Index size) override; - using Stream::Read; - - bool CanWrite() override; - Index Write(const std::byte* buffer, Index offset, Index size) override; - using Stream::Write; - - void Close() override; - - String GetPath() const { return path_; } - io::OpenFileFlag GetOpenFileFlags() const { return flags_; } - - details::Win32FileStreamPrivate* GetPrivate_() { return p_; } - - private: - void CheckClosed(); - - private: - String path_; - io::OpenFileFlag flags_; - bool closed_ = false; - - details::Win32FileStreamPrivate* p_; -}; -} // namespace cru::platform::win - -#endif diff --git a/include/cru/common/platform/win/WinPreConfig.h b/include/cru/common/platform/win/WinPreConfig.h deleted file mode 100644 index c2284df3..00000000 --- a/include/cru/common/platform/win/WinPreConfig.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../../PreConfig.h" -#ifdef CRU_PLATFORM_WINDOWS - -#define NOMINMAX -#define WIN32_LEAN_AND_MEAN -#include <Windows.h> -#undef CreateWindow -#undef DrawText -#undef CreateFont -#undef CreateEvent - -#endif |