From 74bb9cd27242b9320f99ff4d2b50c3051576cc14 Mon Sep 17 00:00:00 2001 From: crupest Date: Tue, 8 Feb 2022 16:53:51 +0800 Subject: ... --- include/cru/common/Base.h | 98 +++++ include/cru/common/Base.hpp | 98 ----- include/cru/common/Bitmask.h | 42 ++ include/cru/common/Bitmask.hpp | 42 -- include/cru/common/ClonablePtr.h | 216 ++++++++++ include/cru/common/ClonablePtr.hpp | 216 ---------- include/cru/common/Event.h | 281 +++++++++++++ include/cru/common/Event.hpp | 281 ------------- include/cru/common/Exception.h | 32 ++ include/cru/common/Exception.hpp | 32 -- include/cru/common/Format.h | 143 +++++++ include/cru/common/Format.hpp | 143 ------- include/cru/common/HandlerRegistry.h | 87 ++++ include/cru/common/HandlerRegistry.hpp | 87 ---- include/cru/common/Logger.h | 114 ++++++ include/cru/common/Logger.hpp | 114 ------ include/cru/common/PreConfig.h | 16 + include/cru/common/PreConfig.hpp | 16 - include/cru/common/PropertyTree.h | 63 +++ include/cru/common/PropertyTree.hpp | 63 --- include/cru/common/Range.h | 43 ++ include/cru/common/Range.hpp | 43 -- include/cru/common/SelfResolvable.h | 69 ++++ include/cru/common/SelfResolvable.hpp | 69 ---- include/cru/common/String.h | 436 +++++++++++++++++++++ include/cru/common/String.hpp | 436 --------------------- include/cru/common/StringUtil.h | 223 +++++++++++ include/cru/common/StringUtil.hpp | 223 ----------- include/cru/common/io/FileStream.h | 13 + include/cru/common/io/FileStream.hpp | 13 - include/cru/common/io/MemoryStream.h | 44 +++ include/cru/common/io/MemoryStream.hpp | 44 --- include/cru/common/io/OpenFileFlag.h | 18 + include/cru/common/io/OpenFileFlag.hpp | 18 - include/cru/common/io/Resource.h | 8 + include/cru/common/io/Resource.hpp | 8 - include/cru/common/io/Stream.h | 48 +++ include/cru/common/io/Stream.hpp | 48 --- include/cru/common/platform/Exception.h | 15 + include/cru/common/platform/Exception.hpp | 15 - include/cru/common/platform/osx/Convert.h | 17 + include/cru/common/platform/osx/Convert.hpp | 17 - include/cru/common/platform/osx/Exception.h | 14 + include/cru/common/platform/osx/Exception.hpp | 14 - include/cru/common/platform/unix/ErrnoException.h | 28 ++ .../cru/common/platform/unix/ErrnoException.hpp | 28 -- include/cru/common/platform/unix/UnixFileStream.h | 46 +++ .../cru/common/platform/unix/UnixFileStream.hpp | 46 --- include/cru/common/platform/win/ComAutoInit.h | 21 + include/cru/common/platform/win/ComAutoInit.hpp | 21 - include/cru/common/platform/win/Exception.h | 56 +++ include/cru/common/platform/win/Exception.hpp | 56 --- include/cru/common/platform/win/StreamConvert.h | 14 + include/cru/common/platform/win/StreamConvert.hpp | 14 - include/cru/common/platform/win/Win32FileStream.h | 54 +++ .../cru/common/platform/win/Win32FileStream.hpp | 54 --- include/cru/common/platform/win/WinPreConfig.h | 13 + include/cru/common/platform/win/WinPreConfig.hpp | 13 - 58 files changed, 2272 insertions(+), 2272 deletions(-) create mode 100644 include/cru/common/Base.h delete mode 100644 include/cru/common/Base.hpp create mode 100644 include/cru/common/Bitmask.h delete mode 100644 include/cru/common/Bitmask.hpp create mode 100644 include/cru/common/ClonablePtr.h delete mode 100644 include/cru/common/ClonablePtr.hpp create mode 100644 include/cru/common/Event.h delete mode 100644 include/cru/common/Event.hpp create mode 100644 include/cru/common/Exception.h delete mode 100644 include/cru/common/Exception.hpp create mode 100644 include/cru/common/Format.h delete mode 100644 include/cru/common/Format.hpp create mode 100644 include/cru/common/HandlerRegistry.h delete mode 100644 include/cru/common/HandlerRegistry.hpp create mode 100644 include/cru/common/Logger.h delete mode 100644 include/cru/common/Logger.hpp create mode 100644 include/cru/common/PreConfig.h delete mode 100644 include/cru/common/PreConfig.hpp create mode 100644 include/cru/common/PropertyTree.h delete mode 100644 include/cru/common/PropertyTree.hpp create mode 100644 include/cru/common/Range.h delete mode 100644 include/cru/common/Range.hpp create mode 100644 include/cru/common/SelfResolvable.h delete mode 100644 include/cru/common/SelfResolvable.hpp create mode 100644 include/cru/common/String.h delete mode 100644 include/cru/common/String.hpp create mode 100644 include/cru/common/StringUtil.h delete mode 100644 include/cru/common/StringUtil.hpp create mode 100644 include/cru/common/io/FileStream.h delete mode 100644 include/cru/common/io/FileStream.hpp create mode 100644 include/cru/common/io/MemoryStream.h delete mode 100644 include/cru/common/io/MemoryStream.hpp create mode 100644 include/cru/common/io/OpenFileFlag.h delete mode 100644 include/cru/common/io/OpenFileFlag.hpp create mode 100644 include/cru/common/io/Resource.h delete mode 100644 include/cru/common/io/Resource.hpp create mode 100644 include/cru/common/io/Stream.h delete mode 100644 include/cru/common/io/Stream.hpp create mode 100644 include/cru/common/platform/Exception.h delete mode 100644 include/cru/common/platform/Exception.hpp create mode 100644 include/cru/common/platform/osx/Convert.h delete mode 100644 include/cru/common/platform/osx/Convert.hpp create mode 100644 include/cru/common/platform/osx/Exception.h delete mode 100644 include/cru/common/platform/osx/Exception.hpp create mode 100644 include/cru/common/platform/unix/ErrnoException.h delete mode 100644 include/cru/common/platform/unix/ErrnoException.hpp create mode 100644 include/cru/common/platform/unix/UnixFileStream.h delete mode 100644 include/cru/common/platform/unix/UnixFileStream.hpp create mode 100644 include/cru/common/platform/win/ComAutoInit.h delete mode 100644 include/cru/common/platform/win/ComAutoInit.hpp create mode 100644 include/cru/common/platform/win/Exception.h delete mode 100644 include/cru/common/platform/win/Exception.hpp create mode 100644 include/cru/common/platform/win/StreamConvert.h delete mode 100644 include/cru/common/platform/win/StreamConvert.hpp create mode 100644 include/cru/common/platform/win/Win32FileStream.h delete mode 100644 include/cru/common/platform/win/Win32FileStream.hpp create mode 100644 include/cru/common/platform/win/WinPreConfig.h delete mode 100644 include/cru/common/platform/win/WinPreConfig.hpp (limited to 'include/cru/common') diff --git a/include/cru/common/Base.h b/include/cru/common/Base.h new file mode 100644 index 00000000..4d4d1f5f --- /dev/null +++ b/include/cru/common/Base.h @@ -0,0 +1,98 @@ +#pragma once +#include "PreConfig.h" + +#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 + +#include + +#define CRU_UNUSED(entity) static_cast(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 = gsl::index; + +// https://www.boost.org/doc/libs/1_54_0/doc/html/hash/reference.html#boost.hash_combine +template +inline void hash_combine(std::size_t& s, const T& v) { + std::hash h; + s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); +} + +#define CRU_DEFINE_CLASS_LOG_TAG(tag) \ + private: \ + constexpr static StringView log_tag = tag; +} // namespace cru diff --git a/include/cru/common/Base.hpp b/include/cru/common/Base.hpp deleted file mode 100644 index bab4f733..00000000 --- a/include/cru/common/Base.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once -#include "PreConfig.hpp" - -#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 - -#include - -#define CRU_UNUSED(entity) static_cast(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 = gsl::index; - -// https://www.boost.org/doc/libs/1_54_0/doc/html/hash/reference.html#boost.hash_combine -template -inline void hash_combine(std::size_t& s, const T& v) { - std::hash h; - s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2); -} - -#define CRU_DEFINE_CLASS_LOG_TAG(tag) \ - private: \ - constexpr static StringView log_tag = tag; -} // namespace cru diff --git a/include/cru/common/Bitmask.h b/include/cru/common/Bitmask.h new file mode 100644 index 00000000..bd6a8309 --- /dev/null +++ b/include/cru/common/Bitmask.h @@ -0,0 +1,42 @@ +#pragma once +#include "Base.h" + +namespace cru { +template +struct Bitmask final { + using Underlying = TUnderlying; + + constexpr Bitmask() : value(0) {} + constexpr explicit Bitmask(TUnderlying value) : value(value) {} + + CRU_DEFAULT_COPY(Bitmask) + CRU_DEFAULT_MOVE(Bitmask) + + ~Bitmask() = default; + + 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 diff --git a/include/cru/common/Bitmask.hpp b/include/cru/common/Bitmask.hpp deleted file mode 100644 index c1b6443a..00000000 --- a/include/cru/common/Bitmask.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once -#include "Base.hpp" - -namespace cru { -template -struct Bitmask final { - using Underlying = TUnderlying; - - constexpr Bitmask() : value(0) {} - constexpr explicit Bitmask(TUnderlying value) : value(value) {} - - CRU_DEFAULT_COPY(Bitmask) - CRU_DEFAULT_MOVE(Bitmask) - - ~Bitmask() = default; - - 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 diff --git a/include/cru/common/ClonablePtr.h b/include/cru/common/ClonablePtr.h new file mode 100644 index 00000000..39b5b454 --- /dev/null +++ b/include/cru/common/ClonablePtr.h @@ -0,0 +1,216 @@ +#pragma once + +#include +#include +#include +#include + +namespace cru { +template +class ClonablePtr { + template + friend class ClonablePtr; + + public: + using element_type = typename std::unique_ptr::element_type; + using pointer = typename std::unique_ptr::pointer; + + ClonablePtr() = default; + ClonablePtr(std::nullptr_t) noexcept : ptr_(nullptr) {} + explicit ClonablePtr(pointer p) noexcept : ptr_(p) {} + ClonablePtr(std::unique_ptr&& p) noexcept + : ptr_(std::move(p)) {} + template ::pointer, pointer>, + int> = 0> + ClonablePtr(std::unique_ptr&& p) : ptr_(std::move(p)) {} + ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} + ClonablePtr(ClonablePtr&& other) = default; + template ::pointer, pointer>, + int> = 0> + ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} + template ::pointer, pointer>, + int> = 0> + ClonablePtr(ClonablePtr&& other) noexcept : ptr_(std::move(other.ptr_)) {} + ClonablePtr& operator=(std::nullptr_t) noexcept { + ptr_ = nullptr; + return *this; + } + ClonablePtr& operator=(std::unique_ptr&& other) noexcept { + ptr_ = std::move(other); + return *this; + } + template ::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(std::unique_ptr&& p) noexcept { + ptr_ = std::move(p); + return *this; + } + ClonablePtr& operator=(const ClonablePtr& other) { + if (this != &other) { + ptr_ = std::unique_ptr(other.ptr_->Clone()); + } + return *this; + } + ClonablePtr& operator=(ClonablePtr&& other) = default; + template ::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(const ClonablePtr& other) noexcept { + if (this != &other) { + ptr_ = std::unique_ptr(other.ptr_->Clone()); + } + return *this; + } + template ::pointer, pointer>, + int> = 0> + ClonablePtr& operator=(ClonablePtr&& 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_; } + + 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 ptr_; +}; + +template +void swap(ClonablePtr& left, ClonablePtr& right) noexcept { + left.swap(right); +} + +template +bool operator==(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) == 0; +} + +template +bool operator!=(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) != 0; +} + +template +bool operator<(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) < 0; +} + +template +bool operator<=(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) <= 0; +} + +template +bool operator>(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) > 0; +} + +template +bool operator>=(const ClonablePtr& left, const ClonablePtr& right) { + return left.Compare(right) >= 0; +} + +template +bool operator==(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) == 0; +} + +template +bool operator!=(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) != 0; +} + +template +bool operator<(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) < 0; +} + +template +bool operator<=(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) <= 0; +} + +template +bool operator>(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) > 0; +} + +template +bool operator>=(const ClonablePtr& left, std::nullptr_t) { + return left.Compare(nullptr) >= 0; +} + +template +bool operator==(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) == 0; +} + +template +bool operator!=(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) != 0; +} + +template +bool operator<(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) > 0; +} + +template +bool operator<=(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) >= 0; +} + +template +bool operator>(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) < 0; +} + +template +bool operator>=(std::nullptr_t, const ClonablePtr& right) { + return right.Compare(nullptr) <= 0; +} + +} // namespace cru + +namespace std { +template +struct hash> { + std::size_t operator()(const cru::ClonablePtr& p) const { + return std::hash::pointer>(p.get()); + } +}; +} // namespace std diff --git a/include/cru/common/ClonablePtr.hpp b/include/cru/common/ClonablePtr.hpp deleted file mode 100644 index 39b5b454..00000000 --- a/include/cru/common/ClonablePtr.hpp +++ /dev/null @@ -1,216 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace cru { -template -class ClonablePtr { - template - friend class ClonablePtr; - - public: - using element_type = typename std::unique_ptr::element_type; - using pointer = typename std::unique_ptr::pointer; - - ClonablePtr() = default; - ClonablePtr(std::nullptr_t) noexcept : ptr_(nullptr) {} - explicit ClonablePtr(pointer p) noexcept : ptr_(p) {} - ClonablePtr(std::unique_ptr&& p) noexcept - : ptr_(std::move(p)) {} - template ::pointer, pointer>, - int> = 0> - ClonablePtr(std::unique_ptr&& p) : ptr_(std::move(p)) {} - ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} - ClonablePtr(ClonablePtr&& other) = default; - template ::pointer, pointer>, - int> = 0> - ClonablePtr(const ClonablePtr& other) : ptr_(other.ptr_->Clone()) {} - template ::pointer, pointer>, - int> = 0> - ClonablePtr(ClonablePtr&& other) noexcept : ptr_(std::move(other.ptr_)) {} - ClonablePtr& operator=(std::nullptr_t) noexcept { - ptr_ = nullptr; - return *this; - } - ClonablePtr& operator=(std::unique_ptr&& other) noexcept { - ptr_ = std::move(other); - return *this; - } - template ::pointer, pointer>, - int> = 0> - ClonablePtr& operator=(std::unique_ptr&& p) noexcept { - ptr_ = std::move(p); - return *this; - } - ClonablePtr& operator=(const ClonablePtr& other) { - if (this != &other) { - ptr_ = std::unique_ptr(other.ptr_->Clone()); - } - return *this; - } - ClonablePtr& operator=(ClonablePtr&& other) = default; - template ::pointer, pointer>, - int> = 0> - ClonablePtr& operator=(const ClonablePtr& other) noexcept { - if (this != &other) { - ptr_ = std::unique_ptr(other.ptr_->Clone()); - } - return *this; - } - template ::pointer, pointer>, - int> = 0> - ClonablePtr& operator=(ClonablePtr&& 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_; } - - 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 ptr_; -}; - -template -void swap(ClonablePtr& left, ClonablePtr& right) noexcept { - left.swap(right); -} - -template -bool operator==(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) == 0; -} - -template -bool operator!=(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) != 0; -} - -template -bool operator<(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) < 0; -} - -template -bool operator<=(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) <= 0; -} - -template -bool operator>(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) > 0; -} - -template -bool operator>=(const ClonablePtr& left, const ClonablePtr& right) { - return left.Compare(right) >= 0; -} - -template -bool operator==(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) == 0; -} - -template -bool operator!=(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) != 0; -} - -template -bool operator<(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) < 0; -} - -template -bool operator<=(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) <= 0; -} - -template -bool operator>(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) > 0; -} - -template -bool operator>=(const ClonablePtr& left, std::nullptr_t) { - return left.Compare(nullptr) >= 0; -} - -template -bool operator==(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) == 0; -} - -template -bool operator!=(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) != 0; -} - -template -bool operator<(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) > 0; -} - -template -bool operator<=(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) >= 0; -} - -template -bool operator>(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) < 0; -} - -template -bool operator>=(std::nullptr_t, const ClonablePtr& right) { - return right.Compare(nullptr) <= 0; -} - -} // namespace cru - -namespace std { -template -struct hash> { - std::size_t operator()(const cru::ClonablePtr& p) const { - return std::hash::pointer>(p.get()); - } -}; -} // namespace std diff --git a/include/cru/common/Event.h b/include/cru/common/Event.h new file mode 100644 index 00000000..564afc40 --- /dev/null +++ b/include/cru/common/Event.h @@ -0,0 +1,281 @@ +#pragma once +#include "Base.h" + +#include "SelfResolvable.h" + +#include +#include +#include +#include +#include +#include + +namespace cru { +class EventRevoker; + +namespace details { +template +inline constexpr bool always_false_v = false; + +// Base class of all Event. +// It erases event args types and provides a +// unified form to create event revoker and +// revoke(remove) handler. +class EventBase : public SelfResolvable { + 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&& 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 resolver_; + details::EventBase::EventHandlerToken token_; +}; + +inline EventRevoker details::EventBase::CreateRevoker(EventHandlerToken token) { + return EventRevoker(CreateResolver(), token); +} + +// int -> int +// Point -> const Point& +// int& -> int& +template +using DeducedEventArgs = std::conditional_t< + std::is_lvalue_reference_v, TRaw, + std::conditional_t, 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; + + 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 +struct IEvent : virtual IBaseEvent { + public: + using EventArgs = DeducedEventArgs; + using EventHandler = std::function; + using ShortCircuitHandler = std::function; + + 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 +class Event : public details::EventBase, public IEvent { + using typename IEvent::EventArgs; + + using typename IBaseEvent::SpyOnlyHandler; + using typename IEvent::EventHandler; + using typename IEvent::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 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 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 + Expects(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 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 event_revoker_guard_list_; +}; +} // namespace cru diff --git a/include/cru/common/Event.hpp b/include/cru/common/Event.hpp deleted file mode 100644 index 5d60c5b3..00000000 --- a/include/cru/common/Event.hpp +++ /dev/null @@ -1,281 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "SelfResolvable.hpp" - -#include -#include -#include -#include -#include -#include - -namespace cru { -class EventRevoker; - -namespace details { -template -inline constexpr bool always_false_v = false; - -// Base class of all Event. -// It erases event args types and provides a -// unified form to create event revoker and -// revoke(remove) handler. -class EventBase : public SelfResolvable { - 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&& 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 resolver_; - details::EventBase::EventHandlerToken token_; -}; - -inline EventRevoker details::EventBase::CreateRevoker(EventHandlerToken token) { - return EventRevoker(CreateResolver(), token); -} - -// int -> int -// Point -> const Point& -// int& -> int& -template -using DeducedEventArgs = std::conditional_t< - std::is_lvalue_reference_v, TRaw, - std::conditional_t, 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; - - 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 -struct IEvent : virtual IBaseEvent { - public: - using EventArgs = DeducedEventArgs; - using EventHandler = std::function; - using ShortCircuitHandler = std::function; - - 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 -class Event : public details::EventBase, public IEvent { - using typename IEvent::EventArgs; - - using typename IBaseEvent::SpyOnlyHandler; - using typename IEvent::EventHandler; - using typename IEvent::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 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 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 - Expects(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 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 event_revoker_guard_list_; -}; -} // namespace cru diff --git a/include/cru/common/Exception.h b/include/cru/common/Exception.h new file mode 100644 index 00000000..365d2064 --- /dev/null +++ b/include/cru/common/Exception.h @@ -0,0 +1,32 @@ +#pragma once +#include "String.h" + +namespace cru { +#ifdef _MSC_VER +#pragma warning(disable : 4275) +#endif +class CRU_BASE_API Exception : public std::exception { + public: + Exception(); + explicit Exception(String message); + + CRU_DEFAULT_COPY(Exception) + CRU_DEFAULT_MOVE(Exception) + + ~Exception() override; + + public: + String GetMessage() const { return message_; } + + const char* what() const noexcept override; + + private: + String message_; + mutable std::string utf8_message_; +}; + +class CRU_BASE_API TextEncodeException : public Exception { + public: + using Exception::Exception; +}; +} // namespace cru diff --git a/include/cru/common/Exception.hpp b/include/cru/common/Exception.hpp deleted file mode 100644 index cb35469c..00000000 --- a/include/cru/common/Exception.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#include "String.hpp" - -namespace cru { -#ifdef _MSC_VER -#pragma warning(disable : 4275) -#endif -class CRU_BASE_API Exception : public std::exception { - public: - Exception(); - explicit Exception(String message); - - CRU_DEFAULT_COPY(Exception) - CRU_DEFAULT_MOVE(Exception) - - ~Exception() override; - - public: - String GetMessage() const { return message_; } - - const char* what() const noexcept override; - - private: - String message_; - mutable std::string utf8_message_; -}; - -class CRU_BASE_API TextEncodeException : public Exception { - public: - using Exception::Exception; -}; -} // namespace cru diff --git a/include/cru/common/Format.h b/include/cru/common/Format.h new file mode 100644 index 00000000..ede2998b --- /dev/null +++ b/include/cru/common/Format.h @@ -0,0 +1,143 @@ +#pragma once + +#include "Exception.h" +#include "String.h" + +#include + +namespace cru { +inline String ToString(bool value) { + return value ? String(u"true") : String(u"false"); +} + +template +std::enable_if_t, String> ToString(T value) { + std::array buffer; + auto result = + std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); + + if (result.ec == std::errc{}) { + } else { + throw std::invalid_argument("Failed to convert value to chars."); + } + + auto size = result.ptr - buffer.data(); + auto b = new char16_t[size + 1]; + b[size] = 0; + std::copy(buffer.data(), result.ptr, b); + return String::FromBuffer(b, size, size); +} + +template +std::enable_if_t, String> ToString(T value) { + auto str = std::to_string(value); + return String(str.cbegin(), str.cend()); +} + +template +std::enable_if_t< + std::is_convertible_v)), String>, + 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 CRU_BASE_API ParseToFormatTokenList(const String& str); + +void CRU_BASE_API FormatAppendFromFormatTokenList( + String& current, const std::vector& format_token_list, + Index index); + +template +void FormatAppendFromFormatTokenList( + String& current, const std::vector& format_token_list, + Index index, TA&& args0, T&&... args) { + for (Index i = index; i < static_cast(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(args0), token.place_holder_option); + FormatAppendFromFormatTokenList(current, format_token_list, i + 1, + std::forward(args)...); + + return; + } else { + throw Exception( + u"Currently do not support positional or named place holder."); + } + } else { + current += token.data; + } + } +} +} // namespace details + +template +String Format(const String& format, T&&... args) { + String result; + + details::FormatAppendFromFormatTokenList( + result, details::ParseToFormatTokenList(format), 0, + std::forward(args)...); + + return result; +} + +template +String String::Format(T&&... args) const { + return cru::Format(*this, std::forward(args)...); +} +} // namespace cru diff --git a/include/cru/common/Format.hpp b/include/cru/common/Format.hpp deleted file mode 100644 index 1ad71262..00000000 --- a/include/cru/common/Format.hpp +++ /dev/null @@ -1,143 +0,0 @@ -#pragma once - -#include "Exception.hpp" -#include "String.hpp" - -#include - -namespace cru { -inline String ToString(bool value) { - return value ? String(u"true") : String(u"false"); -} - -template -std::enable_if_t, String> ToString(T value) { - std::array buffer; - auto result = - std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); - - if (result.ec == std::errc{}) { - } else { - throw std::invalid_argument("Failed to convert value to chars."); - } - - auto size = result.ptr - buffer.data(); - auto b = new char16_t[size + 1]; - b[size] = 0; - std::copy(buffer.data(), result.ptr, b); - return String::FromBuffer(b, size, size); -} - -template -std::enable_if_t, String> ToString(T value) { - auto str = std::to_string(value); - return String(str.cbegin(), str.cend()); -} - -template -std::enable_if_t< - std::is_convertible_v)), String>, - 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 CRU_BASE_API ParseToFormatTokenList(const String& str); - -void CRU_BASE_API FormatAppendFromFormatTokenList( - String& current, const std::vector& format_token_list, - Index index); - -template -void FormatAppendFromFormatTokenList( - String& current, const std::vector& format_token_list, - Index index, TA&& args0, T&&... args) { - for (Index i = index; i < static_cast(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(args0), token.place_holder_option); - FormatAppendFromFormatTokenList(current, format_token_list, i + 1, - std::forward(args)...); - - return; - } else { - throw Exception( - u"Currently do not support positional or named place holder."); - } - } else { - current += token.data; - } - } -} -} // namespace details - -template -String Format(const String& format, T&&... args) { - String result; - - details::FormatAppendFromFormatTokenList( - result, details::ParseToFormatTokenList(format), 0, - std::forward(args)...); - - return result; -} - -template -String String::Format(T&&... args) const { - return cru::Format(*this, std::forward(args)...); -} -} // namespace cru diff --git a/include/cru/common/HandlerRegistry.h b/include/cru/common/HandlerRegistry.h new file mode 100644 index 00000000..e405d1fd --- /dev/null +++ b/include/cru/common/HandlerRegistry.h @@ -0,0 +1,87 @@ +#pragma once +#include "Base.h" + +#include +#include +#include +#include + +namespace cru { + +template +class HandlerRegistryIterator { + public: + using RawIterator = + typename std::vector>>::const_iterator; + + explicit HandlerRegistryIterator(RawIterator raw) : raw_(std::move(raw)) {} + + CRU_DELETE_COPY(HandlerRegistryIterator) + CRU_DELETE_MOVE(HandlerRegistryIterator) + + ~HandlerRegistryIterator() = default; + + const std::function& operator*() const { return raw_->second; } + const std::function* operator->() const { return &raw_->second; } + + HandlerRegistryIterator& operator++() { + ++raw_; + return *this; + } + + HandlerRegistryIterator operator++(int) { + auto c = *this; + this->operator++(); + return c; + } + + bool operator==(const HandlerRegistryIterator& other) const { + return this->raw_ == other.raw_; + } + + bool operator!=(const HandlerRegistryIterator& other) const { + return !this->operator==(other); + } + + private: + RawIterator raw_; +}; + +template +class HandlerRegistry final { + public: + HandlerRegistry() = default; + CRU_DEFAULT_COPY(HandlerRegistry) + CRU_DEFAULT_MOVE(HandlerRegistry) + ~HandlerRegistry() = default; + + public: + int AddHandler(std::function 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>& d) { + return d.first == id; + }); + if (result != handler_list_.cend()) { + handler_list_.erase(result); + } + } + + HandlerRegistryIterator begin() const { + return HandlerRegistryIterator(handler_list_.begin()); + } + + HandlerRegistryIterator end() const { + return HandlerRegistryIterator(handler_list_.end()); + } + + private: + int current_id_ = 1; + std::vector>> handler_list_; +}; +} // namespace cru diff --git a/include/cru/common/HandlerRegistry.hpp b/include/cru/common/HandlerRegistry.hpp deleted file mode 100644 index 8049e74b..00000000 --- a/include/cru/common/HandlerRegistry.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include -#include -#include -#include - -namespace cru { - -template -class HandlerRegistryIterator { - public: - using RawIterator = - typename std::vector>>::const_iterator; - - explicit HandlerRegistryIterator(RawIterator raw) : raw_(std::move(raw)) {} - - CRU_DELETE_COPY(HandlerRegistryIterator) - CRU_DELETE_MOVE(HandlerRegistryIterator) - - ~HandlerRegistryIterator() = default; - - const std::function& operator*() const { return raw_->second; } - const std::function* operator->() const { return &raw_->second; } - - HandlerRegistryIterator& operator++() { - ++raw_; - return *this; - } - - HandlerRegistryIterator operator++(int) { - auto c = *this; - this->operator++(); - return c; - } - - bool operator==(const HandlerRegistryIterator& other) const { - return this->raw_ == other.raw_; - } - - bool operator!=(const HandlerRegistryIterator& other) const { - return !this->operator==(other); - } - - private: - RawIterator raw_; -}; - -template -class HandlerRegistry final { - public: - HandlerRegistry() = default; - CRU_DEFAULT_COPY(HandlerRegistry) - CRU_DEFAULT_MOVE(HandlerRegistry) - ~HandlerRegistry() = default; - - public: - int AddHandler(std::function 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>& d) { - return d.first == id; - }); - if (result != handler_list_.cend()) { - handler_list_.erase(result); - } - } - - HandlerRegistryIterator begin() const { - return HandlerRegistryIterator(handler_list_.begin()); - } - - HandlerRegistryIterator end() const { - return HandlerRegistryIterator(handler_list_.end()); - } - - private: - int current_id_ = 1; - std::vector>> handler_list_; -}; -} // namespace cru diff --git a/include/cru/common/Logger.h b/include/cru/common/Logger.h new file mode 100644 index 00000000..25875651 --- /dev/null +++ b/include/cru/common/Logger.h @@ -0,0 +1,114 @@ +#pragma once +#include "Base.h" + +#include "String.h" +#include "Format.h" + +#include +#include + +namespace cru::log { + +enum class LogLevel { Debug, Info, Warn, Error }; + +struct CRU_BASE_API ILogSource : 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() = default; + + CRU_DELETE_COPY(Logger) + CRU_DELETE_MOVE(Logger) + + ~Logger() override = default; + + public: + void AddSource(std::unique_ptr source); + void RemoveSource(ILogSource* source); + + public: + void Log(LogLevel level, StringView message); + void Log(LogLevel level, StringView tag, StringView message); + + private: + std::list> sources_; +}; + +// TODO: Remove argument evaluation in Debug. +template +void Debug([[maybe_unused]] TArgs&&... args) { +#ifdef CRU_DEBUG + Logger::GetInstance()->Log(LogLevel::Debug, + Format(std::forward(args)...)); +#endif +} + +template +void Info(TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Info, + Format(std::forward(args)...)); +} + +template +void Warn(TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Warn, + Format(std::forward(args)...)); +} + +template +void Error(TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Error, + Format(std::forward(args)...)); +} + +// TODO: Remove argument evaluation in Debug. +template +void TagDebug([[maybe_unused]] StringView tag, + [[maybe_unused]] TArgs&&... args) { +#ifdef CRU_DEBUG + Logger::GetInstance()->Log(LogLevel::Debug, tag, + Format(std::forward(args)...)); +#endif +} + +template +void TagInfo(StringView tag, TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Info, tag, + Format(std::forward(args)...)); +} + +template +void TagWarn(StringView tag, TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Warn, tag, + Format(std::forward(args)...)); +} + +template +void TagError(StringView tag, TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Error, tag, + Format(std::forward(args)...)); +} + +class StdioLogSource : public Object, public virtual ILogSource { + public: + explicit StdioLogSource(bool use_lock = false); + + CRU_DELETE_COPY(StdioLogSource) + CRU_DELETE_MOVE(StdioLogSource) + + ~StdioLogSource() override; + + public: + void Write(LogLevel level, StringView s) override; + + private: + bool use_lock_; +}; +} // namespace cru::log diff --git a/include/cru/common/Logger.hpp b/include/cru/common/Logger.hpp deleted file mode 100644 index c4a3e54a..00000000 --- a/include/cru/common/Logger.hpp +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "String.hpp" -#include "Format.hpp" - -#include -#include - -namespace cru::log { - -enum class LogLevel { Debug, Info, Warn, Error }; - -struct CRU_BASE_API ILogSource : 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() = default; - - CRU_DELETE_COPY(Logger) - CRU_DELETE_MOVE(Logger) - - ~Logger() override = default; - - public: - void AddSource(std::unique_ptr source); - void RemoveSource(ILogSource* source); - - public: - void Log(LogLevel level, StringView message); - void Log(LogLevel level, StringView tag, StringView message); - - private: - std::list> sources_; -}; - -// TODO: Remove argument evaluation in Debug. -template -void Debug([[maybe_unused]] TArgs&&... args) { -#ifdef CRU_DEBUG - Logger::GetInstance()->Log(LogLevel::Debug, - Format(std::forward(args)...)); -#endif -} - -template -void Info(TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Info, - Format(std::forward(args)...)); -} - -template -void Warn(TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Warn, - Format(std::forward(args)...)); -} - -template -void Error(TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Error, - Format(std::forward(args)...)); -} - -// TODO: Remove argument evaluation in Debug. -template -void TagDebug([[maybe_unused]] StringView tag, - [[maybe_unused]] TArgs&&... args) { -#ifdef CRU_DEBUG - Logger::GetInstance()->Log(LogLevel::Debug, tag, - Format(std::forward(args)...)); -#endif -} - -template -void TagInfo(StringView tag, TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Info, tag, - Format(std::forward(args)...)); -} - -template -void TagWarn(StringView tag, TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Warn, tag, - Format(std::forward(args)...)); -} - -template -void TagError(StringView tag, TArgs&&... args) { - Logger::GetInstance()->Log(LogLevel::Error, tag, - Format(std::forward(args)...)); -} - -class StdioLogSource : public Object, public virtual ILogSource { - public: - explicit StdioLogSource(bool use_lock = false); - - CRU_DELETE_COPY(StdioLogSource) - CRU_DELETE_MOVE(StdioLogSource) - - ~StdioLogSource() override; - - public: - void Write(LogLevel level, StringView s) override; - - private: - bool use_lock_; -}; -} // namespace cru::log diff --git a/include/cru/common/PreConfig.h b/include/cru/common/PreConfig.h new file mode 100644 index 00000000..ba0f5bd8 --- /dev/null +++ b/include/cru/common/PreConfig.h @@ -0,0 +1,16 @@ +#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/PreConfig.hpp b/include/cru/common/PreConfig.hpp deleted file mode 100644 index ba0f5bd8..00000000 --- a/include/cru/common/PreConfig.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#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 new file mode 100644 index 00000000..54e185b9 --- /dev/null +++ b/include/cru/common/PropertyTree.h @@ -0,0 +1,63 @@ +#pragma once + +#include "Base.h" +#include "String.h" + +#include + +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 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 values_; +}; + +} // namespace cru diff --git a/include/cru/common/PropertyTree.hpp b/include/cru/common/PropertyTree.hpp deleted file mode 100644 index 613bcc47..00000000 --- a/include/cru/common/PropertyTree.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include "Base.hpp" -#include "String.hpp" - -#include - -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 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 values_; -}; - -} // namespace cru diff --git a/include/cru/common/Range.h b/include/cru/common/Range.h new file mode 100644 index 00000000..e61d90ca --- /dev/null +++ b/include/cru/common/Range.h @@ -0,0 +1,43 @@ +#pragma once +#include "Base.h" + +namespace cru { +struct Range final { + constexpr static Range FromTwoSides(gsl::index start, gsl::index end) { + return Range(start, end - start); + } + + constexpr static Range FromTwoSides(gsl::index start, gsl::index end, + gsl::index offset) { + return Range(start + offset, end - start); + } + + constexpr Range() = default; + constexpr Range(const gsl::index position, const gsl::index count = 0) + : position(position), count(count) {} + + gsl::index GetStart() const { return position; } + gsl::index GetEnd() const { return position + count; } + + void ChangeEnd(gsl::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(gsl::index min, gsl::index max) const { + auto coerce = [min, max](gsl::index index) { + return index > max ? max : (index < min ? min : index); + }; + return Range::FromTwoSides(coerce(GetStart()), coerce(GetEnd())); + } + + gsl::index position = 0; + gsl::index count = 0; +}; +} // namespace cru diff --git a/include/cru/common/Range.hpp b/include/cru/common/Range.hpp deleted file mode 100644 index ecc61243..00000000 --- a/include/cru/common/Range.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once -#include "Base.hpp" - -namespace cru { -struct Range final { - constexpr static Range FromTwoSides(gsl::index start, gsl::index end) { - return Range(start, end - start); - } - - constexpr static Range FromTwoSides(gsl::index start, gsl::index end, - gsl::index offset) { - return Range(start + offset, end - start); - } - - constexpr Range() = default; - constexpr Range(const gsl::index position, const gsl::index count = 0) - : position(position), count(count) {} - - gsl::index GetStart() const { return position; } - gsl::index GetEnd() const { return position + count; } - - void ChangeEnd(gsl::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(gsl::index min, gsl::index max) const { - auto coerce = [min, max](gsl::index index) { - return index > max ? max : (index < min ? min : index); - }; - return Range::FromTwoSides(coerce(GetStart()), coerce(GetEnd())); - } - - gsl::index position = 0; - gsl::index count = 0; -}; -} // namespace cru diff --git a/include/cru/common/SelfResolvable.h b/include/cru/common/SelfResolvable.h new file mode 100644 index 00000000..c8acd4b9 --- /dev/null +++ b/include/cru/common/SelfResolvable.h @@ -0,0 +1,69 @@ +#pragma once +#include "PreConfig.h" + +#include +#include + +namespace cru { +template +class SelfResolvable; + +template +class ObjectResolver { + friend SelfResolvable; + + private: + ObjectResolver(const std::shared_ptr& resolver) : resolver_(resolver) {} + + public: + ObjectResolver(const ObjectResolver&) = default; + ObjectResolver& operator=(const ObjectResolver&) = default; + ObjectResolver(ObjectResolver&&) = default; + ObjectResolver& operator=(ObjectResolver&&) = default; + ~ObjectResolver() = default; + + T* Resolve() const { + // resolver_ is null only when this has been moved. + // You shouldn't resolve a moved resolver. So assert it. + Expects(resolver_); + return *resolver_; + } + + private: + std::shared_ptr resolver_; +}; + +template +class SelfResolvable { + public: + SelfResolvable() : resolver_(new T*(static_cast(this))) {} + 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_)) { + (*resolver_) = static_cast(this); + } + + // Old resolvers for this object will resolve to nullptr. + // Other's resolvers will now resolve to this. + SelfResolvable& operator=(SelfResolvable&& other) { + if (this != &other) { + (*resolver_) = nullptr; + resolver_ = std::move(other.resolver_); + (*resolver_) = static_cast(this); + } + return *this; + } + + virtual ~SelfResolvable() { + if (resolver_ != nullptr) (*resolver_) = nullptr; + } + + ObjectResolver CreateResolver() { return ObjectResolver(resolver_); } + + private: + std::shared_ptr resolver_; +}; +} // namespace cru diff --git a/include/cru/common/SelfResolvable.hpp b/include/cru/common/SelfResolvable.hpp deleted file mode 100644 index eaa4ce34..00000000 --- a/include/cru/common/SelfResolvable.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once -#include "PreConfig.hpp" - -#include -#include - -namespace cru { -template -class SelfResolvable; - -template -class ObjectResolver { - friend SelfResolvable; - - private: - ObjectResolver(const std::shared_ptr& resolver) : resolver_(resolver) {} - - public: - ObjectResolver(const ObjectResolver&) = default; - ObjectResolver& operator=(const ObjectResolver&) = default; - ObjectResolver(ObjectResolver&&) = default; - ObjectResolver& operator=(ObjectResolver&&) = default; - ~ObjectResolver() = default; - - T* Resolve() const { - // resolver_ is null only when this has been moved. - // You shouldn't resolve a moved resolver. So assert it. - Expects(resolver_); - return *resolver_; - } - - private: - std::shared_ptr resolver_; -}; - -template -class SelfResolvable { - public: - SelfResolvable() : resolver_(new T*(static_cast(this))) {} - 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_)) { - (*resolver_) = static_cast(this); - } - - // Old resolvers for this object will resolve to nullptr. - // Other's resolvers will now resolve to this. - SelfResolvable& operator=(SelfResolvable&& other) { - if (this != &other) { - (*resolver_) = nullptr; - resolver_ = std::move(other.resolver_); - (*resolver_) = static_cast(this); - } - return *this; - } - - virtual ~SelfResolvable() { - if (resolver_ != nullptr) (*resolver_) = nullptr; - } - - ObjectResolver CreateResolver() { return ObjectResolver(resolver_); } - - private: - std::shared_ptr resolver_; -}; -} // namespace cru diff --git a/include/cru/common/String.h b/include/cru/common/String.h new file mode 100644 index 00000000..0b1b031b --- /dev/null +++ b/include/cru/common/String.h @@ -0,0 +1,436 @@ +#pragma once +#include "Base.h" + +#include "Range.h" +#include "StringUtil.h" + +#include +#include +#include +#include +#include +#include +#include + +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; + using const_reverse_iterator = std::reverse_iterator; + + public: + static String FromUtf8(const char* str); + static String FromUtf8(const char* str, Index size); + static String FromUtf8(std::string_view str) { + return FromUtf8(str.data(), str.size()); + } + + 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; + + explicit String(const_pointer str); + String(const_pointer str, size_type size); + + template + String(const char16_t (&str)[size]) + : String(reinterpret_cast(str), size - 1) {} + + template + String(Iter start, Iter end) { + for (; start != end; start++) { + append(*start); + } + } + + String(size_type size, value_type ch = 0); + + String(std::initializer_list 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 Split(value_type separator, + bool remove_space_line = false) const; + std::vector 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; + + float ParseToFloat(Index* processed_characters_count = nullptr) const; + double ParseToDouble(Index* processed_characters_count = nullptr) const; + std::vector ParseToFloatList(value_type separator = u' ') const; + std::vector ParseToDoubleList(value_type separator = u' ') const; + +#ifdef CRU_PLATFORM_WINDOWS + const wchar_t* WinCStr() const { + return reinterpret_cast(c_str()); + } +#endif + + template + String Format(T&&... args) const; + + std::string ToUtf8() 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 +}; + +class CRU_BASE_API StringView { + public: + static double_conversion::StringToDoubleConverter + kDefaultStringToDoubleConverter; + + 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; + using const_reverse_iterator = std::reverse_iterator; + + StringView() = default; + + constexpr StringView(const_pointer ptr, Index size) + : ptr_(ptr), size_(size) {} + + template + 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 Split(value_type separator, + bool remove_space_line = false) const; + std::vector 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; + + float ParseToFloat(Index* processed_characters_count = nullptr) const; + double ParseToDouble(Index* processed_characters_count = nullptr) const; + std::vector ParseToFloatList(value_type separator = u' ') const; + std::vector ParseToDoubleList(value_type separator = u' ') const; + + std::string ToUtf8() const; + + private: + const char16_t* ptr_; + Index size_; +}; + +CRU_DEFINE_COMPARE_OPERATORS(String) + +inline String operator+(const String& left, const String& right) { + String 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& 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& 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); +} // namespace cru + +template <> +struct std::hash { + std::size_t operator()(const cru::String& value) const { + return std::hash{}(std::u16string_view( + reinterpret_cast(value.data()), value.size())); + } +}; + +template <> +struct std::hash { + std::size_t operator()(const cru::StringView& value) const { + return std::hash{}(std::u16string_view( + reinterpret_cast(value.data()), value.size())); + } +}; diff --git a/include/cru/common/String.hpp b/include/cru/common/String.hpp deleted file mode 100644 index c1f957c0..00000000 --- a/include/cru/common/String.hpp +++ /dev/null @@ -1,436 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include "Range.hpp" -#include "StringUtil.hpp" - -#include -#include -#include -#include -#include -#include -#include - -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; - using const_reverse_iterator = std::reverse_iterator; - - public: - static String FromUtf8(const char* str); - static String FromUtf8(const char* str, Index size); - static String FromUtf8(std::string_view str) { - return FromUtf8(str.data(), str.size()); - } - - 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; - - explicit String(const_pointer str); - String(const_pointer str, size_type size); - - template - String(const char16_t (&str)[size]) - : String(reinterpret_cast(str), size - 1) {} - - template - String(Iter start, Iter end) { - for (; start != end; start++) { - append(*start); - } - } - - String(size_type size, value_type ch = 0); - - String(std::initializer_list 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 Split(value_type separator, - bool remove_space_line = false) const; - std::vector 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; - - float ParseToFloat(Index* processed_characters_count = nullptr) const; - double ParseToDouble(Index* processed_characters_count = nullptr) const; - std::vector ParseToFloatList(value_type separator = u' ') const; - std::vector ParseToDoubleList(value_type separator = u' ') const; - -#ifdef CRU_PLATFORM_WINDOWS - const wchar_t* WinCStr() const { - return reinterpret_cast(c_str()); - } -#endif - - template - String Format(T&&... args) const; - - std::string ToUtf8() 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 -}; - -class CRU_BASE_API StringView { - public: - static double_conversion::StringToDoubleConverter - kDefaultStringToDoubleConverter; - - 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; - using const_reverse_iterator = std::reverse_iterator; - - StringView() = default; - - constexpr StringView(const_pointer ptr, Index size) - : ptr_(ptr), size_(size) {} - - template - 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 Split(value_type separator, - bool remove_space_line = false) const; - std::vector 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; - - float ParseToFloat(Index* processed_characters_count = nullptr) const; - double ParseToDouble(Index* processed_characters_count = nullptr) const; - std::vector ParseToFloatList(value_type separator = u' ') const; - std::vector ParseToDoubleList(value_type separator = u' ') const; - - std::string ToUtf8() const; - - private: - const char16_t* ptr_; - Index size_; -}; - -CRU_DEFINE_COMPARE_OPERATORS(String) - -inline String operator+(const String& left, const String& right) { - String 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& 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& 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); -} // namespace cru - -template <> -struct std::hash { - std::size_t operator()(const cru::String& value) const { - return std::hash{}(std::u16string_view( - reinterpret_cast(value.data()), value.size())); - } -}; - -template <> -struct std::hash { - std::size_t operator()(const cru::StringView& value) const { - return std::hash{}(std::u16string_view( - reinterpret_cast(value.data()), value.size())); - } -}; diff --git a/include/cru/common/StringUtil.h b/include/cru/common/StringUtil.h new file mode 100644 index 00000000..19948250 --- /dev/null +++ b/include/cru/common/StringUtil.h @@ -0,0 +1,223 @@ +#pragma once +#include "Base.h" + +#include + +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 +using NextCodePointFunctionType = CodePoint (*)(const CharType*, Index, Index, + Index*); + +template 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(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; + +using Utf16CodePointIterator = CodePointIterator; + +namespace details { +template +inline std::enable_if_t, ReturnType> ExtractBits( + UInt n) { + return static_cast(n & ((1u << number_of_bit) - 1)); +} +} // namespace details + +template +bool Utf8EncodeCodePointAppend(CodePoint code_point, TStr& str) { + auto write_continue_byte = [&str](std::uint8_t byte6) { + str.push_back((1u << 7) + (((1u << 6) - 1) & byte6)); + }; + + if (code_point >= 0 && code_point <= 0x007F) { + str.push_back(static_cast(code_point)); + return true; + } else if (code_point >= 0x0080 && code_point <= 0x07FF) { + std::uint32_t unsigned_code_point = code_point; + str.push_back( + static_cast(details::ExtractBits( + (unsigned_code_point >> 6)) + + 0b11000000)); + write_continue_byte(details::ExtractBits( + unsigned_code_point)); + return true; + } else if (code_point >= 0x0800 && code_point <= 0xFFFF) { + std::uint32_t unsigned_code_point = code_point; + str.push_back( + static_cast(details::ExtractBits( + (unsigned_code_point >> (6 * 2))) + + 0b11100000)); + write_continue_byte(details::ExtractBits( + unsigned_code_point >> 6)); + write_continue_byte(details::ExtractBits( + unsigned_code_point)); + return true; + } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { + std::uint32_t unsigned_code_point = code_point; + str.push_back( + static_cast(details::ExtractBits( + (unsigned_code_point >> (6 * 3))) + + 0b11110000)); + write_continue_byte(details::ExtractBits( + unsigned_code_point >> (6 * 2))); + write_continue_byte(details::ExtractBits( + unsigned_code_point >> 6)); + write_continue_byte(details::ExtractBits( + unsigned_code_point)); + return true; + } else { + return false; + } +} + +template +bool Utf16EncodeCodePointAppend(CodePoint code_point, TStr& str) { + if ((code_point >= 0 && code_point <= 0xD7FF) || + (code_point >= 0xE000 && code_point <= 0xFFFF)) { + str.push_back(static_cast(code_point)); + return true; + } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { + std::uint32_t u = code_point - 0x10000; + str.push_back(static_cast( + details::ExtractBits(u >> 10) + + 0xD800u)); + str.push_back(static_cast( + details::ExtractBits(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& 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& 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& buffer); + +} // namespace cru diff --git a/include/cru/common/StringUtil.hpp b/include/cru/common/StringUtil.hpp deleted file mode 100644 index c840960d..00000000 --- a/include/cru/common/StringUtil.hpp +++ /dev/null @@ -1,223 +0,0 @@ -#pragma once -#include "Base.hpp" - -#include - -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 -using NextCodePointFunctionType = CodePoint (*)(const CharType*, Index, Index, - Index*); - -template 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(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; - -using Utf16CodePointIterator = CodePointIterator; - -namespace details { -template -inline std::enable_if_t, ReturnType> ExtractBits( - UInt n) { - return static_cast(n & ((1u << number_of_bit) - 1)); -} -} // namespace details - -template -bool Utf8EncodeCodePointAppend(CodePoint code_point, TStr& str) { - auto write_continue_byte = [&str](std::uint8_t byte6) { - str.push_back((1u << 7) + (((1u << 6) - 1) & byte6)); - }; - - if (code_point >= 0 && code_point <= 0x007F) { - str.push_back(static_cast(code_point)); - return true; - } else if (code_point >= 0x0080 && code_point <= 0x07FF) { - std::uint32_t unsigned_code_point = code_point; - str.push_back( - static_cast(details::ExtractBits( - (unsigned_code_point >> 6)) + - 0b11000000)); - write_continue_byte(details::ExtractBits( - unsigned_code_point)); - return true; - } else if (code_point >= 0x0800 && code_point <= 0xFFFF) { - std::uint32_t unsigned_code_point = code_point; - str.push_back( - static_cast(details::ExtractBits( - (unsigned_code_point >> (6 * 2))) + - 0b11100000)); - write_continue_byte(details::ExtractBits( - unsigned_code_point >> 6)); - write_continue_byte(details::ExtractBits( - unsigned_code_point)); - return true; - } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { - std::uint32_t unsigned_code_point = code_point; - str.push_back( - static_cast(details::ExtractBits( - (unsigned_code_point >> (6 * 3))) + - 0b11110000)); - write_continue_byte(details::ExtractBits( - unsigned_code_point >> (6 * 2))); - write_continue_byte(details::ExtractBits( - unsigned_code_point >> 6)); - write_continue_byte(details::ExtractBits( - unsigned_code_point)); - return true; - } else { - return false; - } -} - -template -bool Utf16EncodeCodePointAppend(CodePoint code_point, TStr& str) { - if ((code_point >= 0 && code_point <= 0xD7FF) || - (code_point >= 0xE000 && code_point <= 0xFFFF)) { - str.push_back(static_cast(code_point)); - return true; - } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { - std::uint32_t u = code_point - 0x10000; - str.push_back(static_cast( - details::ExtractBits(u >> 10) + - 0xD800u)); - str.push_back(static_cast( - details::ExtractBits(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& 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& 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& buffer); - -} // namespace cru diff --git a/include/cru/common/io/FileStream.h b/include/cru/common/io/FileStream.h new file mode 100644 index 00000000..4f1499be --- /dev/null +++ b/include/cru/common/io/FileStream.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef CRU_PLATFORM_UNIX +#include "../platform/unix/UnixFileStream.h" +namespace cru::io { +using FileStream = platform::unix::UnixFileStream; +} +#elif CRU_PLATFORM_WINDOWS +#include "../platform/win/Win32FileStream.h" +namespace cru::io { +using FileStream = platform::win::Win32FileStream; +} +#endif diff --git a/include/cru/common/io/FileStream.hpp b/include/cru/common/io/FileStream.hpp deleted file mode 100644 index 86c4c037..00000000 --- a/include/cru/common/io/FileStream.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#ifdef CRU_PLATFORM_UNIX -#include "../platform/unix/UnixFileStream.hpp" -namespace cru::io { -using FileStream = platform::unix::UnixFileStream; -} -#elif CRU_PLATFORM_WINDOWS -#include "../platform/win/Win32FileStream.hpp" -namespace cru::io { -using FileStream = platform::win::Win32FileStream; -} -#endif diff --git a/include/cru/common/io/MemoryStream.h b/include/cru/common/io/MemoryStream.h new file mode 100644 index 00000000..a6243d67 --- /dev/null +++ b/include/cru/common/io/MemoryStream.h @@ -0,0 +1,44 @@ +#pragma once + +#include "Stream.h" + +#include + +namespace cru::io { +class CRU_BASE_API MemoryStream : public Stream { + public: + MemoryStream() = default; + MemoryStream( + std::byte* buffer, Index size, bool read_only = false, + std::function release_func = {}) + : buffer_(buffer), + size_(size), + read_only_(read_only), + release_func_(std::move(release_func)) {} + + CRU_DELETE_COPY(MemoryStream) + CRU_DELETE_MOVE(MemoryStream) + + ~MemoryStream() 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; + + bool CanWrite() override; + Index Write(const std::byte* buffer, Index offset, Index size) override; + + std::byte* GetBuffer() const { return buffer_; } + Index GetSize() override { return size_; } + + private: + std::byte* buffer_ = nullptr; + Index size_ = 0; + Index position_ = 0; + bool read_only_ = false; + std::function release_func_; +}; +} // namespace cru::io diff --git a/include/cru/common/io/MemoryStream.hpp b/include/cru/common/io/MemoryStream.hpp deleted file mode 100644 index 29da7b9f..00000000 --- a/include/cru/common/io/MemoryStream.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "Stream.hpp" - -#include - -namespace cru::io { -class CRU_BASE_API MemoryStream : public Stream { - public: - MemoryStream() = default; - MemoryStream( - std::byte* buffer, Index size, bool read_only = false, - std::function release_func = {}) - : buffer_(buffer), - size_(size), - read_only_(read_only), - release_func_(std::move(release_func)) {} - - CRU_DELETE_COPY(MemoryStream) - CRU_DELETE_MOVE(MemoryStream) - - ~MemoryStream() 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; - - bool CanWrite() override; - Index Write(const std::byte* buffer, Index offset, Index size) override; - - std::byte* GetBuffer() const { return buffer_; } - Index GetSize() override { return size_; } - - private: - std::byte* buffer_ = nullptr; - Index size_ = 0; - Index position_ = 0; - bool read_only_ = false; - std::function release_func_; -}; -} // namespace cru::io diff --git a/include/cru/common/io/OpenFileFlag.h b/include/cru/common/io/OpenFileFlag.h new file mode 100644 index 00000000..b0bceddc --- /dev/null +++ b/include/cru/common/io/OpenFileFlag.h @@ -0,0 +1,18 @@ +#pragma once + +#include "../Bitmask.h" + +namespace cru::io { +namespace details { +struct OpenFileFlagTag {}; +} // namespace details +using OpenFileFlag = Bitmask; + +struct OpenFileFlags { + static constexpr OpenFileFlag Read{0x1}; + static constexpr OpenFileFlag Write{0x2}; + static constexpr OpenFileFlag Append{0x4}; + static constexpr OpenFileFlag Create{0x8}; + static constexpr OpenFileFlag ThrowOnExist{0x10}; +}; +} // namespace cru::io diff --git a/include/cru/common/io/OpenFileFlag.hpp b/include/cru/common/io/OpenFileFlag.hpp deleted file mode 100644 index 3319bb4f..00000000 --- a/include/cru/common/io/OpenFileFlag.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "../Bitmask.hpp" - -namespace cru::io { -namespace details { -struct OpenFileFlagTag {}; -} // namespace details -using OpenFileFlag = Bitmask; - -struct OpenFileFlags { - static constexpr OpenFileFlag Read{0x1}; - static constexpr OpenFileFlag Write{0x2}; - static constexpr OpenFileFlag Append{0x4}; - static constexpr OpenFileFlag Create{0x8}; - static constexpr OpenFileFlag ThrowOnExist{0x10}; -}; -} // namespace cru::io diff --git a/include/cru/common/io/Resource.h b/include/cru/common/io/Resource.h new file mode 100644 index 00000000..1d5313a6 --- /dev/null +++ b/include/cru/common/io/Resource.h @@ -0,0 +1,8 @@ +#pragma once +#include "../Base.h" + +#include + +namespace cru::io { +std::filesystem::path CRU_BASE_API GetResourceDir(); +} diff --git a/include/cru/common/io/Resource.hpp b/include/cru/common/io/Resource.hpp deleted file mode 100644 index 4fd00bdd..00000000 --- a/include/cru/common/io/Resource.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include "../Base.hpp" - -#include - -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 new file mode 100644 index 00000000..66be4468 --- /dev/null +++ b/include/cru/common/io/Stream.h @@ -0,0 +1,48 @@ +#pragma once + +#include "../Base.h" + +#include "../String.h" + +#include +#include + +namespace cru::io { +class CRU_BASE_API Stream : public Object { + public: + enum class SeekOrigin { Current, Begin, End }; + + Stream() = default; + + CRU_DELETE_COPY(Stream) + CRU_DELETE_MOVE(Stream) + + ~Stream() override = default; + + public: + virtual bool CanSeek() = 0; + virtual Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) = 0; + virtual Index Tell(); + virtual void Rewind(); + virtual Index GetSize(); + + virtual bool CanRead() = 0; + virtual Index Read(std::byte* buffer, Index offset, Index size) = 0; + virtual Index Read(std::byte* buffer, Index size); + + virtual bool CanWrite() = 0; + virtual Index Write(const std::byte* buffer, Index offset, Index size) = 0; + virtual Index Write(const std::byte* buffer, Index size); + Index Write(const char* buffer, Index offset, Index size); + Index Write(const char* buffer, Index size); + + virtual std::vector ReadAll(); + + // Utf8 encoding. + String ReadAllAsString(); + + virtual void Flush(); + + virtual void Close(); +}; +} // namespace cru::io diff --git a/include/cru/common/io/Stream.hpp b/include/cru/common/io/Stream.hpp deleted file mode 100644 index 131e82e9..00000000 --- a/include/cru/common/io/Stream.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include "../Base.hpp" - -#include "../String.hpp" - -#include -#include - -namespace cru::io { -class CRU_BASE_API Stream : public Object { - public: - enum class SeekOrigin { Current, Begin, End }; - - Stream() = default; - - CRU_DELETE_COPY(Stream) - CRU_DELETE_MOVE(Stream) - - ~Stream() override = default; - - public: - virtual bool CanSeek() = 0; - virtual Index Seek(Index offset, SeekOrigin origin = SeekOrigin::Current) = 0; - virtual Index Tell(); - virtual void Rewind(); - virtual Index GetSize(); - - virtual bool CanRead() = 0; - virtual Index Read(std::byte* buffer, Index offset, Index size) = 0; - virtual Index Read(std::byte* buffer, Index size); - - virtual bool CanWrite() = 0; - virtual Index Write(const std::byte* buffer, Index offset, Index size) = 0; - virtual Index Write(const std::byte* buffer, Index size); - Index Write(const char* buffer, Index offset, Index size); - Index Write(const char* buffer, Index size); - - virtual std::vector ReadAll(); - - // Utf8 encoding. - String ReadAllAsString(); - - virtual void Flush(); - - virtual void Close(); -}; -} // namespace cru::io diff --git a/include/cru/common/platform/Exception.h b/include/cru/common/platform/Exception.h new file mode 100644 index 00000000..c1b649f3 --- /dev/null +++ b/include/cru/common/platform/Exception.h @@ -0,0 +1,15 @@ +#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_COPY(PlatformException) + CRU_DEFAULT_MOVE(PlatformException) + + CRU_DEFAULT_DESTRUCTOR(PlatformException) +}; +} // namespace cru::platform diff --git a/include/cru/common/platform/Exception.hpp b/include/cru/common/platform/Exception.hpp deleted file mode 100644 index 0241947b..00000000 --- a/include/cru/common/platform/Exception.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "../Base.hpp" -#include "../Exception.hpp" - -namespace cru::platform { -class CRU_BASE_API PlatformException : public Exception { - public: - using Exception::Exception; // inherit constructors - - CRU_DEFAULT_COPY(PlatformException) - CRU_DEFAULT_MOVE(PlatformException) - - 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 new file mode 100644 index 00000000..503576be --- /dev/null +++ b/include/cru/common/platform/osx/Convert.h @@ -0,0 +1,17 @@ +#pragma once +#include "../../PreConfig.h" +#ifdef CRU_PLATFORM_OSX + +#include "../../String.h" + +#include + +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 + +#endif diff --git a/include/cru/common/platform/osx/Convert.hpp b/include/cru/common/platform/osx/Convert.hpp deleted file mode 100644 index a2d8beae..00000000 --- a/include/cru/common/platform/osx/Convert.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "../../PreConfig.hpp" -#ifdef CRU_PLATFORM_OSX - -#include "../../String.hpp" - -#include - -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 - -#endif diff --git a/include/cru/common/platform/osx/Exception.h b/include/cru/common/platform/osx/Exception.h new file mode 100644 index 00000000..53e874e9 --- /dev/null +++ b/include/cru/common/platform/osx/Exception.h @@ -0,0 +1,14 @@ +#pragma once +#include "../../PreConfig.h" +#ifdef CRU_PLATFORM_OSX + +#include "../Exception.h" + +namespace cru::platform::osx { +class OsxException : public PlatformException { + public: + using PlatformException::PlatformException; +}; +} // namespace cru::platform::osx + +#endif diff --git a/include/cru/common/platform/osx/Exception.hpp b/include/cru/common/platform/osx/Exception.hpp deleted file mode 100644 index 49527c69..00000000 --- a/include/cru/common/platform/osx/Exception.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "../../PreConfig.hpp" -#ifdef CRU_PLATFORM_OSX - -#include "../Exception.hpp" - -namespace cru::platform::osx { -class OsxException : public PlatformException { - public: - using PlatformException::PlatformException; -}; -} // namespace cru::platform::osx - -#endif diff --git a/include/cru/common/platform/unix/ErrnoException.h b/include/cru/common/platform/unix/ErrnoException.h new file mode 100644 index 00000000..00e1864b --- /dev/null +++ b/include/cru/common/platform/unix/ErrnoException.h @@ -0,0 +1,28 @@ +#pragma once + +#include "../../PreConfig.h" + +#ifdef CRU_PLATFORM_UNIX + +#include "../Exception.h" + +namespace cru::platform::unix { +class ErrnoException : public PlatformException { + public: + ErrnoException() : ErrnoException(String{}) {} + explicit ErrnoException(const String& message); + ErrnoException(const 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::platform::unix + +#endif diff --git a/include/cru/common/platform/unix/ErrnoException.hpp b/include/cru/common/platform/unix/ErrnoException.hpp deleted file mode 100644 index 2982e26a..00000000 --- a/include/cru/common/platform/unix/ErrnoException.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "../../PreConfig.hpp" - -#ifdef CRU_PLATFORM_UNIX - -#include "../Exception.hpp" - -namespace cru::platform::unix { -class ErrnoException : public PlatformException { - public: - ErrnoException() : ErrnoException(String{}) {} - explicit ErrnoException(const String& message); - ErrnoException(const 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::platform::unix - -#endif diff --git a/include/cru/common/platform/unix/UnixFileStream.h b/include/cru/common/platform/unix/UnixFileStream.h new file mode 100644 index 00000000..0c8ef340 --- /dev/null +++ b/include/cru/common/platform/unix/UnixFileStream.h @@ -0,0 +1,46 @@ +#pragma once + +#include "../../PreConfig.h" + +#ifdef CRU_PLATFORM_UNIX + +#include "../../String.h" +#include "../../io/OpenFileFlag.h" +#include "../../io/Stream.h" + +namespace cru::platform::unix { +class UnixFileStream : public io::Stream { + public: + UnixFileStream(String path, io::OpenFileFlag flags); + + CRU_DELETE_COPY(UnixFileStream) + CRU_DELETE_MOVE(UnixFileStream) + + ~UnixFileStream() 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; + + private: + void CheckClosed(); + + private: + String path_; + io::OpenFileFlag flags_; + int file_descriptor_; + bool closed_ = false; +}; +} // namespace cru::platform::unix + +#endif diff --git a/include/cru/common/platform/unix/UnixFileStream.hpp b/include/cru/common/platform/unix/UnixFileStream.hpp deleted file mode 100644 index 76355f2f..00000000 --- a/include/cru/common/platform/unix/UnixFileStream.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include "../../PreConfig.hpp" - -#ifdef CRU_PLATFORM_UNIX - -#include "../../String.hpp" -#include "../../io/OpenFileFlag.hpp" -#include "../../io/Stream.hpp" - -namespace cru::platform::unix { -class UnixFileStream : public io::Stream { - public: - UnixFileStream(String path, io::OpenFileFlag flags); - - CRU_DELETE_COPY(UnixFileStream) - CRU_DELETE_MOVE(UnixFileStream) - - ~UnixFileStream() 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; - - private: - void CheckClosed(); - - private: - String path_; - io::OpenFileFlag flags_; - int file_descriptor_; - bool closed_ = false; -}; -} // namespace cru::platform::unix - -#endif diff --git a/include/cru/common/platform/win/ComAutoInit.h b/include/cru/common/platform/win/ComAutoInit.h new file mode 100644 index 00000000..cc968e4b --- /dev/null +++ b/include/cru/common/platform/win/ComAutoInit.h @@ -0,0 +1,21 @@ +#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/ComAutoInit.hpp b/include/cru/common/platform/win/ComAutoInit.hpp deleted file mode 100644 index 131f3f30..00000000 --- a/include/cru/common/platform/win/ComAutoInit.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "../../PreConfig.hpp" -#ifdef CRU_PLATFORM_WINDOWS - -#include "WinPreConfig.hpp" -#include "cru/common/Base.hpp" - -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/Exception.h b/include/cru/common/platform/win/Exception.h new file mode 100644 index 00000000..3e63b191 --- /dev/null +++ b/include/cru/common/platform/win/Exception.h @@ -0,0 +1,56 @@ +#pragma once +#include "../../PreConfig.h" +#ifdef CRU_PLATFORM_WINDOWS + +#include "WinPreConfig.h" + +#include "../Exception.h" + +#include +#include + +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/Exception.hpp b/include/cru/common/platform/win/Exception.hpp deleted file mode 100644 index 4e332b4f..00000000 --- a/include/cru/common/platform/win/Exception.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include "../../PreConfig.hpp" -#ifdef CRU_PLATFORM_WINDOWS - -#include "WinPreConfig.hpp" - -#include "../Exception.hpp" - -#include -#include - -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 new file mode 100644 index 00000000..3499604a --- /dev/null +++ b/include/cru/common/platform/win/StreamConvert.h @@ -0,0 +1,14 @@ +#pragma once +#include "../../PreConfig.h" + +#ifdef CRU_PLATFORM_WINDOWS + +#include "../../io/Stream.h" + +#include + +namespace cru::platform::win { +CRU_BASE_API IStream* ConvertStreamToComStream(io::Stream* stream); +} + +#endif diff --git a/include/cru/common/platform/win/StreamConvert.hpp b/include/cru/common/platform/win/StreamConvert.hpp deleted file mode 100644 index 80800115..00000000 --- a/include/cru/common/platform/win/StreamConvert.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include "../../PreConfig.hpp" - -#ifdef CRU_PLATFORM_WINDOWS - -#include "../../io/Stream.hpp" - -#include - -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 new file mode 100644 index 00000000..521fd58d --- /dev/null +++ b/include/cru/common/platform/win/Win32FileStream.h @@ -0,0 +1,54 @@ +#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_; } + + 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/Win32FileStream.hpp b/include/cru/common/platform/win/Win32FileStream.hpp deleted file mode 100644 index b5511ba3..00000000 --- a/include/cru/common/platform/win/Win32FileStream.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "../../PreConfig.hpp" - -#ifdef CRU_PLATFORM_WINDOWS - -#include "../../String.hpp" -#include "../../io/OpenFileFlag.hpp" -#include "../../io/Stream.hpp" - -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_; } - - 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 new file mode 100644 index 00000000..c2284df3 --- /dev/null +++ b/include/cru/common/platform/win/WinPreConfig.h @@ -0,0 +1,13 @@ +#pragma once +#include "../../PreConfig.h" +#ifdef CRU_PLATFORM_WINDOWS + +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN +#include +#undef CreateWindow +#undef DrawText +#undef CreateFont +#undef CreateEvent + +#endif diff --git a/include/cru/common/platform/win/WinPreConfig.hpp b/include/cru/common/platform/win/WinPreConfig.hpp deleted file mode 100644 index ac397820..00000000 --- a/include/cru/common/platform/win/WinPreConfig.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../../PreConfig.hpp" -#ifdef CRU_PLATFORM_WINDOWS - -#define NOMINMAX -#define WIN32_LEAN_AND_MEAN -#include -#undef CreateWindow -#undef DrawText -#undef CreateFont -#undef CreateEvent - -#endif -- cgit v1.2.3