diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj index 8e09898c..c4abc73a 100644 --- a/projects/kiwano/kiwano.vcxproj +++ b/projects/kiwano/kiwano.vcxproj @@ -12,6 +12,7 @@ + @@ -20,10 +21,15 @@ + + + + + @@ -129,6 +135,7 @@ + diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters index d470f726..21b248a6 100644 --- a/projects/kiwano/kiwano.vcxproj.filters +++ b/projects/kiwano/kiwano.vcxproj.filters @@ -300,6 +300,24 @@ platform + + core + + + core + + + core + + + core + + + core + + + core + @@ -512,5 +530,8 @@ platform + + core + \ No newline at end of file diff --git a/src/3rd-party/OuterC/LICENSE b/src/3rd-party/OuterC/LICENSE deleted file mode 100644 index 9e74ea5c..00000000 --- a/src/3rd-party/OuterC/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Nomango - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/src/3rd-party/OuterC/oc/any.h b/src/3rd-party/OuterC/oc/any.h deleted file mode 100644 index fa4594b5..00000000 --- a/src/3rd-party/OuterC/oc/any.h +++ /dev/null @@ -1,511 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include -#include -#include - -namespace oc -{ - -class bad_any_cast : public std::exception -{ -public: - bad_any_cast() {} - - virtual const char* what() const override - { - return "bad any_cast"; - } -}; - - -class any -{ -public: - any() : storage_{} - { - } - - template < - typename _Ty, - typename _Decayed = typename std::decay<_Ty>::type, - typename std::enable_if::value, int>::type = 0 - > - any(_Ty&& val) : storage_{} - { - emplace<_Decayed>(std::forward<_Ty>(val)); - } - - template < - typename _Ty, - typename... _Args - > - any(_Args&&... args) : storage_{} - { - using _Decayed = typename std::decay<_Ty>::type; - - reset(); - emplace_decayed<_Decayed>(std::forward<_Args>(args)...); - } - - any(const any& rhs) : storage_{} - { - copy_from(rhs); - } - - any(any&& rhs) noexcept : storage_{} - { - move_from(std::move(rhs)); - } - - ~any() - { - reset(); - } - - inline const type_info& type() const noexcept - { - const type_info* const info = typeinfo(); - if (info) - { - return *info; - } - return typeid(void); - } - - inline bool has_value() const noexcept - { - return typeinfo() != nullptr; - } - - template < - typename _Ty, - typename... _Args - > - void emplace(_Args&&... args) - { - using _Decayed = typename std::decay<_Ty>::type; - - reset(); - emplace_decayed<_Decayed>(std::forward<_Args>(args)...); - } - - void swap(any& rhs) noexcept - { - any old = static_cast(rhs); - rhs = static_cast(*this); - *this = static_cast(old); - } - - inline void reset() noexcept - { - tidy(); - } - - template - _Ty* cast_pointer() noexcept - { - return const_cast<_Ty*>(const_cast(this)->cast_pointer<_Ty>()); - } - - template - const _Ty* cast_pointer() const noexcept - { - static_assert(!std::is_void<_Ty>::value, "oc::any cannot contain void"); - - const type_info* const info = typeinfo(); - if (info && (*info == typeid(std::decay<_Ty>::type))) - { - if (has_small_type()) - { - return static_cast(small_data()); - } - else - { - return static_cast(big_data()); - } - } - return nullptr; - } - - template - _Ty cast() - { - using _Decayed = typename std::decay<_Ty>::type; - - const auto ptr = cast_pointer<_Decayed>(); - if (!ptr) - { - throw bad_any_cast{}; - } - return static_cast<_Ty>(*ptr); - } - - template - _Ty cast() const - { - using _Decayed = typename std::decay<_Ty>::type; - - const auto ptr = cast_pointer<_Decayed>(); - if (!ptr) - { - throw bad_any_cast{}; - } - return static_cast<_Ty>(*ptr); - } - - any& operator=(const any& rhs) - { - *this = any(rhs); - return (*this); - } - - any& operator=(any&& rhs) noexcept - { - reset(); - move_from(std::move(rhs)); - return (*this); - } - -protected: - const type_info*& typeinfo() - { - return storage_.small_.info_; - } - - const type_info* typeinfo() const - { - return storage_.small_.info_; - } - - template < - typename _Decayed, - typename... _Args - > - inline void emplace_decayed(_Args&&... args) - { - store<_Decayed>(decayed_is_small<_Decayed>{}, std::forward<_Args>(args)...); - } - - template < - typename _Decayed, - typename... _Args - > - void store(std::true_type, _Args&&... args) - { - storage_.is_small_ = true; - typeinfo() = &typeid(_Decayed); - small_rtti() = small_storage_rtti::make<_Decayed>(); - - ::new (small_data()) _Decayed(std::forward<_Args>(args)...); - } - - template < - typename _Decayed, - typename... _Args - > - void store(std::false_type, _Args&&... args) - { - storage_.is_small_ = false; - typeinfo() = &typeid(_Decayed); - big_rtti() = big_storage_rtti::make<_Decayed>(); - - big_data() = ::new _Decayed(std::forward<_Args>(args)...); - } - - void tidy() noexcept - { - if (has_value()) - { - if (has_small_type()) - { - small_rtti().destroy(small_data()); - } - else - { - big_rtti().destroy(big_data()); - big_data() = nullptr; - } - typeinfo() = nullptr; - } - } - - void copy_from(const any& rhs) - { - if (rhs.has_value()) - { - typeinfo() = rhs.typeinfo(); - storage_.is_small_ = rhs.storage_.is_small_; - - if (rhs.has_small_type()) - { - small_rtti() = rhs.small_rtti(); - small_rtti().copy(small_data(), rhs.small_data()); - } - else - { - big_rtti() = rhs.big_rtti(); - big_data() = big_rtti().copy(rhs.big_data()); - } - } - } - - void move_from(any&& rhs) noexcept - { - if (rhs.has_value()) - { - typeinfo() = rhs.typeinfo(); - storage_.is_small_ = rhs.storage_.is_small_; - - if (rhs.has_small_type()) - { - small_rtti() = rhs.small_rtti(); - small_rtti().move(small_data(), rhs.small_data()); - } - else - { - big_rtti() = rhs.big_rtti(); - big_data() = rhs.big_data(); - rhs.typeinfo() = nullptr; - } - } - } - - inline void* small_data() - { - return storage_.small_.buffer_; - } - - inline const void* small_data() const - { - return storage_.small_.buffer_; - } - - inline void*& big_data() - { - return storage_.big_.ptr_; - } - - inline void* big_data() const - { - return storage_.big_.ptr_; - } - - inline bool has_small_type() const - { - return storage_.is_small_; - } - -protected: - static const auto ANY_SMALL_SPACE_SIZE = 8U; - - template - struct decayed_is_small : public std::bool_constant - { - }; - - struct big_storage_rtti - { - using destroy_func = void(void*); - using copy_func = void*(const void*); - - big_storage_rtti() - { - destroy = nullptr; - copy = nullptr; - } - - template - static inline big_storage_rtti make() - { - big_storage_rtti rtti; - rtti.destroy = &big_storage_rtti::destroy_impl<_Ty>; - rtti.copy = &big_storage_rtti::copy_impl<_Ty>; - return rtti; - } - - template - static void destroy_impl(void* const ptr) noexcept - { - ::delete static_cast<_Ty*>(ptr); - } - - template - static void* copy_impl(const void* const ptr) noexcept - { - return ::new _Ty(*static_cast(ptr)); - } - - destroy_func* destroy; - copy_func* copy; - }; - - struct small_storage_rtti - { - using destroy_func = void(void*); - using copy_func = void* (void*, const void*); - using move_func = void*(void*, void*); - - small_storage_rtti() - { - destroy = nullptr; - copy = nullptr; - move = nullptr; - } - - template - static inline small_storage_rtti make() - { - small_storage_rtti rtti; - rtti.destroy = &small_storage_rtti::destroy_impl<_Ty>; - rtti.copy = &small_storage_rtti::copy_impl<_Ty>; - rtti.move = &small_storage_rtti::move_impl<_Ty>; - return rtti; - } - - template - static void destroy_impl(void* const ptr) noexcept - { - if (ptr) - { - _Ty& obj = *(static_cast<_Ty* const>(ptr)); - obj.~_Ty(); - } - } - - template - static void* copy_impl(void* const target, const void* const ptr) noexcept - { - return ::new (static_cast<_Ty*>(target)) _Ty(*static_cast(ptr)); - } - - template - static void* move_impl(void* const target, void* const ptr) noexcept - { - return ::new (static_cast<_Ty*>(target)) _Ty(std::move(*static_cast<_Ty*>(ptr))); - } - - destroy_func* destroy; - copy_func* copy; - move_func* move; - }; - -protected: - inline small_storage_rtti& small_rtti() - { - return storage_.small_.rtti_; - } - - inline const small_storage_rtti& small_rtti() const - { - return storage_.small_.rtti_; - } - - inline big_storage_rtti& big_rtti() - { - return storage_.big_.rtti_; - } - - inline const big_storage_rtti& big_rtti() const - { - return storage_.big_.rtti_; - } - -protected: - struct small_storage - { - const type_info* info_; - small_storage_rtti rtti_; - char buffer_[ANY_SMALL_SPACE_SIZE]; - }; - - struct big_storage - { - const type_info* info_; - big_storage_rtti rtti_; - void* ptr_; - }; - - struct storage - { - bool is_small_; - union - { - small_storage small_; - big_storage big_; - }; - - storage() : is_small_(false), small_() {} // fix error C2280 for VisualStudio 2015 - }; - - storage storage_; -}; - - -// -// any_cast functions -// - -template -_Ty* any_cast(any* const a) noexcept -{ - return a->cast_pointer<_Ty>(); -} - -template -const _Ty* any_cast(const any* const a) noexcept -{ - return a->cast_pointer<_Ty>(); -} - -template -_Ty any_cast(any& a) -{ - using _Decayed = typename std::decay<_Ty>::type; - - const auto ptr = any_cast<_Decayed>(&a); - if (!ptr) - { - throw bad_any_cast{}; - } - return static_cast<_Ty>(*ptr); -} - -template -const _Ty any_cast(const any& a) -{ - using _Decayed = typename std::decay<_Ty>::type; - - const auto ptr = any_cast<_Decayed>(&a); - if (!ptr) - { - throw bad_any_cast{}; - } - return static_cast<_Ty>(*ptr); -} - -template -_Ty any_cast(any&& a) -{ - using _Decayed = typename std::decay<_Ty>::type; - - const auto ptr = any_cast<_Decayed>(&a); - if (!ptr) - { - throw bad_any_cast{}; - } - return static_cast<_Ty>(std::move(*ptr)); -} - -} // namespace oc - -namespace std -{ - -inline void swap(oc::any& lhs, oc::any& rhs) noexcept -{ - lhs.swap(rhs); -} - -} diff --git a/src/3rd-party/OuterC/oc/function.h b/src/3rd-party/OuterC/oc/function.h deleted file mode 100644 index af9cce32..00000000 --- a/src/3rd-party/OuterC/oc/function.h +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include "function/details.h" -#include - -namespace oc -{ - -class bad_function_call : public ::std::exception -{ -public: - bad_function_call() {} - - virtual const char* what() const override - { - return "bad function call"; - } -}; - - -template -class function; - -template -class function<_Ret(_Args...)> -{ -public: - function() - : callable_(nullptr) - { - } - - function(std::nullptr_t) - : callable_(nullptr) - { - } - - function(const function& rhs) - : callable_(rhs.callable_) - { - if (callable_) callable_->retain(); - } - - function(function&& rhs) noexcept - : callable_(rhs.callable_) - { - rhs.callable_ = nullptr; - } - - function(_Ret(*func)(_Args...)) - { - callable_ = __function_detail::proxy_callable<_Ret(*)(_Args...), _Ret, _Args...>::make(::std::move(func)); - if (callable_) callable_->retain(); - } - - template< - typename _Ty, - typename = typename ::std::enable_if<__function_detail::is_callable<_Ty, _Ret, _Args...>::value, int>::type> - function(_Ty val) - { - callable_ = __function_detail::proxy_callable<_Ty, _Ret, _Args...>::make(::std::move(val)); - if (callable_) callable_->retain(); - } - - template::value || ::std::is_base_of<_Ty, _Uty>::value, int>::type> - function(_Uty* ptr, _Ret(_Ty::* func)(_Args...)) - { - callable_ = __function_detail::proxy_mem_callable<_Ty, _Ret, _Args...>::make(ptr, func); - if (callable_) callable_->retain(); - } - - template::value || ::std::is_base_of<_Ty, _Uty>::value, int>::type> - function(_Uty* ptr, _Ret(_Ty::* func)(_Args...) const) - { - callable_ = __function_detail::proxy_const_mem_callable<_Ty, _Ret, _Args...>::make(ptr, func); - if (callable_) callable_->retain(); - } - - ~function() - { - tidy(); - } - - inline void swap(const function& rhs) - { - std::swap(callable_, rhs.callable_); - } - - inline _Ret operator()(_Args... args) const - { - if (!callable_) - throw bad_function_call(); - return callable_->invoke(::std::forward<_Args>(args)...); - } - - inline operator bool() const - { - return !!callable_; - } - - inline function& operator=(const function& rhs) - { - tidy(); - callable_ = rhs.callable_; - if (callable_) callable_->retain(); - return (*this); - } - - inline function& operator=(function&& rhs) - { - tidy(); - callable_ = rhs.callable_; - rhs.callable_ = nullptr; - return (*this); - } - -private: - inline void tidy() - { - if (callable_) - { - callable_->release(); - callable_ = nullptr; - } - } - -private: - __function_detail::callable<_Ret, _Args...>* callable_; -}; - -template::value || std::is_base_of<_Ty, _Uty>::value, int - >::type, - typename _Ret, - typename... _Args -> -inline function<_Ret(_Args...)> closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...)) -{ - return function<_Ret(_Args...)>(ptr, func); -} - -template::value || std::is_base_of<_Ty, _Uty>::value, int - >::type, - typename _Ret, - typename... _Args -> -inline function<_Ret(_Args...)> closure(_Uty* ptr, _Ret(_Ty::* func)(_Args...) const) -{ - return function<_Ret(_Args...)>(ptr, func); -} - - -template -inline void swap(oc::function<_Ret(_Args...)>& lhs, oc::function<_Ret(_Args...)>& rhs) noexcept -{ - lhs.swap(rhs); -} - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/function/details.h b/src/3rd-party/OuterC/oc/function/details.h deleted file mode 100644 index 66813ea6..00000000 --- a/src/3rd-party/OuterC/oc/function/details.h +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include - -namespace oc -{ -namespace __function_detail -{ - -template -struct is_callable_helper -{ - template - struct class_mem; - - template - struct class_const_mem; - - template - static int test(...); - - template - static char test(class_mem<_Uty, &_Uty::operator()>*); - - template - static char test(class_const_mem<_Uty, &_Uty::operator()>*); - - template< - typename _Uty, - typename _Uret = typename std::decay().operator()(std::declval<_Args>()...))>::type, - typename = typename std::enable_if::value>::type - > - static char test(int); - - static constexpr bool value = sizeof(test<_Ty>(0)) == sizeof(char); -}; - -template -struct is_callable - : public ::std::bool_constant::value> -{ -}; - -// -// callable -// - -template -class callable -{ -public: - virtual ~callable() {} - - virtual void retain() = 0; - virtual void release() = 0; - virtual _Ret invoke(_Args... args) const = 0; -}; - -template -class ref_count_callable - : public callable<_Ret, _Args...> -{ -public: - ref_count_callable() : ref_count_(0) {} - - virtual void retain() override - { - ++ref_count_; - } - - virtual void release() override - { - --ref_count_; - if (ref_count_ <= 0) - { - delete this; - } - } - -private: - int ref_count_; -}; - -template -class proxy_callable - : public ref_count_callable<_Ret, _Args...> -{ -public: - proxy_callable(_Ty&& val) - : callee_(::std::move(val)) - { - } - - virtual _Ret invoke(_Args... args) const override - { - return callee_(::std::forward<_Args&&>(args)...); - } - - static inline callable<_Ret, _Args...>* make(_Ty&& val) - { - return new (::std::nothrow) proxy_callable<_Ty, _Ret, _Args...>(::std::move(val)); - } - -private: - _Ty callee_; -}; - -template -class proxy_mem_callable - : public ref_count_callable<_Ret, _Args...> -{ -public: - typedef _Ret(_Ty::* _FuncType)(_Args...); - - virtual _Ret invoke(_Args... args) const override - { - return (ptr_->*func_)(::std::forward<_Args>(args)...); - } - - static inline callable<_Ret, _Args...>* make(_Ty* ptr, _FuncType func) - { - return new (::std::nothrow) proxy_mem_callable<_Ty, _Ret, _Args...>(ptr, func); - } - -protected: - proxy_mem_callable(_Ty* ptr, _FuncType func) - : ptr_(ptr) - , func_(func) - { - } - -protected: - _Ty* ptr_; - _FuncType func_; -}; - -template -class proxy_const_mem_callable - : public ref_count_callable<_Ret, _Args...> -{ -public: - typedef _Ret(_Ty::* _FuncType)(_Args...) const; - - virtual _Ret invoke(_Args... args) const override - { - return (ptr_->*func_)(::std::forward<_Args>(args)...); - } - - static inline callable<_Ret, _Args...>* make(_Ty* ptr, _FuncType func) - { - return new (::std::nothrow) proxy_const_mem_callable<_Ty, _Ret, _Args...>(ptr, func); - } - -protected: - proxy_const_mem_callable(_Ty* ptr, _FuncType func) - : ptr_(ptr) - , func_(func) - { - } - -protected: - _Ty* ptr_; - _FuncType func_; -}; - -} // namespace __function_detail -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/intrusive_list.h b/src/3rd-party/OuterC/oc/intrusive_list.h deleted file mode 100644 index 81c3d8e1..00000000 --- a/src/3rd-party/OuterC/oc/intrusive_list.h +++ /dev/null @@ -1,258 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include -#include -#include -#include "macros.h" - -namespace oc -{ - -template ::pointer> -class intrusive_list; - -template ::pointer> -class intrusive_list_item -{ -public: - using pointer = _PTy; - - intrusive_list_item() : prev_(nullptr), next_(nullptr) {} - intrusive_list_item(pointer rhs) : prev_(nullptr), next_(nullptr) { if (rhs) { prev_ = rhs->prev_; next_ = rhs->next_; } } - - const pointer prev_item() const { return prev_; } - pointer prev_item() { return prev_; } - const pointer next_item() const { return next_; } - pointer next_item() { return next_; } - -private: - pointer prev_; - pointer next_; - - friend class intrusive_list<_Ty, _PTy>; -}; - - -template -class intrusive_list -{ -public: - using value_type = typename std::pointer_traits<_PTy>::element_type; - using pointer = _PTy; - using reference = value_type&; - - intrusive_list() : first_(), last_() {} - ~intrusive_list() { clear(); } - - const pointer first_item() const { return first_; } - pointer first_item() { return first_; } - const pointer last_item() const { return last_; } - pointer last_item() { return last_; } - - inline bool empty() const - { - return first_ == nullptr; - } - - void push_back(pointer child) - { - if (child->prev_) - child->prev_->next_ = child->next_; - if (child->next_) - child->next_->prev_ = child->prev_; - - child->prev_ = last_; - child->next_ = nullptr; - - if (first_) - { - last_->next_ = child; - } - else - { - first_ = child; - } - - last_ = child; - } - - void push_front(pointer child) - { - if (child->prev_) - child->prev_->next_ = child->next_; - if (child->next_) - child->next_->prev_ = child->prev_; - - child->prev_ = nullptr; - child->next_ = first_; - - if (first_) - { - first_->prev_ = child; - } - else - { - last_ = child; - } - - first_ = child; - } - - void insert_before(pointer child, pointer before) - { - if (child->prev_) - child->prev_->next_ = child->next_; - if (child->next_) - child->next_->prev_ = child->prev_; - - if (before->prev_) - before->prev_->next_ = child; - else - first_ = child; - - child->prev_ = before->prev_; - child->next_ = before; - before->prev_ = child; - } - - void insert_after(pointer child, pointer after) - { - if (child->prev_) - child->prev_->next_ = child->next_; - if (child->next_) - child->next_->prev_ = child->prev_; - - if (after->next_) - after->next_->prev_ = child; - else - last_ = child; - - child->next_ = after->next_; - child->prev_ = after; - after->next_ = child; - } - - void remove(pointer child) - { - if (child->next_) - { - child->next_->prev_ = child->prev_; - } - else - { - last_ = child->prev_; - } - - if (child->prev_) - { - child->prev_->next_ = child->next_; - } - else - { - first_ = child->next_; - } - - child->prev_ = nullptr; - child->next_ = nullptr; - } - - void clear() - { - pointer p = first_; - while (p) - { - pointer tmp = p; - p = p->next_; - if (tmp) - { - tmp->next_ = nullptr; - tmp->prev_ = nullptr; - } - } - first_ = nullptr; - last_ = nullptr; - } - - void check_list() - { - if (!first_) - return; - - int pos = 0; - pointer p = first_; - pointer tmp = p; - do - { - tmp = p; - p = p->next_; - ++pos; - - if (p) - { - OC_ASSERT(p->prev_ == tmp && "Check list failed"); - } - else - { - OC_ASSERT(tmp == last_ && "Check list failed"); - } - } while (p); - } - -public: - // Iterator - template - struct iterator_impl - { - using iterator_category = std::bidirectional_iterator_tag; - using value_type = typename std::pointer_traits<_PTy>::element_type; - using difference_type = ptrdiff_t; - using pointer = _PTy; - using reference = value_type&; - - inline iterator_impl(pointer ptr = nullptr, bool is_end = false) : base_(ptr), is_end_(is_end) {} - - inline pointer base() const { OC_ASSERT(!is_end_); return const_cast(base_); } - inline reference operator*() const { OC_ASSERT(base_ && !is_end_); return const_cast(*base_); } - inline pointer operator->() const { OC_ASSERT(base_ && !is_end_); return const_cast(base_); } - inline iterator_impl& operator++() { OC_ASSERT(base_ && !is_end_); pointer next = base_->next_item(); if (next) base_ = next; else is_end_ = true; return (*this); } - inline iterator_impl operator++(int) { iterator_impl old = (*this); ++(*this); return old; } - inline iterator_impl& operator--() { OC_ASSERT(base_); if (is_end_) is_end_ = false; else base_ = pointer(base_->prev_item()); return (*this); } - inline iterator_impl operator--(int) { iterator_impl old = (*this); --(*this); return old; } - inline bool operator==(iterator_impl const& other) const { return base_ == other.base_ && is_end_ == other.is_end_; } - inline bool operator!=(iterator_impl const& other) const { return !(*this == other); } - inline operator bool() const { return base_ != nullptr && !is_end_; } - - private: - bool is_end_; - pointer base_; - }; - - using iterator = iterator_impl; - using const_iterator = iterator_impl; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - inline iterator begin() { return iterator(first_item(), first_item() == nullptr); } - inline const_iterator begin() const { return const_iterator(first_item(), first_item() == nullptr); } - inline const_iterator cbegin() const { return begin(); } - inline iterator end() { return iterator(last_item(), true); } - inline const_iterator end() const { return const_iterator(last_item(), true); } - inline const_iterator cend() const { return end(); } - inline reverse_iterator rbegin() { return reverse_iterator(end()); } - inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - inline const_reverse_iterator crbegin() const { return rbegin(); } - inline reverse_iterator rend() { return reverse_iterator(begin()); } - inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } - inline const_reverse_iterator crend() const { return rend(); } - inline pointer front() { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); } - inline const pointer front() const { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); } - inline pointer back() { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); } - inline const pointer back() const { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); } - -private: - pointer first_; - pointer last_; -}; - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/intrusive_ptr.h b/src/3rd-party/OuterC/oc/intrusive_ptr.h deleted file mode 100644 index e13aef0c..00000000 --- a/src/3rd-party/OuterC/oc/intrusive_ptr.h +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango -// -// Permission is hereby granted, free of charge, to any person obtaining lhs copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#pragma once -#include -#include -#include -#include "macros.h" - -namespace oc -{ - -template -class intrusive_ptr -{ -public: - using value_type = _Ty; - using pointer_type = _Ty*; - using const_pointer_type = const _Ty*; - using reference_type = _Ty&; - using const_reference_type = const _Ty&; - using ref_proxy_type = _ProxyTy; - - intrusive_ptr() noexcept : ptr_(nullptr) {} - intrusive_ptr(std::nullptr_t) noexcept : ptr_(nullptr) {} - intrusive_ptr(pointer_type p) : ptr_(p) { typename ref_proxy_type::add_ref(ptr_); } - intrusive_ptr(const intrusive_ptr& other) : ptr_(other.ptr_) { typename ref_proxy_type::add_ref(ptr_); } - intrusive_ptr(intrusive_ptr&& other) noexcept : ptr_(nullptr) { swap(other); } - ~intrusive_ptr() { tidy(); } - - template - intrusive_ptr(const intrusive_ptr<_UTy, ref_proxy_type>& other) { ptr_ = const_cast(dynamic_cast(other.get())); typename ref_proxy_type::add_ref(ptr_); } - - inline pointer_type get() noexcept { return ptr_; } - inline const_pointer_type get() const noexcept { return ptr_; } - inline void reset(pointer_type ptr = nullptr) { if (ptr) intrusive_ptr(ptr).swap(*this); else tidy(); } - inline void swap(intrusive_ptr& other) noexcept { std::swap(ptr_, other.ptr_); } - - inline pointer_type operator ->() { OC_ASSERT(ptr_ != nullptr && "Invalid pointer"); return ptr_; } - inline const_pointer_type operator ->() const { OC_ASSERT(ptr_ != nullptr && "Invalid pointer"); return ptr_; } - inline reference_type operator *() { OC_ASSERT(ptr_ != nullptr && "Invalid pointer"); return *ptr_; } - inline const_reference_type operator *() const { OC_ASSERT(ptr_ != nullptr && "Invalid pointer"); return *ptr_; } - inline pointer_type* operator &() { OC_ASSERT(ptr_ == nullptr && "Memory leak"); return &ptr_; } - inline operator bool() const noexcept { return ptr_ != nullptr; } - inline bool operator !() const noexcept { return ptr_ == 0; } - - inline intrusive_ptr& operator=(const intrusive_ptr& other) { if (other.ptr_ != ptr_) intrusive_ptr(other).swap(*this); return (*this); } - inline intrusive_ptr& operator=(intrusive_ptr&& other) noexcept { if (other.ptr_ != ptr_) other.swap(*this); return (*this); } - inline intrusive_ptr& operator=(pointer_type p) { if (p != ptr_) intrusive_ptr(p).swap(*this); return (*this); } - inline intrusive_ptr& operator=(std::nullptr_t) { tidy(); return *this; } - -private: - void tidy() - { - typename ref_proxy_type::release(ptr_); - ptr_ = nullptr; - } - -private: - pointer_type ptr_; -}; - -template -inline bool operator==(intrusive_ptr<_Ty, _ProxyTy> const& lhs, intrusive_ptr<_UTy, _ProxyTy> const& rhs) noexcept -{ - return lhs.get() == rhs.get(); -} - -template -inline bool operator==(intrusive_ptr<_Ty, _ProxyTy> const& lhs, _Ty* rhs) noexcept -{ - return lhs.get() == rhs; -} - -template -inline bool operator==(_Ty* lhs, intrusive_ptr<_Ty, _ProxyTy> const& rhs) noexcept -{ - return lhs == rhs.get(); -} - -template -inline bool operator==(intrusive_ptr<_Ty, _ProxyTy> const& lhs, std::nullptr_t) noexcept -{ - return !static_cast(lhs); -} - -template -inline bool operator==(std::nullptr_t, intrusive_ptr<_Ty, _ProxyTy> const& rhs) noexcept -{ - return !static_cast(rhs); -} - -template -inline bool operator!=(intrusive_ptr<_Ty, _ProxyTy> const& lhs, intrusive_ptr<_UTy, _ProxyTy> const& rhs) noexcept -{ - return !(lhs == rhs); -} - -template -inline bool operator!=(intrusive_ptr<_Ty, _ProxyTy> const& lhs, _Ty* rhs) noexcept -{ - return lhs.get() != rhs; -} - -template -inline bool operator!=(_Ty* lhs, intrusive_ptr<_Ty, _ProxyTy> const& rhs) noexcept -{ - return lhs != rhs.get(); -} - -template -inline bool operator!=(intrusive_ptr<_Ty, _ProxyTy> const& lhs, std::nullptr_t) noexcept -{ - return static_cast(lhs); -} - -template -inline bool operator!=(std::nullptr_t, intrusive_ptr<_Ty, _ProxyTy> const& rhs) noexcept -{ - return static_cast(rhs); -} - -template -inline bool operator<(intrusive_ptr<_Ty, _ProxyTy> const& lhs, intrusive_ptr<_UTy, _ProxyTy> const& rhs) noexcept -{ - return lhs.get() < rhs.get(); -} - -// template class cannot specialize std::swap, -// so implement a swap Function in oc namespace -template -inline void swap(intrusive_ptr<_Ty, _ProxyTy>& lhs, intrusive_ptr<_Ty, _ProxyTy>& rhs) noexcept -{ - lhs.swap(rhs); -} - - -class intrusive_ref -{ -public: - void add_ref() - { - ++ref_count_; - } - - void release() - { - --ref_count_; - if (ref_count_ == 0) - { - delete this; - } - } - - int16_t get_ref() const - { - return ref_count_; - } - -protected: - intrusive_ref() - : ref_count_(0) - { - } - -private: - std::atomic ref_count_; -}; - - -class intrusive_ref_proxy -{ -public: - static inline void add_ref(intrusive_ref* ptr) { if (ptr) ptr->add_ref(); } - - static inline void release(intrusive_ref* ptr) { if (ptr) ptr->release(); } -}; - -template< - typename _Ty, - typename = typename std::enable_if::value, int>::type> -using intrusive_ref_ptr = intrusive_ptr<_Ty, intrusive_ref_proxy>; - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json.h b/src/3rd-party/OuterC/oc/json.h deleted file mode 100644 index e61c0d95..00000000 --- a/src/3rd-party/OuterC/oc/json.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include -#include "vector.h" -#include "string.h" -#include "json/basic_json.h" - -namespace oc -{ - -using json = oc::basic_json; -using wjson = oc::basic_json; - -} // namespace oc - -namespace std -{ - -template<> -struct hash<::oc::json> -{ - size_t operator()(const ::oc::json& json) const - { - return hash<::oc::json::string_type>{}(json.dump()); - } -}; - -template<> -struct hash<::oc::wjson> -{ - size_t operator()(const ::oc::wjson& json) const - { - return hash<::oc::wjson::string_type>{}(json.dump()); - } -}; - -template<> -inline void swap<::oc::json>(::oc::json& lhs, ::oc::json& rhs) noexcept -{ - lhs.swap(rhs); -} - -template<> -inline void swap<::oc::wjson>(::oc::wjson& lhs, ::oc::wjson& rhs) noexcept -{ - lhs.swap(rhs); -} - -} diff --git a/src/3rd-party/OuterC/oc/json/basic_json.h b/src/3rd-party/OuterC/oc/json/basic_json.h deleted file mode 100644 index f5a3c5cb..00000000 --- a/src/3rd-party/OuterC/oc/json/basic_json.h +++ /dev/null @@ -1,929 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include "json_exception.h" -#include "json_value.h" -#include "json_iterator.h" -#include "json_serializer.h" -#include "json_parser.h" -#include "json_value_getter.h" - -namespace oc -{ - -#define OC_DECLARE_BASIC_JSON_TEMPLATE\ - template <\ - template typename _ObjectTy, \ - template typename _ArrayTy, \ - typename _StringTy, \ - typename _IntegerTy, \ - typename _FloatTy, \ - typename _BooleanTy, \ - template typename _Allocator> - -#define OC_DECLARE_BASIC_JSON_TPL_ARGS \ - _ObjectTy, _ArrayTy, _StringTy, _IntegerTy, _FloatTy, _BooleanTy, _Allocator - - -OC_DECLARE_BASIC_JSON_TEMPLATE -class basic_json; - - -// -// is_basic_json -// - -template -struct is_basic_json - : std::false_type -{ -}; - -OC_DECLARE_BASIC_JSON_TEMPLATE -struct is_basic_json< basic_json > - : std::true_type -{ -}; - - -OC_DECLARE_BASIC_JSON_TEMPLATE -class basic_json -{ - friend struct __json_detail::iterator_impl; - friend struct __json_detail::iterator_impl; - friend struct __json_detail::json_serializer; - friend struct __json_detail::json_parser; - friend struct __json_detail::json_value_getter; - -public: - template - using allocator_type = _Allocator<_Ty>; - using size_type = size_t; - using difference_type = ptrdiff_t; - using string_type = _StringTy; - using char_type = typename _StringTy::value_type; - using integer_type = _IntegerTy; - using float_type = _FloatTy; - using boolean_type = _BooleanTy; - using array_type = typename _ArrayTy>; - using object_type = typename _ObjectTy, allocator_type>>; - using initializer_list = std::initializer_list; - - using iterator = __json_detail::iterator_impl; - using const_iterator = __json_detail::iterator_impl; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - -public: - basic_json() {} - - basic_json(std::nullptr_t) {} - - basic_json(const json_type type) : value_(type) {} - - basic_json(basic_json const& other) : value_(other.value_) {} - - basic_json(basic_json&& other) noexcept : value_(std::move(other.value_)) - { - // invalidate payload - other.value_.type = json_type::NIL; - other.value_.data.object = nullptr; - } - - basic_json(string_type const& value) : value_(value) {} - - template < - typename _CompatibleTy, - typename std::enable_if::value, int>::type = 0> - basic_json(const _CompatibleTy& value) - { - value_.type = json_type::STRING; - value_.data.string = value_.template create(value); - } - - basic_json(array_type const& arr) - : value_(arr) - { - } - - basic_json(object_type const& object) - : value_(object) - { - } - - basic_json(integer_type value) - : value_(value) - { - } - - template < - typename _IntegerTy, - typename std::enable_if::value, int>::type = 0> - basic_json(_IntegerTy value) - : value_(static_cast(value)) - { - } - - basic_json(float_type value) - : value_(value) - { - } - - template < - typename _FloatingTy, - typename std::enable_if::value, int>::type = 0> - basic_json(_FloatingTy value) - : value_(static_cast(value)) - { - } - - basic_json(boolean_type value) - : value_(value) - { - } - - basic_json(initializer_list const& init_list) - { - bool is_an_object = std::all_of(init_list.begin(), init_list.end(), [](const basic_json& json) - { - return (json.is_array() && json.size() == 2 && json[0].is_string()); - }); - - if (is_an_object) - { - value_ = json_type::OBJECT; - - std::for_each(init_list.begin(), init_list.end(), [this](const basic_json& json) - { - value_.data.object->emplace( - *((*json.value_.data.vector)[0].value_.data.string), - (*json.value_.data.vector)[1] - ); - }); - } - else - { - value_ = json_type::VECTOR; - value_.data.vector->reserve(init_list.size()); - value_.data.vector->assign(init_list.begin(), init_list.end()); - } - } - - static inline basic_json object(initializer_list const& init_list) - { - if (init_list.size() != 2 || !(*init_list.begin()).is_string()) - { - throw json_type_error("cannot create object from initializer_list"); - } - - basic_json json; - json.value_ = json_type::OBJECT; - json.value_.data.object->emplace(*((*init_list.begin()).value_.data.string), *(init_list.begin() + 1)); - return json; - } - - static inline basic_json array(initializer_list const& init_list) - { - basic_json json; - json.value_ = json_type::VECTOR; - - if (init_list.size()) - { - json.value_.data.vector->reserve(init_list.size()); - json.value_.data.vector->assign(init_list.begin(), init_list.end()); - } - return json; - } - - inline bool is_object() const { return value_.type == json_type::OBJECT; } - - inline bool is_array() const { return value_.type == json_type::VECTOR; } - - inline bool is_string() const { return value_.type == json_type::STRING; } - - inline bool is_boolean() const { return value_.type == json_type::BOOL; } - - inline bool is_integer() const { return value_.type == json_type::INTEGER; } - - inline bool is_float() const { return value_.type == json_type::FLOAT; } - - inline bool is_number() const { return is_integer() || is_float(); } - - inline bool is_null() const { return value_.type == json_type::NIL; } - - inline json_type type() const { return value_.type; } - - inline string_type type_name() const - { - switch (type()) - { - case json_type::OBJECT: - return string_type(L"object"); - case json_type::VECTOR: - return string_type(L"array"); - case json_type::STRING: - return string_type(L"string"); - case json_type::INTEGER: - return string_type(L"integer"); - case json_type::FLOAT: - return string_type(L"float"); - case json_type::BOOL: - return string_type(L"boolean"); - case json_type::NIL: - return string_type(L"null"); - } - return string_type(); - } - - inline void swap(basic_json& rhs) { value_.swap(rhs.value_); } - -public: - - inline iterator begin() { iterator iter(this); iter.set_begin(); return iter; } - inline const_iterator begin() const { return cbegin(); } - inline const_iterator cbegin() const { const_iterator iter(this); iter.set_begin(); return iter; } - inline iterator end() { iterator iter(this); iter.set_end(); return iter; } - inline const_iterator end() const { return cend(); } - inline const_iterator cend() const { const_iterator iter(this); iter.set_end(); return iter; } - inline reverse_iterator rbegin() { return reverse_iterator(end()); } - inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - inline const_reverse_iterator crbegin() const { return rbegin(); } - inline reverse_iterator rend() { return reverse_iterator(begin()); } - inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } - inline const_reverse_iterator crend() const { return rend(); } - -public: - inline size_type size() const - { - switch (type()) - { - case json_type::NIL: - return 0; - case json_type::VECTOR: - return value_.data.vector->size(); - case json_type::OBJECT: - return value_.data.object->size(); - default: - return 1; - } - } - - inline bool empty() const - { - if (is_null()) - return true; - - if (is_object()) - return value_.data.object->empty(); - - if (is_array()) - return value_.data.vector->empty(); - - return false; - } - - template - inline const_iterator find(_Kty && key) const - { - if (is_object()) - { - const_iterator iter; - iter.object_iter = value_.data.object->find(std::forward<_Kty>(key)); - return iter; - } - return cend(); - } - - template - inline size_type count(_Kty && key) const - { - return is_object() ? value_.data.object->count(std::forward<_Kty>(key)) : 0; - } - - inline size_type erase(const typename object_type::key_type& key) - { - if (!is_object()) - { - throw json_invalid_key("cannot use erase() with non-object value"); - } - return value_.data.object->erase(key); - } - - inline void erase(const size_type index) - { - if (!is_array()) - { - throw json_invalid_key("cannot use erase() with non-array value"); - } - value_.data.vector->erase(value_.data.vector->begin() + static_cast(index)); - } - - template< - class _IteratorTy, - typename std::enable_if< - std::is_same<_IteratorTy, iterator>::value || - std::is_same<_IteratorTy, const_iterator>::value, int - >::type = 0> - inline _IteratorTy erase(_IteratorTy pos) - { - _IteratorTy result = end(); - - switch (type()) - { - case json_type::OBJECT: - { - result.object_iter = value_.data.object->erase(pos.object_iter); - break; - } - - case json_type::VECTOR: - { - result.array_iter = value_.data.vector->erase(pos.array_iter); - break; - } - - default: - throw json_invalid_iterator("cannot use erase() with non-object & non-array value"); - } - - return result; - } - - template< - class _IteratorTy, - typename std::enable_if< - std::is_same<_IteratorTy, iterator>::value || - std::is_same<_IteratorTy, const_iterator>::value, int - >::type = 0> - inline _IteratorTy erase(_IteratorTy first, _IteratorTy last) - { - _IteratorTy result = end(); - - switch (type()) - { - case json_type::OBJECT: - { - result.object_iter = value_.data.object->erase(first.object_iter, last.object_iter); - break; - } - - case json_type::VECTOR: - { - result.array_iter = value_.data.vector->erase(first.array_iter, last.array_iter); - break; - } - - default: - throw json_invalid_iterator("cannot use erase() with non-object & non-array value"); - } - - return result; - } - - inline void push_back(basic_json&& json) - { - if (!is_null() && !is_array()) - { - throw json_type_error("cannot use push_back() with non-array value"); - } - - if (is_null()) - { - value_ = json_type::VECTOR; - } - - value_.data.vector->push_back(std::move(json)); - } - - inline basic_json& operator+=(basic_json&& json) - { - push_back(std::move(json)); - return (*this); - } - - inline void clear() - { - switch (type()) - { - case json_type::INTEGER: - { - value_.data.number_integer = 0; - break; - } - - case json_type::FLOAT: - { - value_.data.number_float = static_cast(0.0); - break; - } - - case json_type::BOOL: - { - value_.data.boolean = false; - break; - } - - case json_type::STRING: - { - value_.data.string->clear(); - break; - } - - case json_type::VECTOR: - { - value_.data.vector->clear(); - break; - } - - case json_type::OBJECT: - { - value_.data.object->clear(); - break; - } - - default: - break; - } - } - -public: - // GET value functions - - inline bool get_value(boolean_type& val) const - { - if (is_boolean()) - { - val = value_.data.boolean; - return true; - } - return false; - } - - inline bool get_value(integer_type& val) const - { - if (is_integer()) - { - val = value_.data.number_integer; - return true; - } - return false; - } - - inline bool get_value(float_type& val) const - { - if (is_float()) - { - val = value_.data.number_float; - return true; - } - return false; - } - - template < - typename _IntegerTy, - typename std::enable_if::value, int>::type = 0> - inline bool get_value(_IntegerTy& val) const - { - if (is_integer()) - { - val = static_cast<_IntegerTy>(value_.data.number_integer); - return true; - } - return false; - } - - template < - typename _FloatingTy, - typename std::enable_if::value, int>::type = 0> - inline bool get_value(_FloatingTy& val) const - { - if (is_float()) - { - val = static_cast<_FloatingTy>(value_.data.number_float); - return true; - } - return false; - } - - inline bool get_value(array_type& val) const - { - if (is_array()) - { - val.assign((*value_.data.vector).begin(), (*value_.data.vector).end()); - return true; - } - return false; - } - - inline bool get_value(string_type& val) const - { - if (is_string()) - { - val.assign(*value_.data.string); - return true; - } - return false; - } - - inline bool get_value(object_type& val) const - { - if (is_object()) - { - val.assign(*value_.data.object); - return true; - } - return false; - } - - boolean_type as_bool() const - { - if (!is_boolean()) throw json_type_error("json value must be boolean"); - return value_.data.boolean; - } - - integer_type as_int() const - { - if (!is_integer()) throw json_type_error("json value must be integer"); - return value_.data.number_integer; - } - - float_type as_float() const - { - if (!is_float()) throw json_type_error("json value must be float"); - return value_.data.number_float; - } - - const array_type& as_array() const - { - if (!is_array()) throw json_type_error("json value must be array"); - return *value_.data.vector; - } - - const string_type& as_string() const - { - if (!is_string()) throw json_type_error("json value must be string"); - return *value_.data.string; - } - - const object_type& as_object() const - { - if (!is_object()) throw json_type_error("json value must be object"); - return *value_.data.object; - } - - template - _Ty get() const - { - _Ty value; - __json_detail::json_value_getter::assign(*this, value); - return value; - } - -public: - // operator= functions - - inline basic_json& operator=(basic_json const& other) - { - value_ = other.value_; - return (*this); - } - - inline basic_json& operator=(basic_json&& other) noexcept - { - value_ = std::move(other.value_); - return (*this); - } - - inline basic_json& operator=(std::nullptr_t) - { - value_ = nullptr; - return (*this); - } - -public: - // operator[] functions - - inline basic_json& operator[](size_type index) - { - if (is_null()) - { - value_ = json_type::VECTOR; - } - - if (!is_array()) - { - throw json_invalid_key("operator[] called on a non-array object"); - } - - if (index >= value_.data.vector->size()) - { - value_.data.vector->insert(value_.data.vector->end(), - index - value_.data.vector->size() + 1, - basic_json() - ); - } - return (*value_.data.vector)[index]; - } - - inline basic_json& operator[](size_type index) const - { - if (!is_array()) - { - throw json_invalid_key("operator[] called on a non-array type"); - } - - if (index >= value_.data.vector->size()) - { - throw std::out_of_range("operator[] index out of range"); - } - return (*value_.data.vector)[index]; - } - - inline basic_json& operator[](const typename object_type::key_type& key) - { - if (is_null()) - { - value_ = json_type::OBJECT; - } - - if (!is_object()) - { - throw json_invalid_key("operator[] called on a non-object type"); - } - return (*value_.data.object)[key]; - } - - inline basic_json& operator[](const typename object_type::key_type& key) const - { - if (!is_object()) - { - throw json_invalid_key("operator[] called on a non-object object"); - } - - auto iter = value_.data.object->find(key); - if (iter == value_.data.object->end()) - { - throw std::out_of_range("operator[] key out of range"); - } - return iter->second; - } - - template - inline basic_json& operator[](_CharT* key) - { - if (is_null()) - { - value_ = json_type::OBJECT; - } - - if (!is_object()) - { - throw json_invalid_key("operator[] called on a non-object object"); - } - return (*value_.data.object)[key]; - } - - template - inline basic_json& operator[](_CharT* key) const - { - if (!is_object()) - { - throw json_invalid_key("operator[] called on a non-object object"); - } - - auto iter = value_.data.object->find(key); - if (iter == value_.data.object->end()) - { - throw std::out_of_range("operator[] key out of range"); - } - return iter->second; - } - -public: - // implicitly convert functions - - inline operator boolean_type () const - { - return as_bool(); - } - - inline operator integer_type () const - { - return as_int(); - } - - inline operator float_type () const - { - return as_float(); - } - - inline operator const array_type& () const - { - return as_array(); - } - - inline operator const string_type& () const - { - return as_string(); - } - - inline operator const object_type& () const - { - return as_object(); - } - -public: - // dumps functions - - string_type dump( - const int indent = -1, - const char_type indent_char = ' ', - const bool char_escape = true) const - { - string_type result; - __json_detail::string_output_adapter adapter(result); - dump(&adapter, indent, indent_char, char_escape); - return result; - } - - void dump( - __json_detail::output_adapter* adapter, - const int indent = -1, - const char_type indent_char = ' ', - const bool char_escape = true) const - { - __json_detail::json_serializer(adapter, indent_char).dump(*this, (indent >= 0), char_escape, static_cast(indent)); - } - - friend std::basic_ostream& operator<<(std::basic_ostream& out, const basic_json& json) - { - using char_type = typename std::basic_ostream::char_type; - - const bool pretty_print = (out.width() > 0); - const auto indentation = (pretty_print ? out.width() : 0); - out.width(0); - - __json_detail::stream_output_adapter adapter(out); - __json_detail::json_serializer(&adapter, out.fill()).dump(json, pretty_print, true, static_cast(indentation)); - return out; - } - -public: - // parse functions - - static inline basic_json parse(const string_type& str) - { - __json_detail::string_input_adapter adapter(str); - return parse(&adapter); - } - - static inline basic_json parse(const char_type* str) - { - __json_detail::buffer_input_adapter adapter(str); - return parse(&adapter); - } - - static inline basic_json parse(std::FILE* file) - { - __json_detail::file_input_adapter adapter(file); - return parse(&adapter); - } - - static inline basic_json parse(__json_detail::input_adapter* adapter) - { - basic_json result; - __json_detail::json_parser(adapter).parse(result); - return result; - } - - friend std::basic_istream& - operator>>(std::basic_istream& in, basic_json& json) - { - __json_detail::stream_input_adapter adapter(in); - __json_detail::json_parser(&adapter).parse(json); - return in; - } - -public: - // compare functions - - friend bool operator==(const basic_json& lhs, const basic_json& rhs) - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case json_type::VECTOR: - return (*lhs.value_.data.vector == *rhs.value_.data.vector); - - case json_type::OBJECT: - return (*lhs.value_.data.object == *rhs.value_.data.object); - - case json_type::NIL: - return true; - - case json_type::STRING: - return (*lhs.value_.data.string == *rhs.value_.data.string); - - case json_type::BOOL: - return (lhs.value_.data.boolean == rhs.value_.data.boolean); - - case json_type::INTEGER: - return (lhs.value_.data.number_integer == rhs.value_.data.number_integer); - - case json_type::FLOAT: - return (lhs.value_.data.number_float == rhs.value_.data.number_float); - - default: - return false; - } - } - else if (lhs_type == json_type::INTEGER && rhs_type == json_type::FLOAT) - { - return (static_cast(lhs.value_.data.number_integer) == rhs.value_.data.number_float); - } - else if (lhs_type == json_type::FLOAT && rhs_type == json_type::INTEGER) - { - return (lhs.value_.data.number_float == static_cast(rhs.value_.data.number_integer)); - } - - return false; - } - - friend bool operator!=(const basic_json& lhs, const basic_json& rhs) - { - return !(lhs == rhs); - } - - friend bool operator<(const basic_json& lhs, const basic_json& rhs) - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case json_type::VECTOR: - return (*lhs.value_.data.vector) < (*rhs.value_.data.vector); - - case json_type::OBJECT: - return (*lhs.value_.data.object) < (*rhs.value_.data.object); - - case json_type::NIL: - return false; - - case json_type::STRING: - return (*lhs.value_.data.string) < (*rhs.value_.data.string); - - case json_type::BOOL: - return (lhs.value_.data.boolean < rhs.value_.data.boolean); - - case json_type::INTEGER: - return (lhs.value_.data.number_integer < rhs.value_.data.number_integer); - - case json_type::FLOAT: - return (lhs.value_.data.number_float < rhs.value_.data.number_float); - - default: - return false; - } - } - else if (lhs_type == json_type::INTEGER && rhs_type == json_type::FLOAT) - { - return (static_cast(lhs.value_.data.number_integer) < rhs.value_.data.number_float); - } - else if (lhs_type == json_type::FLOAT && rhs_type == json_type::INTEGER) - { - return (lhs.value_.data.number_float < static_cast(rhs.value_.data.number_integer)); - } - - return false; - } - - friend bool operator<=(const basic_json& lhs, const basic_json& rhs) - { - return !(rhs < lhs); - } - - friend bool operator>(const basic_json& lhs, const basic_json& rhs) - { - return rhs < lhs; - } - - friend bool operator>=(const basic_json& lhs, const basic_json& rhs) - { - return !(lhs < rhs); - } - -private: - __json_detail::json_value value_; -}; - -} // namespace oc - -#undef OC_DECLARE_BASIC_JSON_TEMPLATE -#undef OC_DECLARE_BASIC_JSON_TPL_ARGS diff --git a/src/3rd-party/OuterC/oc/json/json_exception.h b/src/3rd-party/OuterC/oc/json/json_exception.h deleted file mode 100644 index 0bf579e9..00000000 --- a/src/3rd-party/OuterC/oc/json/json_exception.h +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include -#include "json_value.h" - -namespace oc -{ - -class json_exception - : public std::runtime_error -{ -public: - json_exception(const char* message) - : std::runtime_error(message) - {} -}; - -class json_type_error - : public json_exception -{ -public: - json_type_error(const char* message) : json_exception(message) {} -}; - -class json_invalid_key - : public json_exception -{ -public: - json_invalid_key(const char* message) : json_exception(message) {} -}; - -class json_invalid_iterator - : public json_exception -{ -public: - json_invalid_iterator(const char* message) : json_exception(message) {} -}; - -class json_parse_error - : public json_exception -{ -public: - json_parse_error(const char* message) : json_exception(message) {} -}; - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_intput_adapter.h b/src/3rd-party/OuterC/oc/json/json_intput_adapter.h deleted file mode 100644 index 5fdba4af..00000000 --- a/src/3rd-party/OuterC/oc/json/json_intput_adapter.h +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include - -namespace oc -{ -namespace __json_detail -{ - -template -struct input_adapter -{ - using char_type = _CharTy; - using char_traits = std::char_traits; - - virtual typename char_traits::int_type get_char() = 0; - virtual ~input_adapter() = default; -}; - -template -struct file_input_adapter - : public input_adapter<_CharTy> -{ - using char_type = typename input_adapter<_CharTy>::char_type; - using char_traits = typename input_adapter<_CharTy>::char_traits; - - file_input_adapter(std::FILE* file) : file(file) {} - - virtual typename char_traits::int_type get_char() override - { - return std::fgetc(file); - } - -private: - std::FILE* file; -}; - -template -struct stream_input_adapter - : public input_adapter<_CharTy> -{ - using char_type = typename input_adapter<_CharTy>::char_type; - using char_traits = typename input_adapter<_CharTy>::char_traits; - - stream_input_adapter(std::basic_istream& stream) : stream(stream), streambuf(*stream.rdbuf()) {} - - virtual typename char_traits::int_type get_char() override - { - auto ch = streambuf.sbumpc(); - if (ch == EOF) - { - stream.clear(stream.rdstate() | std::ios::eofbit); - } - return ch; - } - - virtual ~stream_input_adapter() - { - stream.clear(stream.rdstate() & std::ios::eofbit); - } - -private: - std::basic_istream& stream; - std::basic_streambuf& streambuf; -}; - -template -struct string_input_adapter - : public input_adapter -{ - using char_type = typename input_adapter::char_type; - using char_traits = typename input_adapter::char_traits; - - string_input_adapter(const _StringTy& str) : str(str), index(0) {} - - virtual typename char_traits::int_type get_char() override - { - if (index == str.size()) - return char_traits::eof(); - return str[index++]; - } - -private: - const _StringTy& str; - typename _StringTy::size_type index; -}; - -template -struct buffer_input_adapter - : public input_adapter<_CharTy> -{ - using char_type = typename input_adapter<_CharTy>::char_type; - using char_traits = typename input_adapter<_CharTy>::char_traits; - - buffer_input_adapter(const _CharTy* str) : str(str), index(0) {} - - virtual typename char_traits::int_type get_char() override - { - if (str[index] == '\0') - return char_traits::eof(); - return str[index++]; - } - -private: - const char_type* str; - uint32_t index; -}; - -} // namespace __json_detail - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_iterator.h b/src/3rd-party/OuterC/oc/json/json_iterator.h deleted file mode 100644 index 2520860b..00000000 --- a/src/3rd-party/OuterC/oc/json/json_iterator.h +++ /dev/null @@ -1,377 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include - -namespace oc -{ -namespace __json_detail -{ - -struct primitive_iterator -{ - using difference_type = ptrdiff_t; - - inline primitive_iterator(difference_type it = 0) : it_(it) {} - - inline void set_begin() { it_ = 0; } - inline void set_end() { it_ = 1; } - - inline primitive_iterator& operator++() { ++it_; return *this; } - - inline primitive_iterator operator++(int) { primitive_iterator old(it_); ++(*this); return old; } - - inline primitive_iterator& operator--() { --it_; return (*this); } - inline primitive_iterator operator--(int) { primitive_iterator old = (*this); --(*this); return old; } - - inline bool operator==(primitive_iterator const& other) const { return it_ == other.it_; } - inline bool operator!=(primitive_iterator const& other) const { return !(*this == other); } - - inline const primitive_iterator operator+(difference_type off) const { return primitive_iterator(it_ + off); } - inline const primitive_iterator operator-(difference_type off) const { return primitive_iterator(it_ - off); } - - inline primitive_iterator& operator+=(difference_type off) { it_ += off; return (*this); } - inline primitive_iterator& operator-=(difference_type off) { it_ -= off; return (*this); } - - inline difference_type operator-(primitive_iterator const& other) const { return it_ - other.it_; } - - inline bool operator<(primitive_iterator const& other) const { return it_ < other.it_; } - inline bool operator<=(primitive_iterator const& other) const { return it_ <= other.it_; } - inline bool operator>(primitive_iterator const& other) const { return it_ > other.it_; } - inline bool operator>=(primitive_iterator const& other) const { return it_ >= other.it_; } - -private: - difference_type it_; -}; - -template -struct iterator_impl -{ - friend _BasicJsonTy; - - using string_type = typename _BasicJsonTy::string_type; - using char_type = typename _BasicJsonTy::char_type; - using integer_type = typename _BasicJsonTy::integer_type; - using float_type = typename _BasicJsonTy::float_type; - using boolean_type = typename _BasicJsonTy::boolean_type; - using array_type = typename _BasicJsonTy::array_type; - using object_type = typename _BasicJsonTy::object_type; - - using value_type = _BasicJsonTy; - using difference_type = ptrdiff_t; - using iterator_category = std::bidirectional_iterator_tag; - using pointer = value_type*; - using reference = value_type&; - - using array_iterator = typename _BasicJsonTy::array_type::iterator; - using object_iterator = typename _BasicJsonTy::object_type::iterator; - - inline iterator_impl(pointer json = nullptr) : data_(json), primitive_iter(0), array_iter(), object_iter() {} - - inline iterator_impl(const iterator_impl& rhs) : iterator_impl() - { - operator=(rhs); - } - - ~iterator_impl() {} - - inline iterator_impl& operator=(const iterator_impl& rhs) - { - data_ = rhs.data_; - if (data_) - { - switch (data_->type()) - { - case json_type::OBJECT: - object_iter = rhs.object_iter; - break; - case json_type::VECTOR: - array_iter = rhs.array_iter; - break; - default: - primitive_iter = rhs.primitive_iter; - break; - } - } - return (*this); - } - - inline reference operator*() const - { - check_data(); - check_iterator(); - switch (data_->type()) - { - case json_type::OBJECT: - return (object_iter->second); - case json_type::VECTOR: - return (*array_iter); - default: - return *data_; - } - } - - inline pointer operator->() const - { - check_data(); - check_iterator(); - switch (data_->type()) - { - case json_type::OBJECT: - return &(object_iter->second); - case json_type::VECTOR: - return &(*array_iter); - default: - return data_; - } - } - - inline const typename object_type::key_type& key() const - { - check_data(); - check_iterator(); - if (!data_->is_object()) - throw json_invalid_iterator("cannot use key() with non-object type"); - return object_iter->first; - } - - inline reference value() const - { - return operator*(); - } - - inline void set_begin() - { - check_data(); - - switch (data_->type()) - { - case json_type::OBJECT: - { - object_iter = data_->value_.data.object->begin(); - break; - } - case json_type::VECTOR: - { - array_iter = data_->value_.data.vector->begin(); - break; - } - default: - { - primitive_iter.set_begin(); - break; - } - } - } - - inline void set_end() - { - check_data(); - - switch (data_->type()) - { - case json_type::OBJECT: - { - object_iter = data_->value_.data.object->end(); - break; - } - case json_type::VECTOR: - { - array_iter = data_->value_.data.vector->end(); - break; - } - default: - { - primitive_iter.set_end(); - break; - } - } - } - - inline iterator_impl operator++(int) { iterator_impl old = (*this); ++(*this); return old; } - inline iterator_impl& operator++() - { - check_data(); - - switch (data_->type()) - { - case json_type::OBJECT: - { - std::advance(object_iter, 1); - break; - } - case json_type::VECTOR: - { - std::advance(array_iter, 1); - break; - } - default: - { - ++primitive_iter; - break; - } - } - return *this; - } - - inline iterator_impl operator--(int) { iterator_impl old = (*this); --(*this); return old; } - inline iterator_impl& operator--() - { - check_data(); - - switch (data_->type()) - { - case json_type::OBJECT: - { - std::advance(object_iter, -1); - break; - } - case json_type::VECTOR: - { - std::advance(array_iter, -1); - break; - } - default: - { - --primitive_iter; - break; - } - } - } - - inline const iterator_impl operator-(difference_type off) const { return operator+(-off); } - inline const iterator_impl operator+(difference_type off) const { iterator_impl ret(*this); ret += off; return ret; } - - inline iterator_impl& operator-=(difference_type off) { return operator+=(-off); } - inline iterator_impl& operator+=(difference_type off) - { - check_data(); - - switch (data_->type()) - { - case json_type::OBJECT: - { - throw json_invalid_iterator("cannot use offsets with object type"); - break; - } - case json_type::VECTOR: - { - std::advance(array_iter, off); - break; - } - default: - { - primitive_iter += off; - break; - } - } - return *this; - } - - inline bool operator!=(iterator_impl const& other) const { return !(*this == other); } - inline bool operator==(iterator_impl const& other) const - { - check_data(); - other.check_data(); - - if (data_ != other.data_) - throw json_invalid_iterator("cannot compare iterators of different objects"); - - switch (data_->type()) - { - case json_type::OBJECT: - { - return object_iter == other.object_iter; - } - case json_type::VECTOR: - { - return array_iter == other.array_iter; - } - default: - { - return primitive_iter == other.primitive_iter; - } - } - } - - inline bool operator>(iterator_impl const& other) const { return other.operator<(*this); } - inline bool operator>=(iterator_impl const& other) const { return !operator<(other); } - inline bool operator<=(iterator_impl const& other) const { return !other.operator<(*this); } - inline bool operator<(iterator_impl const& other) const - { - check_data(); - other.check_data(); - - if (data_ != other.data_) - throw json_invalid_iterator("cannot compare iterators of different objects"); - - switch (data_->type()) - { - case json_type::OBJECT: - throw json_invalid_iterator("cannot compare iterators with object type"); - case json_type::VECTOR: - return array_iter < other.array_iter; - default: - return primitive_iter < other.primitive_iter; - } - } - -private: - inline void check_data() const - { - if (data_ == nullptr) - { - throw json_invalid_iterator("iterator contains an empty object"); - } - } - - inline void check_iterator() const - { - switch (data_->type()) - { - case json_type::OBJECT: - if (object_iter == data_->value_.data.object->end()) - { - throw std::out_of_range("iterator out of range"); - } - break; - case json_type::VECTOR: - if (array_iter == data_->value_.data.vector->end()) - { - throw std::out_of_range("iterator out of range"); - } - break; - default: - if (primitive_iter == 1) - { - throw std::out_of_range("iterator out of range"); - } - break; - } - } - -private: - pointer data_; - - union - { - struct - { - array_iterator array_iter; - }; - - struct - { - object_iterator object_iter; - }; - - struct - { - primitive_iterator primitive_iter; // for other types - }; - }; -}; - -} // namespace __json_detail - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_output_adapter.h b/src/3rd-party/OuterC/oc/json/json_output_adapter.h deleted file mode 100644 index 8c0d2adb..00000000 --- a/src/3rd-party/OuterC/oc/json/json_output_adapter.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include - -namespace oc -{ -namespace __json_detail -{ - -template -struct output_adapter -{ - using char_type = _CharTy; - using char_traits = std::char_traits; - - virtual void write(const _CharTy ch) = 0; - virtual void write(const _CharTy* str, uint32_t size) = 0; - virtual void write(const _CharTy* str) - { - const auto size = char_traits::length(str); - write(str, static_cast(size)); - } -}; - -template -struct string_output_adapter - : public output_adapter -{ - using char_type = typename _StringTy::value_type; - using size_type = typename _StringTy::size_type; - using char_traits = std::char_traits; - - string_output_adapter(_StringTy& str) : str_(str) {} - - virtual void write(const char_type ch) override - { - str_.push_back(ch); - } - - virtual void write(const char_type* str, uint32_t size) override - { - str_.append(str, static_cast(size)); - } - -private: - _StringTy& str_; -}; - -template -struct stream_output_adapter - : public output_adapter<_CharTy> -{ - using char_type = _CharTy; - using size_type = typename std::streamsize; - using char_traits = std::char_traits; - - stream_output_adapter(std::basic_ostream& stream) : stream_(stream) {} - - virtual void write(const char_type ch) override - { - stream_.put(ch); - } - - virtual void write(const char_type* str, uint32_t size) override - { - stream_.write(str, static_cast(size)); - } - -private: - std::basic_ostream& stream_; -}; - -} // namespace __json_detail - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_parser.h b/src/3rd-party/OuterC/oc/json/json_parser.h deleted file mode 100644 index 0732f517..00000000 --- a/src/3rd-party/OuterC/oc/json/json_parser.h +++ /dev/null @@ -1,567 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include "json_intput_adapter.h" - -namespace oc -{ -namespace __json_detail -{ - -enum class token_type -{ - UNINITIALIZED, - - LITERAL_TRUE, - LITERAL_FALSE, - LITERAL_NULL, - - VALUE_STRING, - VALUE_INTEGER, - VALUE_FLOAT, - - BEGIN_ARRAY, - END_ARRAY, - - BEGIN_OBJECT, - END_OBJECT, - - NAME_SEPARATOR, - VALUE_SEPARATOR, - - PARSE_ERROR, - - END_OF_INPUT -}; - -template -struct json_lexer -{ - using string_type = typename _BasicJsonTy::string_type; - using char_type = typename _BasicJsonTy::char_type; - using integer_type = typename _BasicJsonTy::integer_type; - using float_type = typename _BasicJsonTy::float_type; - using boolean_type = typename _BasicJsonTy::boolean_type; - using array_type = typename _BasicJsonTy::array_type; - using object_type = typename _BasicJsonTy::object_type; - using char_traits = std::char_traits; - - json_lexer(input_adapter* adapter) : adapter(adapter) - { - // read first char - read_next(); - } - - typename char_traits::int_type read_next() - { - current = adapter->get_char(); - return current; - } - - void skip_spaces() - { - while (current == ' ' || current == '\t' || current == '\n' || current == '\r') - { - read_next(); - } - } - - token_type scan() - { - skip_spaces(); - - token_type result = token_type::UNINITIALIZED; - switch (current) - { - case '[': - result = token_type::BEGIN_ARRAY; - break; - case ']': - result = token_type::END_ARRAY; - break; - case '{': - result = token_type::BEGIN_OBJECT; - break; - case '}': - result = token_type::END_OBJECT; - break; - case ':': - result = token_type::NAME_SEPARATOR; - break; - case ',': - result = token_type::VALUE_SEPARATOR; - break; - - case 't': - return scan_literal("true", token_type::LITERAL_TRUE); - case 'f': - return scan_literal("false", token_type::LITERAL_FALSE); - case 'n': - return scan_literal("null", token_type::LITERAL_NULL); - - case '\"': - return scan_string(); - - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return scan_number(); - - case '\0': - case char_traits::eof(): - return token_type::END_OF_INPUT; - - // unexpected char - default: - return token_type::PARSE_ERROR; - } - - // skip current char - read_next(); - - return result; - } - - token_type scan_literal(const char_type* text, token_type result) - { - for (uint32_t i = 0; text[i] != '\0'; ++i) - { - if (text[i] != char_traits::to_char_type(current)) - { - return token_type::PARSE_ERROR; - } - read_next(); - } - return result; - } - - token_type scan_string() - { - if (current != '\"') - return token_type::PARSE_ERROR; - - string_buffer.clear(); - - while (true) - { - const auto ch = read_next(); - switch (ch) - { - case char_traits::eof(): - { - // unexpected end - return token_type::PARSE_ERROR; - } - - case '\"': - { - // skip last `\"` - read_next(); - return token_type::VALUE_STRING; - } - - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1A: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x1E: - case 0x1F: - { - // invalid control character - return token_type::PARSE_ERROR; - } - - case '\\': - { - switch (read_next()) - { - case '\"': - string_buffer.push_back('\"'); - break; - case '\\': - string_buffer.push_back('\\'); - break; - case '/': - string_buffer.push_back('/'); - break; - case 'b': - string_buffer.push_back('\b'); - break; - case 'f': - string_buffer.push_back('\f'); - break; - case 'n': - string_buffer.push_back('\n'); - break; - case 'r': - string_buffer.push_back('\r'); - break; - case 't': - string_buffer.push_back('\t'); - break; - - case 'u': - { - // unicode escapes - uint16_t byte = 0; - - for (const auto factor : { 12, 8, 4, 0 }) - { - const auto n = read_next(); - if (n >= L'0' && n <= L'9') - { - byte += ((n - L'0') << factor); - } - else if (n >= L'A' && n <= L'F') - { - byte += ((n - L'A' + 10) << factor); - } - else if (n >= L'a' && n <= L'f') - { - byte += ((n - L'a' + 10) << factor); - } - else - { - // '\u' must be followed by 4 hex digits - return token_type::PARSE_ERROR; - } - } - - string_buffer.push_back(char_traits::to_char_type(byte)); - break; - } - - default: - { - return token_type::PARSE_ERROR; - } - } - break; - } - - default: - { - if (ch > 0x1F && ch < 0x7F) - { - string_buffer.push_back(char_traits::to_char_type(ch)); - break; - } - else - { - return token_type::PARSE_ERROR; - } - } - - } - } - } - - token_type scan_number() - { - is_negative = false; - number_value = static_cast(0.0); - - if (current == '-') - { - return scan_negative(); - } - - if (current == '0') - { - return scan_zero(); - } - - return scan_integer(); - } - - token_type scan_negative() - { - if (current == '-') - { - is_negative = true; - read_next(); - - return scan_integer(); - } - return token_type::PARSE_ERROR; - } - - token_type scan_zero() - { - if (current == '0') - { - if (read_next() == '.') - return scan_float(); - else - return token_type::VALUE_INTEGER; - } - return token_type::PARSE_ERROR; - } - - token_type scan_integer() - { - if (std::isdigit(current)) - { - number_value = static_cast(current - '0'); - - while (true) - { - const auto ch = read_next(); - if (ch == '.') - return scan_float(); - - if (ch == 'e' || ch == 'E') - return scan_exponent(); - - if (std::isdigit(ch)) - number_value = number_value * 10 + (ch - '0'); - else - break; - } - return token_type::VALUE_INTEGER; - } - return token_type::PARSE_ERROR; - } - - token_type scan_float() - { - if (current != '.') - return token_type::PARSE_ERROR; - - if (std::isdigit(read_next())) - { - float_type fraction = static_cast(0.1); - number_value += static_cast(current - '0') * fraction; - - while (true) - { - const auto ch = read_next(); - if (ch == 'e' || ch == 'E') - return scan_exponent(); - - if (std::isdigit(ch)) - { - fraction *= static_cast(0.1); - number_value += static_cast(ch - '0') * fraction; - } - else - break; - } - return token_type::VALUE_FLOAT; - } - return token_type::PARSE_ERROR; - } - - token_type scan_exponent() - { - if (current != 'e' && current != 'E') - return token_type::PARSE_ERROR; - - // skip current char - read_next(); - - if ((std::isdigit(current) && current != '0') || (current == '-') || (current == '+')) - { - float_type core = 10; - if (current == '+') - { - read_next(); - } - else if (current == '-') - { - core = static_cast(0.1); - read_next(); - } - - uint32_t exponent = static_cast(current - '0'); - while (std::isdigit(read_next())) - { - exponent = (exponent * 10) + static_cast(current - '0'); - } - - float_type power = 1; - for (; exponent; exponent >>= 1, core *= core) - if (exponent & 1) - power *= core; - - number_value *= power; - return token_type::VALUE_FLOAT; - } - return token_type::PARSE_ERROR; - } - - integer_type token_to_integer() const - { - integer_type integer = static_cast(number_value); - return is_negative ? -integer : integer; - } - - float_type token_to_float() const - { - return is_negative ? -number_value : number_value; - } - - string_type token_to_string() const - { - return string_buffer; - } - -private: - input_adapter* adapter; - typename char_traits::int_type current; - - bool is_negative; - float_type number_value; - string_type string_buffer; -}; - - -template -struct json_parser -{ - using string_type = typename _BasicJsonTy::string_type; - using char_type = typename _BasicJsonTy::char_type; - using integer_type = typename _BasicJsonTy::integer_type; - using float_type = typename _BasicJsonTy::float_type; - using boolean_type = typename _BasicJsonTy::boolean_type; - using array_type = typename _BasicJsonTy::array_type; - using object_type = typename _BasicJsonTy::object_type; - using char_traits = std::char_traits; - - json_parser(input_adapter* adapter) - : lexer(adapter) - , last_token(token_type::UNINITIALIZED) - {} - - void parse(_BasicJsonTy& json) - { - parse_value(json); - - if (get_token() != token_type::END_OF_INPUT) - throw json_parse_error("unexpected token, expect end"); - } - -private: - token_type get_token() - { - last_token = lexer.scan(); - return last_token; - } - - void parse_value(_BasicJsonTy& json) - { - switch (get_token()) - { - case token_type::LITERAL_TRUE: - json = json_type::BOOL; - json.value_.data.boolean = true; - break; - - case token_type::LITERAL_FALSE: - json = json_type::BOOL; - json.value_.data.boolean = false; - break; - - case token_type::LITERAL_NULL: - json = json_type::NIL; - break; - - case token_type::VALUE_STRING: - json = lexer.token_to_string(); - break; - - case token_type::VALUE_INTEGER: - json = lexer.token_to_integer(); - break; - - case token_type::VALUE_FLOAT: - json = lexer.token_to_float(); - break; - - case token_type::BEGIN_ARRAY: - json = json_type::VECTOR; - while (true) - { - json.value_.data.vector->push_back(_BasicJsonTy()); - parse_value(json.value_.data.vector->back()); - - // read ',' - if (get_token() != token_type::VALUE_SEPARATOR) - break; - } - if (last_token != token_type::END_ARRAY) - throw json_parse_error("unexpected token in array"); - break; - - case token_type::BEGIN_OBJECT: - json = json_type::OBJECT; - while (true) - { - if (get_token() != token_type::VALUE_STRING) - break; - string_type key = lexer.token_to_string(); - - if (get_token() != token_type::NAME_SEPARATOR) - break; - - _BasicJsonTy object; - parse_value(object); - json.value_.data.object->insert(std::make_pair(key, object)); - - // read ',' - if (get_token() != token_type::VALUE_SEPARATOR) - break; - } - if (last_token != token_type::END_OBJECT) - throw json_parse_error("unexpected token in object"); - break; - - default: - // unexpected token - throw json_parse_error("unexpected token"); - break; - } - } - -private: - json_lexer<_BasicJsonTy> lexer; - token_type last_token; -}; - -} // namespace __json_detail - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_serializer.h b/src/3rd-party/OuterC/oc/json/json_serializer.h deleted file mode 100644 index 68e120d1..00000000 --- a/src/3rd-party/OuterC/oc/json/json_serializer.h +++ /dev/null @@ -1,421 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include "json_output_adapter.h" -#include -#include - -namespace oc -{ - -namespace __json_detail -{ - -template -struct json_literaler -{ - using char_type = _CharTy; - using string_type = const char_type*; - - static inline string_type value_separator() { return ",\n"; } - - static inline string_type empty_object() { return "{}"; } - static inline string_type object_begin() { return "{\n"; } - static inline string_type object_key_begin() { return "\": "; } - - static inline string_type empty_array() { return "[]"; } - static inline string_type array_begin() { return "[\n"; } - - static inline string_type literal_true() { return "true"; } - static inline string_type literal_false() { return "false"; } - static inline string_type literal_null() { return "null"; } - - static inline string_type escape_t() { return "\\t"; } - static inline string_type escape_r() { return "\\r"; } - static inline string_type escape_n() { return "\\n"; } - static inline string_type escape_b() { return "\\b"; } - static inline string_type escape_f() { return "\\f"; } - static inline string_type escape_quote() { return "\\\""; } - static inline string_type escape_slash() { return "\\\\"; } - - template - static inline void sprint_float(char_type* buff, const _FloatTy value) - { - const auto digits = std::numeric_limits<_FloatTy>::max_digits10; - const auto len = ::_scprintf("%.*g", digits, value); - if (len) - { - buff[0] = '\0'; - ::sprintf_s(buff, size_t(len) + 1, "%.*g", digits, value); - } - else - { - buff[0] = '0'; - buff[1] = '.'; - buff[2] = '0'; - buff[3] = '\0'; - } - } -}; - -template <> -struct json_literaler -{ - using char_type = wchar_t; - using string_type = const char_type*; - - static inline string_type value_separator() { return L",\n"; } - - static inline string_type empty_object() { return L"{}"; } - static inline string_type object_begin() { return L"{\n"; } - static inline string_type object_key_begin() { return L"\":"; } - - static inline string_type empty_array() { return L"[]"; } - static inline string_type array_begin() { return L"[\n"; } - - static inline string_type literal_true() { return L"true"; } - static inline string_type literal_false() { return L"false"; } - static inline string_type literal_null() { return L"null"; } - - static inline string_type escape_t() { return L"\\t"; } - static inline string_type escape_r() { return L"\\r"; } - static inline string_type escape_n() { return L"\\n"; } - static inline string_type escape_b() { return L"\\b"; } - static inline string_type escape_f() { return L"\\f"; } - static inline string_type escape_quote() { return L"\\\""; } - static inline string_type escape_slash() { return L"\\\\"; } - - template - static inline void sprint_float(char_type* buff, const _FloatTy value) - { - const auto digits = std::numeric_limits<_FloatTy>::max_digits10; - const auto len = ::_scwprintf(L"%.*g", digits, value); - if (len) - { - buff[0] = '\0'; - ::swprintf_s(buff, size_t(len) + 1, L"%.*g", digits, value); - } - else - { - buff[0] = '0'; - buff[1] = '.'; - buff[2] = '0'; - buff[3] = '\0'; - } - } -}; - -template -struct json_serializer -{ - using string_type = typename _BasicJsonTy::string_type; - using char_type = typename _BasicJsonTy::char_type; - using integer_type = typename _BasicJsonTy::integer_type; - using float_type = typename _BasicJsonTy::float_type; - using boolean_type = typename _BasicJsonTy::boolean_type; - using array_type = typename _BasicJsonTy::array_type; - using object_type = typename _BasicJsonTy::object_type; - using literaler = json_literaler; - - json_serializer(output_adapter* out, const char_type indent_char) - : out(out) - , indent_char(indent_char) - , indent_string(32, indent_char) - {} - - void dump( - const _BasicJsonTy& json, - const bool pretty_print, - const bool char_escape, - const uint32_t indent_step, - const uint32_t current_indent = 0) - { - switch (json.type()) - { - case json_type::OBJECT: - { - auto& object = *json.value_.data.object; - - if (object.empty()) - { - out->write(literaler::empty_object()); - return; - } - - if (pretty_print) - { - out->write(literaler::object_begin()); - - const auto new_indent = current_indent + indent_step; - if (indent_string.size() < new_indent) - { - indent_string.resize(indent_string.size() * 2, indent_char); - } - - auto iter = object.cbegin(); - const auto size = object.size(); - for (uint32_t i = 0; i < size; ++i, ++iter) - { - out->write(indent_string.c_str(), new_indent); - out->write('\"'); - out->write(iter->first.c_str()); - out->write(literaler::object_key_begin()); - out->write(' '); - dump(iter->second, pretty_print, char_escape, indent_step, new_indent); - - // not last element - if (i != size - 1) - out->write(literaler::value_separator()); - } - - out->write('\n'); - out->write(indent_string.c_str(), current_indent); - out->write('}'); - } - else - { - out->write('{'); - - auto iter = object.cbegin(); - const auto size = object.size(); - for (uint32_t i = 0; i < size; ++i, ++iter) - { - out->write('\"'); - out->write(iter->first.c_str()); - out->write(literaler::object_key_begin()); - dump(iter->second, pretty_print, char_escape, indent_step, current_indent); - - // not last element - if (i != size - 1) - out->write(','); - } - - out->write('}'); - } - - return; - } - - case json_type::VECTOR: - { - auto& vector = *json.value_.data.vector; - - if (vector.empty()) - { - out->write(literaler::empty_array()); - return; - } - - if (pretty_print) - { - out->write(literaler::array_begin()); - - const auto new_indent = current_indent + indent_step; - if (indent_string.size() < new_indent) - { - indent_string.resize(indent_string.size() * 2, indent_char); - } - - auto iter = vector.cbegin(); - const auto size = vector.size(); - for (uint32_t i = 0; i < size; ++i, ++iter) - { - out->write(indent_string.c_str(), new_indent); - dump(*iter, pretty_print, char_escape, indent_step, new_indent); - - // not last element - if (i != size - 1) - out->write(literaler::value_separator()); - } - - out->write('\n'); - out->write(indent_string.c_str(), current_indent); - out->write(']'); - } - else - { - out->write('['); - - auto iter = vector.cbegin(); - const auto size = vector.size(); - for (uint32_t i = 0; i < size; ++i, ++iter) - { - dump(*iter, pretty_print, char_escape, indent_step, current_indent); - // not last element - if (i != size - 1) - out->write(','); - } - - out->write(']'); - } - - return; - } - - case json_type::STRING: - { - out->write('\"'); - dump_string(*json.value_.data.string, char_escape); - out->write('\"'); - return; - } - - case json_type::BOOL: - { - if (json.value_.data.boolean) - { - out->write(literaler::literal_true()); - } - else - { - out->write(literaler::literal_false()); - } - return; - } - - case json_type::INTEGER: - { - dump_integer(json.value_.data.number_integer); - return; - } - - case json_type::FLOAT: - { - dump_float(json.value_.data.number_float); - return; - } - - case json_type::NIL: - { - out->write(literaler::literal_null()); - return; - } - } - } - - void dump_integer(integer_type val) - { - if (val == 0) - { - out->write('0'); - return; - } - - auto uval = static_cast>(val); - - if (val < 0) - uval = 0 - uval; - - if (number_buffer == nullptr) - number_buffer.reset(new number_buffer_type); - - auto next = (*number_buffer).rbegin(); - *next = '\0'; - - do - { - *(++next) = static_cast('0' + uval % 10); - uval /= 10; - } while (uval != 0); - - if (val < 0) - *(++next) = '-'; - - out->write(&(*next)); - } - - void dump_float(float_type val) - { - if (number_buffer == nullptr) - number_buffer.reset(new number_buffer_type); - - literaler::sprint_float((*number_buffer).data(), val); - out->write((*number_buffer).data()); - } - - void dump_string(const string_type & val, const bool char_escape) - { - for (const auto& ch : val) - { - switch (ch) - { - case '\t': - { - out->write(literaler::escape_t()); - break; - } - - case '\r': - { - out->write(literaler::escape_r()); - break; - } - - case '\n': - { - out->write(literaler::escape_n()); - break; - } - - case '\b': - { - out->write(literaler::escape_b()); - break; - } - - case '\f': - { - out->write(literaler::escape_f()); - break; - } - - case '\"': - { - out->write(literaler::escape_quote()); - break; - } - - case '\\': - { - out->write(literaler::escape_slash()); - break; - } - - default: - { - uint32_t char_byte = static_cast(ch); - if (char_byte > 0x1F && (!char_escape || char_byte < 0x7F)) - { - out->write(ch); - } - else - { - char_type escaped[7] = { '\\', 'u', 0 }; - - uint8_t index = 2; - for (const auto factor : { 12, 8, 4, 0 }) - { - char_type code = ((char_byte >> factor) & 0x0F); - code += (code < 0x0A) ? '0' : 'a' - 0x0A; - escaped[index++] = code; - } - out->write(escaped); - } - break; - } - } - } - } - -private: - output_adapter* out; - char_type indent_char; - string_type indent_string; - - using number_buffer_type = std::array; - std::unique_ptr number_buffer; -}; - -} // namespace __json_detail - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_value.h b/src/3rd-party/OuterC/oc/json/json_value.h deleted file mode 100644 index 94f5ba0f..00000000 --- a/src/3rd-party/OuterC/oc/json/json_value.h +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include -#include - -namespace oc -{ - -enum class json_type -{ - INTEGER, - FLOAT, - STRING, - VECTOR, - OBJECT, - BOOL, - NIL, -}; - -namespace __json_detail -{ - -template -struct json_value -{ - using string_type = typename _BasicJsonTy::string_type; - using char_type = typename _BasicJsonTy::char_type; - using integer_type = typename _BasicJsonTy::integer_type; - using float_type = typename _BasicJsonTy::float_type; - using boolean_type = typename _BasicJsonTy::boolean_type; - using array_type = typename _BasicJsonTy::array_type; - using object_type = typename _BasicJsonTy::object_type; - - json_type type; - union - { - object_type* object; - array_type* vector; - string_type* string; - integer_type number_integer; - float_type number_float; - boolean_type boolean; - } data; - - json_value() - { - type = json_type::NIL; - data.object = nullptr; - } - - json_value(std::nullptr_t) - { - type = json_type::NIL; - data.object = nullptr; - } - - json_value(const object_type& value) - { - type = json_type::OBJECT; - data.object = create(value); - } - - json_value(const array_type& value) - { - type = json_type::VECTOR; - data.vector = create(value); - } - - json_value(const string_type& value) - { - type = json_type::STRING; - data.string = create(value); - } - - template - json_value(const _CharT* str) - { - type = json_type::STRING; - data.string = create(str); - } - - json_value(const integer_type value) - { - type = json_type::INTEGER; - data.number_integer = value; - } - - json_value(const float_type value) - { - type = json_type::FLOAT; - data.number_float = value; - } - - json_value(const boolean_type value) - { - type = json_type::BOOL; - data.boolean = value; - } - - json_value(const json_type value_type) - { - type = value_type; - switch (type) - { - case json_type::OBJECT: - data.object = create(); - break; - case json_type::VECTOR: - data.vector = create(); - break; - case json_type::STRING: - data.string = create(); - break; - case json_type::INTEGER: - data.number_integer = integer_type(0); - break; - case json_type::FLOAT: - data.number_float = float_type(0.0); - break; - case json_type::BOOL: - data.boolean = boolean_type(false); - break; - default: - data.object = nullptr; - break; - } - } - - json_value(json_value const& other) - { - type = other.type; - - switch (other.type) - { - case json_type::OBJECT: - data.object = create(*other.data.object); - break; - case json_type::VECTOR: - data.vector = create(*other.data.vector); - break; - case json_type::STRING: - data.string = create(*other.data.string); - break; - case json_type::INTEGER: - data.number_integer = other.data.number_integer; - break; - case json_type::FLOAT: - data.number_float = other.data.number_float; - break; - case json_type::BOOL: - data.boolean = other.data.boolean; - break; - default: - data.object = nullptr; - break; - } - } - - json_value(json_value&& other) noexcept - { - type = other.type; - data = other.data; - other.type = json_type::NIL; - other.data.object = nullptr; - } - - ~json_value() - { - clear(); - } - - void swap(json_value& other) - { - std::swap(type, other.type); - std::swap(data, other.data); - } - - void clear() - { - switch (type) - { - case json_type::OBJECT: - destroy(data.object); - break; - case json_type::VECTOR: - destroy(data.vector); - break; - case json_type::STRING: - destroy(data.string); - break; - default: - break; - } - } - - template - inline _Ty* create(_Args&&... args) - { - using allocator_type = typename _BasicJsonTy::template allocator_type<_Ty>; - using allocator_traits = std::allocator_traits; - - allocator_type allocator; - _Ty* ptr = allocator_traits::allocate(allocator, 1); - allocator_traits::construct(allocator, ptr, std::forward<_Args>(args)...); - return ptr; - } - - template - inline void destroy(_Ty* ptr) - { - using allocator_type = typename _BasicJsonTy::template allocator_type<_Ty>; - using allocator_traits = std::allocator_traits; - - allocator_type allocator; - allocator_traits::destroy(allocator, ptr); - allocator_traits::deallocate(allocator, ptr, 1); - } - - inline json_value& operator=(json_value const& other) - { - json_value{ other }.swap(*this); - return (*this); - } - - inline json_value& operator=(json_value&& other) noexcept - { - clear(); - type = other.type; - data = std::move(other.data); - // invalidate payload - other.type = json_type::NIL; - other.data.object = nullptr; - return (*this); - } -}; - -} // namespace __json_detail - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/json/json_value_getter.h b/src/3rd-party/OuterC/oc/json/json_value_getter.h deleted file mode 100644 index 220deb27..00000000 --- a/src/3rd-party/OuterC/oc/json/json_value_getter.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include "json_value.h" - -namespace oc -{ -namespace __json_detail -{ - -template -struct json_value_getter -{ - using string_type = typename _BasicJsonTy::string_type; - using char_type = typename _BasicJsonTy::char_type; - using integer_type = typename _BasicJsonTy::integer_type; - using float_type = typename _BasicJsonTy::float_type; - using boolean_type = typename _BasicJsonTy::boolean_type; - using array_type = typename _BasicJsonTy::array_type; - using object_type = typename _BasicJsonTy::object_type; - - static inline void assign(const _BasicJsonTy& json, object_type& value) - { - if (!json.is_object()) throw json_type_error("json value type must be object"); - value = *json.value_.data.object; - } - - static inline void assign(const _BasicJsonTy& json, array_type& value) - { - if (!json.is_array()) throw json_type_error("json value type must be array"); - value = *json.value_.data.vector; - } - - static inline void assign(const _BasicJsonTy& json, string_type& value) - { - if (!json.is_string()) throw json_type_error("json value type must be string"); - value = *json.value_.data.string; - } - - static inline void assign(const _BasicJsonTy& json, boolean_type& value) - { - if (!json.is_boolean()) throw json_type_error("json value type must be boolean"); - value = json.value_.data.boolean; - } - - static inline void assign(const _BasicJsonTy& json, integer_type& value) - { - if (!json.is_integer()) throw json_type_error("json value type must be integer"); - value = json.value_.data.number_integer; - } - - template < - typename _IntegerTy, - typename std::enable_if::value, int>::type = 0> - static inline void assign(const _BasicJsonTy& json, _IntegerTy& value) - { - if (!json.is_integer()) throw json_type_error("json value type must be integer"); - value = static_cast<_IntegerTy>(json.value_.data.number_integer); - } - - static inline void assign(const _BasicJsonTy& json, float_type& value) - { - if (!json.is_float()) throw json_type_error("json value type must be float"); - value = json.value_.data.number_float; - } - - template < - typename _FloatingTy, - typename std::enable_if::value, int>::type = 0> - static inline void assign(const _BasicJsonTy& json, _FloatingTy& value) - { - if (!json.is_float()) throw json_type_error("json value type must be float"); - value = static_cast<_FloatingTy>(json.value_.data.number_float); - } -}; - -} // namespace __json_detail - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/macros.h b/src/3rd-party/OuterC/oc/macros.h deleted file mode 100644 index c85a8d7b..00000000 --- a/src/3rd-party/OuterC/oc/macros.h +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include -#include -#include - -#define OC_ASSERT(EXPR) assert(EXPR) diff --git a/src/3rd-party/OuterC/oc/noncopyable.h b/src/3rd-party/OuterC/oc/noncopyable.h deleted file mode 100644 index 76725522..00000000 --- a/src/3rd-party/OuterC/oc/noncopyable.h +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once - -namespace oc -{ - -class noncopyable -{ -protected: - noncopyable() = default; - -private: - noncopyable(const noncopyable&) = delete; - - noncopyable& operator=(const noncopyable&) = delete; -}; - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/oc.h b/src/3rd-party/OuterC/oc/oc.h deleted file mode 100644 index 5171e999..00000000 --- a/src/3rd-party/OuterC/oc/oc.h +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include "macros.h" -#include "vector.h" -#include "string.h" -#include "any.h" -#include "function.h" -#include "noncopyable.h" -#include "singleton.h" -#include "intrusive_ptr.h" -#include "intrusive_list.h" -#include "json.h" diff --git a/src/3rd-party/OuterC/oc/singleton.h b/src/3rd-party/OuterC/oc/singleton.h deleted file mode 100644 index 44726bb6..00000000 --- a/src/3rd-party/OuterC/oc/singleton.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once - -// Class that will implement the singleton mode must use the macro in its delare file - -#ifndef OC_DECLARE_SINGLETON -#define OC_DECLARE_SINGLETON( CLASS ) \ - friend ::oc::singleton< CLASS >; -#endif - -namespace oc -{ - -template -struct singleton -{ -protected: - singleton() = default; - singleton(const singleton&) = delete; - singleton& operator=(const singleton&) = delete; - -private: - struct object_creator - { - object_creator() - { - (void)singleton<_Ty>::instance(); - } - - inline void dummy() const {} - }; - static object_creator creator_; - -public: - using object_type = _Ty; - - static inline object_type& instance() - { - static object_type instance; - creator_.dummy(); - return instance; - } -}; - -template -typename singleton<_Ty>::object_creator singleton<_Ty>::creator_; - - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/string.h b/src/3rd-party/OuterC/oc/string.h deleted file mode 100644 index 0fc944d4..00000000 --- a/src/3rd-party/OuterC/oc/string.h +++ /dev/null @@ -1,1741 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include -#include -#include -#include -#include -#include -#include - -namespace oc -{ - -// -// basic_string<> -// Lightweight std::basic_string<>-like class -// When using basic_string<> with a c-style string (char* or wchar_t*), constructor and operator=() just hold -// a pointer to the character array but don't copy its content, considering performance issues. -// Use assign() and basic_string<>::cstr() to work fine with c-style strings. -// -template -class basic_string -{ -private: - // Iterator - template - struct iterator_impl - { - using iterator_category = typename std::iterator_traits<_Ty*>::iterator_category; - using value_type = typename std::iterator_traits<_Ty*>::value_type; - using difference_type = typename std::iterator_traits<_Ty*>::difference_type; - using pointer = typename std::iterator_traits<_Ty*>::pointer; - using reference = typename std::iterator_traits<_Ty*>::reference; - - // disable warning 4996 - using _Unchecked_type = _Ty; - - inline iterator_impl(pointer core = nullptr) : base_(core) {} - - inline reference operator*() const { return *base_; } - inline pointer core() const { return base_; } - - inline iterator_impl& operator++() { ++base_; return (*this); } - inline iterator_impl operator++(int) { iterator_impl old = (*this); ++(*this); return old; } - - inline iterator_impl& operator--() { --base_; return (*this); } - inline iterator_impl operator--(int) { iterator_impl old = (*this); --(*this); return old; } - - inline const iterator_impl operator+(difference_type off) const { return iterator_impl(base_ + off); } - inline const iterator_impl operator-(difference_type off) const { return iterator_impl(base_ - off); } - - inline iterator_impl& operator+=(difference_type off) { base_ += off; return (*this); } - inline iterator_impl& operator-=(difference_type off) { base_ -= off; return (*this); } - - inline difference_type operator-(iterator_impl const& other) const { return base_ - other.base_; } - - inline bool operator==(iterator_impl const& other) const { return base_ == other.base_; } - inline bool operator!=(iterator_impl const& other) const { return !(*this == other); } - - inline bool operator<(iterator_impl const& other) const { return base_ < other.base_; } - inline bool operator<=(iterator_impl const& other) const { return base_ <= other.base_; } - inline bool operator>(iterator_impl const& other) const { return base_ > other.base_; } - inline bool operator>=(iterator_impl const& other) const { return base_ >= other.base_; } - - inline reference operator[](difference_type off) { return *(base_ + off); } - inline const reference operator[](difference_type off) const { return *(base_ + off); } - - inline operator bool() const { return base_ != nullptr; } - - private: - pointer base_{ nullptr }; - }; - -public: - using value_type = _CharTy; - using char_type = value_type; - using size_type = size_t; - using reference = value_type &; - using const_reference = const value_type &; - using iterator = iterator_impl; - using const_iterator = iterator_impl; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - using traits_type = std::char_traits; - using allocator_type = std::allocator; - - basic_string(); - basic_string(const char_type* cstr, bool const_str = true); - basic_string(const char_type* cstr, size_type count); - basic_string(size_type count, char_type ch); - basic_string(std::basic_string const& str); - basic_string(basic_string const& rhs); - basic_string(basic_string const& rhs, size_type pos, size_type count = npos); - basic_string(basic_string && rhs) noexcept; - ~basic_string(); - - template - basic_string(_Iter first, _Iter last) : basic_string() { assign_iter(first, last); } - - inline const char_type* c_str() const { return empty() ? empty_cstr : const_str_; } - inline const char_type* data() const { return empty() ? empty_cstr : const_str_; } - inline char_type at(size_type i) const { return (*this)[i]; } - inline size_type size() const { return size_; } - inline size_type length() const { return size(); } - inline size_type capacity() const { return capacity_; } - inline size_type max_size() const { return (static_cast(-1) / sizeof(value_type)); } - inline bool empty() const { return size_ == 0; } - inline void clear() { discard_const_data(); if (str_) { str_[0] = value_type(); } size_ = 0; } - - void reserve(const size_type new_cap = 0); - inline void resize(const size_type new_size, const char_type ch = value_type()) { check_operability(); if (new_size < size_) str_[size_ = new_size] = value_type(); else append(new_size - size_, ch); } - - int compare(const char_type* const str) const; - inline int compare(basic_string const& str) const { return compare(str.c_str()); } - - basic_string& append(size_type count, char_type ch); - basic_string& append(const char_type* cstr, size_type count); - basic_string& append(basic_string const& other, size_type pos, size_type count = npos); - inline basic_string& append(const char_type* cstr) { return append(cstr, traits_type::length(cstr)); } - inline basic_string& append(basic_string const& other) { return append(other.const_str_, 0, npos); } - inline basic_string& append(std::basic_string const& other) { return append(other.c_str()); } - - size_type find(const char_type ch, size_type offset = 0) const; - size_type find(const char_type* const str, size_type offset, size_type count) const; - inline size_type find(basic_string const& str, size_type offset = 0) const { return find(str.c_str(), offset, str.size()); } - inline size_type find(const char_type* const str, size_type offset = 0) const { return find(str, offset, traits_type::length(str)); } - - size_type find_first_of(const char_type* const str, size_type offset, size_type count) const; - inline size_type find_first_of(const char_type ch, size_type offset = 0) const { return find(ch, offset); } - inline size_type find_first_of(basic_string const& str, size_type offset = 0) const { return find_first_of(str.c_str(), offset, str.size()); } - inline size_type find_first_of(const char_type* const str, size_type offset = 0) const { return find_first_of(str, offset, traits_type::length(str)); } - - size_type find_last_of(const char_type ch, size_type pos = npos) const; - size_type find_last_of(const char_type* const str, size_type pos, size_type count) const; - inline size_type find_last_of(basic_string const& str, size_type pos = npos) const { return find_first_of(str.c_str(), pos, str.size()); } - inline size_type find_last_of(const char_type* const str, size_type pos = npos) const { return find_first_of(str, pos, traits_type::length(str)); } - - basic_string& replace(size_type pos, size_type count, const char_type* cstr, size_type count2); - basic_string& replace(size_type pos, size_type count, size_type count2, const char_type ch); - inline basic_string& replace(size_type pos, size_type count, const basic_string& str) { return replace(pos, count, str.c_str(), str.size()); } - inline basic_string& replace(size_type pos, size_type count, const char_type* cstr) { return replace(pos, count, cstr, traits_type::length(cstr)); } - inline basic_string& replace(const_iterator first, const_iterator last, const basic_string& str) { return replace(first, last, str.c_str(), str.size()); } - inline basic_string& replace(const_iterator first, const_iterator last, const char_type* cstr) { return replace(first, last, cstr, traits_type::length(cstr)); } - inline basic_string& replace(const_iterator first, const_iterator last, const char_type* cstr, size_type count) { return replace(first - cbegin(), last - first, cstr, count); } - inline basic_string& replace(const_iterator first, const_iterator last, size_type count2, const char_type ch) { return replace(first - cbegin(), last - first, count2, ch); } - - basic_string& assign(size_type count, const char_type ch); - basic_string& assign(const char_type* cstr, size_type count); - inline basic_string& assign(const char_type* cstr) { basic_string(cstr, false).swap(*this); return *this; } - inline basic_string& assign(basic_string const& rhs) { basic_string{ rhs }.swap(*this); return *this; } - inline basic_string& assign(std::basic_string const& rhs) { basic_string{ rhs }.swap(*this); return *this; } - basic_string& assign(basic_string const& rhs, size_type pos, size_type count = npos); - - template - inline basic_string& assign(_Iter first, _Iter last) { assign_iter(first, last); return(*this); } - - basic_string& erase(size_type offset = 0, size_type count = npos); - iterator erase(const const_iterator where) { size_type off = where - cbegin(); erase(off, 1); return begin().core() + off; } - iterator erase(const const_iterator first, const const_iterator last) { size_type off = first - cbegin(); erase(first - cbegin(), last - first); return begin().core() + off; } - - basic_string substr(size_type pos = 0, size_type count = npos) const { return basic_string(*this, pos, count); } - - basic_string& insert(size_type index, size_type count, char_type ch); - basic_string& insert(size_type index, const char_type* s, size_type count); - basic_string& insert(size_type index, const basic_string& str, size_type off, size_type count = npos); - inline basic_string& insert(size_type index, const char_type* s) { return insert(index, s, traits_type::length(s)); } - inline basic_string& insert(size_type index, const basic_string& str) { return insert(index, str, 0, str.size()); } - inline iterator insert(const_iterator pos, size_type count, char_type ch) { size_type off = pos - cbegin(); insert(off, count, ch); return begin().core() + off; } - inline iterator insert(const_iterator pos, char_type ch) { return insert(pos, 1, ch); } - - inline void push_back(const char_type ch) { append(1, ch); } - inline char_type pop_back() { if (empty()) throw std::out_of_range("pop_back() called on empty string"); check_operability(); char_type ch = str_[--size_]; str_[size_] = value_type(); return ch; } - - size_type copy(char_type* cstr, size_type count, size_type pos = 0) const; - - void swap(basic_string& rhs) noexcept; - size_type hash() const; - -public: - static basic_string parse(int val); - static basic_string parse(unsigned int val); - static basic_string parse(long val); - static basic_string parse(unsigned long val); - static basic_string parse(long long val); - static basic_string parse(unsigned long long val); - static basic_string parse(float val); - static basic_string parse(double val); - static basic_string parse(long double val); - - template - static basic_string format(const char_type* fmt, _Args&&... args); - - static inline basic_string cstr(const char_type* cstr) { return basic_string(cstr, false); } - -public: - inline iterator begin() { check_operability(); return iterator(str_); } - inline const_iterator begin() const { return const_iterator(const_str_); } - inline const_iterator cbegin() const { return begin(); } - inline iterator end() { check_operability(); return iterator(str_ + size_); } - inline const_iterator end() const { return const_iterator(const_str_ + size_); } - inline const_iterator cend() const { return end(); } - inline reverse_iterator rbegin() { check_operability(); return reverse_iterator(end()); } - inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - inline const_reverse_iterator crbegin() const { return rbegin(); } - inline reverse_iterator rend() { check_operability(); return reverse_iterator(begin()); } - inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } - inline const_reverse_iterator crend() const { return rend(); } - inline reference front() { if (empty()) throw std::out_of_range("front() called on empty string"); check_operability(); return str_[0]; } - inline const_reference front() const { if (empty()) throw std::out_of_range("front() called on empty string"); return const_str_[0]; } - inline reference back() { if (empty()) throw std::out_of_range("back() called on empty string"); check_operability(); return str_[size_ - 1]; } - inline const_reference back() const { if (empty()) throw std::out_of_range("back() called on empty string"); return const_str_[size_ - 1]; } - -public: - inline char_type operator[](size_type off) const { if (off >= size_) throw std::out_of_range("string subscript out of range"); return const_str_[off]; } - inline char_type& operator[](size_type off) { if (off >= size_) throw std::out_of_range("string subscript out of range"); check_operability(); return str_[off]; } - -public: - inline const basic_string operator+(const char_type ch) const { return basic_string{ *this }.append(1, ch); } - inline const basic_string operator+(const char_type* cstr) const { return basic_string{ *this }.append(cstr); } - inline const basic_string operator+(basic_string const& rhs) const { return basic_string{ *this }.append(rhs); } - - inline basic_string& operator+=(const char_type ch) { return append(1, ch); } - inline basic_string& operator+=(const char_type* cstr) { return append(cstr); } - inline basic_string& operator+=(basic_string const& rhs) { return append(rhs); } - -public: - inline basic_string& operator=(const char_type* cstr) { if (const_str_ != cstr) basic_string{ cstr }.swap(*this); return *this; } - inline basic_string& operator=(std::basic_string const& rhs) { basic_string{ rhs }.swap(*this); return *this; } - inline basic_string& operator=(basic_string const& rhs) { if (this != &rhs) basic_string{ rhs }.swap(*this); return *this; } - inline basic_string& operator=(basic_string && rhs) noexcept { if (this != &rhs) basic_string{ rhs }.swap(*this); return *this; } - -public: - static const size_type npos; - static const char_type empty_cstr[1]; - - static inline allocator_type& get_allocator() - { - static allocator_type allocator_; - return allocator_; - } - -private: - char_type* allocate(size_type count); - void deallocate(char_type*& ptr, size_type count); - - void destroy(); - - void discard_const_data(); - void check_operability(); - void check_offset(size_type offset) const { if (offset > size()) throw std::out_of_range("invalid string position"); } - size_type clamp_suffix_size(size_type off, size_type count) const { return std::min(size() - off, count); } - - template - void assign_iter(_Iter first, _Iter last) - { - size_type diff = static_cast(std::distance(first, last)); - if (diff == 0) - return; - - discard_const_data(); - if (diff > capacity_) - { - destroy(); - str_ = allocate(diff + 1); - capacity_ = diff; - } - size_ = diff; - - for (size_type index = 0; first != last; ++first, ++index) - { - traits_type::assign(str_[index], traits_type::to_char_type(*first)); - } - traits_type::assign(str_[size_], value_type()); - } - -private: - union - { - struct - { - value_type* str_; - }; - - struct - { - const value_type* const_str_; - }; - }; - size_type size_; - size_type capacity_; - const bool operable_; -}; - -// static members -template -const typename basic_string<_CharTy>::size_type basic_string<_CharTy>::npos = static_cast::size_type>(-1); - -template -const typename basic_string<_CharTy>::char_type basic_string<_CharTy>::empty_cstr[1] = { 0 }; - - -// -// operator== for basic_string -// - -template -inline bool operator==(basic_string<_CharTy> const& lhs, basic_string<_CharTy> const& rhs) { return lhs.compare(rhs) == 0; } - -template -inline bool operator==(const typename basic_string<_CharTy>::char_type* lhs, basic_string<_CharTy> const& rhs) { return rhs.compare(lhs) == 0; } - -template -inline bool operator==(basic_string<_CharTy> const& lhs, const typename basic_string<_CharTy>::char_type* rhs) { return lhs.compare(rhs) == 0; } - -// -// operator!= for basic_string -// - -template -inline bool operator!=(basic_string<_CharTy> const& lhs, basic_string<_CharTy> const& rhs) { return lhs.compare(rhs) != 0; } - -template -inline bool operator!=(const typename basic_string<_CharTy>::char_type* lhs, basic_string<_CharTy> const& rhs) { return rhs.compare(lhs) != 0; } - -template -inline bool operator!=(basic_string<_CharTy> const& lhs, const typename basic_string<_CharTy>::char_type* rhs) { return lhs.compare(rhs) != 0; } - -// -// operator+ for basic_string -// - -template -inline basic_string<_CharTy> operator+(const typename basic_string<_CharTy>::char_type* lhs, basic_string<_CharTy> const& rhs) { return basic_string<_CharTy>{ lhs } + rhs; } - -// -// operator<> for basic_string -// - -template -inline bool operator<(basic_string<_CharTy> const& lhs, basic_string<_CharTy> const& rhs) { return lhs.compare(rhs) < 0; } - -template -inline bool operator>(basic_string<_CharTy> const& lhs, basic_string<_CharTy> const& rhs) { return lhs.compare(rhs) > 0; } - -template -inline bool operator<=(basic_string<_CharTy> const& lhs, basic_string<_CharTy> const& rhs) { return lhs.compare(rhs) <= 0; } - -template -inline bool operator>=(basic_string<_CharTy> const& lhs, basic_string<_CharTy> const& rhs) { return lhs.compare(rhs) >= 0; } - -// -// operator<<>> for basic_string -// - -template -std::basic_ostream::char_type>& operator<<(std::basic_ostream::char_type>& os, const basic_string<_CharTy>& str); - -template -std::basic_istream::char_type>& operator>>(std::basic_istream::char_type>& is, basic_string<_CharTy>& str); - - -// -// to_string functions -// - -template -basic_string<_CharTy> to_basic_string(int val); - -template -basic_string<_CharTy> to_basic_string(unsigned int val); - -template -basic_string<_CharTy> to_basic_string(long val); - -template -basic_string<_CharTy> to_basic_string(unsigned long val); - -template -basic_string<_CharTy> to_basic_string(long long val); - -template -basic_string<_CharTy> to_basic_string(unsigned long long val); - -template -basic_string<_CharTy> to_basic_string(float val); - -template -basic_string<_CharTy> to_basic_string(double val); - -template -basic_string<_CharTy> to_basic_string(long double val); - -// -// format_string -// - -template -basic_string format_string(const char* const fmt, _Args&& ... args); - -template -basic_string format_string(const wchar_t* const fmt, _Args&& ... args); - - -// -// string && wstring -// -using string = ::oc::basic_string; -using wstring = ::oc::basic_string; - - -inline string to_string(int val) { return to_basic_string(val); } -inline string to_string(unsigned int val) { return to_basic_string(val); } -inline string to_string(long val) { return to_basic_string(val); } -inline string to_string(unsigned long val) { return to_basic_string(val); } -inline string to_string(long long val) { return to_basic_string(val); } -inline string to_string(unsigned long long val) { return to_basic_string(val); } -inline string to_string(float val) { return to_basic_string(val); } -inline string to_string(double val) { return to_basic_string(val); } -inline string to_string(long double val) { return to_basic_string(val); } - -inline wstring to_wstring(int val) { return to_basic_string(val); } -inline wstring to_wstring(unsigned int val) { return to_basic_string(val); } -inline wstring to_wstring(long val) { return to_basic_string(val); } -inline wstring to_wstring(unsigned long val) { return to_basic_string(val); } -inline wstring to_wstring(long long val) { return to_basic_string(val); } -inline wstring to_wstring(unsigned long long val) { return to_basic_string(val); } -inline wstring to_wstring(float val) { return to_basic_string(val); } -inline wstring to_wstring(double val) { return to_basic_string(val); } -inline wstring to_wstring(long double val) { return to_basic_string(val); } - - -} // namespace oc - -namespace oc -{ - -// -// details of basic_string -// -namespace __string_details -{ - template - _SizeTy TraitsFind( - const typename _Traits::char_type* first, _SizeTy first_size, _SizeTy offset, - const typename _Traits::char_type* second, _SizeTy count) - { - if (count > first_size || offset > first_size - count) - { - return static_cast<_SizeTy>(-1); - } - - if (count == 0) - { - return offset; - } - - const auto matches_end = first + (first_size - count) + 1; - for (auto iter = first + offset; ; ++iter) - { - iter = typename _Traits::find(iter, static_cast<_SizeTy>(matches_end - iter), *second); - if (!iter) - { - return static_cast<_SizeTy>(-1); - } - - if (typename _Traits::compare(iter, second, count) == 0) - { - return static_cast<_SizeTy>(iter - first); - } - } - } - - template - _SizeTy TraitsFindLastOf( - const typename _Traits::char_type* first, const _SizeTy first_size, const _SizeTy pos, - const typename _Traits::char_type* second, const _SizeTy count) - { - if (count != 0 && first_size != 0) - { - for (auto iter = first + std::min(pos, first_size - 1); ; --iter) - { - if (typename _Traits::find(second, count, *iter)) - { - return static_cast<_SizeTy>(iter - first); - } - if (iter == first) - { - break; - } - } - } - return static_cast<_SizeTy>(-1); - } -} - - -template -inline basic_string<_CharTy>::basic_string() - : str_(nullptr) - , size_(0) - , capacity_(0) - , operable_(true) -{ -} - -template -inline basic_string<_CharTy>::basic_string(const char_type* cstr, bool const_str) - : operable_(!const_str) - , size_(0) - , capacity_(0) - , str_(nullptr) -{ - if (cstr == nullptr) - return; - - if (operable_) - { - assign(cstr, traits_type::length(cstr)); - } - else - { - const_str_ = cstr; - size_ = traits_type::length(cstr); - capacity_ = size_; - } -} - -template -inline basic_string<_CharTy>::basic_string(const char_type* cstr, size_type count) - : basic_string() -{ - assign(cstr, count); -} - -template -inline basic_string<_CharTy>::basic_string(size_type count, char_type ch) - : basic_string() -{ - assign(count, ch); -} - -template -inline basic_string<_CharTy>::basic_string(basic_string const& rhs) - : basic_string(rhs.const_str_, !rhs.operable_) -{ -} - -template -inline basic_string<_CharTy>::basic_string(basic_string const& rhs, size_type pos, size_type count) - : basic_string() -{ - assign(rhs, pos, count); -} - -template -inline basic_string<_CharTy>::basic_string(std::basic_string const& str) - : basic_string(str.c_str(), false) -{ -} - -template -inline basic_string<_CharTy>::basic_string(basic_string&& rhs) noexcept - : str_(rhs.str_) - , size_(rhs.size_) - , capacity_(rhs.capacity_) - , operable_(rhs.operable_) -{ - rhs.str_ = nullptr; - rhs.size_ = rhs.capacity_ = 0; -} - -template -inline basic_string<_CharTy>::~basic_string() -{ - destroy(); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::assign(size_type count, const char_type ch) -{ - discard_const_data(); - - if (count != 0) - { - if (count > capacity_) - { - destroy(); - str_ = allocate(count + 1); - capacity_ = count; - } - size_ = count; - - traits_type::assign(str_, size_, ch); - traits_type::assign(*(str_ + size_), value_type()); - } - else - { - clear(); - } - return (*this); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::assign(const char_type* cstr, size_type count) -{ - discard_const_data(); - - if (cstr && count) - { - if (count > capacity_) - { - destroy(); - str_ = allocate(count + 1); - capacity_ = count; - } - size_ = count; - - traits_type::move(str_, cstr, size_); - traits_type::assign(str_[size_], value_type()); - } - else - { - clear(); - } - return (*this); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::assign(basic_string const& rhs, size_type pos, size_type count) -{ - if (count == 0 || pos > rhs.size()) - { - clear(); - return (*this); - } - - discard_const_data(); - - count = rhs.clamp_suffix_size(pos, count); - - if (count > capacity_) - { - destroy(); - str_ = allocate(count + 1); - capacity_ = count; - } - size_ = count; - - traits_type::move(str_, rhs.begin().core() + pos, size_); - traits_type::assign(str_[size_], value_type()); - return (*this); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::erase(size_type offset, size_type count) -{ - if (count == 0) - return (*this); - - check_offset(offset); - check_operability(); - - count = clamp_suffix_size(offset, count); - - if (count == 0) - { - clear(); - return (*this); - } - - size_type new_size = size_ - count; - iterator erase_at = begin().core() + offset; - traits_type::move(erase_at.core(), erase_at.core() + count, new_size - offset + 1); - return (*this); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::insert(size_type index, size_type count, char_type ch) -{ - if (count == 0) - return (*this); - - if (index >= size()) - return append(count, ch); - - check_operability(); - - char_type* const old_ptr = str_; - const size_type old_size = size_; - const size_type old_capacity = capacity_; - const size_type suffix_size = old_size - index + 1; - - size_ = old_size + count; - - if (size_ > old_capacity) - { - capacity_ = size_; - char_type* new_ptr = allocate(capacity_ + 1); - - char_type* const insert_at = new_ptr + index; - traits_type::move(new_ptr, old_ptr, index); // (0) - (index) - traits_type::assign(insert_at, count, ch); // (index) - (index + count) - traits_type::move(insert_at + count, old_ptr + index, suffix_size); // (index + count) - (old_size - index) - - deallocate(str_, old_capacity + 1); - str_ = new_ptr; - } - else - { - char_type* const insert_at = old_ptr + index; - traits_type::move(insert_at + count, old_ptr + index, suffix_size); - traits_type::assign(insert_at, count, ch); - } - - return (*this); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::insert(size_type index, const char_type* cstr, size_type count) -{ - if (count == 0) - return (*this); - - if (index >= size()) - return append(cstr, count); - - check_operability(); - - char_type* const old_ptr = str_; - const size_type old_size = size_; - const size_type old_capacity = capacity_; - const size_type suffix_size = old_size - index + 1; - - size_ = old_size + count; - - if (size_ > old_capacity) - { - capacity_ = size_; - char_type* new_ptr = allocate(capacity_ + 1); - - char_type* const insert_at = new_ptr + index; - traits_type::move(new_ptr, old_ptr, index); // (0) - (index) - traits_type::move(insert_at, cstr, count); // (index) - (index + count) - traits_type::move(insert_at + count, old_ptr + index, suffix_size); // (index + count) - (old_size - index) - - deallocate(str_, old_capacity + 1); - str_ = new_ptr; - } - else - { - char_type* const insert_at = old_ptr + index; - traits_type::move(insert_at + count, old_ptr + index, suffix_size); - traits_type::move(insert_at, cstr, count); - } - - return (*this); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::insert(size_type index, const basic_string& str, size_type off, size_type count) -{ - if (count == 0 || off > str.size()) - return (*this); - - if (index >= size()) - return append(str, off, count); - - check_operability(); - - count = clamp_suffix_size(off, count); - - char_type* const old_ptr = str_; - const size_type old_size = size_; - const size_type old_capacity = capacity_; - const size_type suffix_size = old_size - index + 1; - - size_ = old_size + count; - - if (size_ > old_capacity) - { - capacity_ = size_; - char_type* new_ptr = allocate(capacity_ + 1); - - char_type* const insert_at = new_ptr + index; - traits_type::move(new_ptr, old_ptr, index); // (0) - (index) - traits_type::move(insert_at, str.begin().core() + off, count); // (index) - (index + count) - traits_type::move(insert_at + count, old_ptr + index, suffix_size); // (index + count) - (old_size - index) - - deallocate(str_, old_capacity + 1); - str_ = new_ptr; - } - else - { - char_type* const insert_at = old_ptr + index; - traits_type::move(insert_at + count, old_ptr + index, suffix_size); - traits_type::move(insert_at, str.begin().core() + off, count); - } - - return (*this); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::append(size_type count, char_type ch) -{ - check_operability(); - - size_type new_size = size_ + count; - size_type new_cap = new_size + 1; - char_type* new_str = allocate(new_cap); - - traits_type::move(new_str, str_, size_); - traits_type::assign(new_str + size_, count, ch); - traits_type::assign(new_str[new_size], value_type()); - - destroy(); - - str_ = new_str; - size_ = new_size; - capacity_ = new_cap; - return (*this); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::append(const char_type* cstr, size_type count) -{ - check_operability(); - - size_type new_size = size_ + count; - size_type new_cap = new_size + 1; - char_type* new_str = allocate(new_cap); - - traits_type::move(new_str, str_, size_); - traits_type::move(new_str + size_, cstr, count); - traits_type::assign(new_str[new_size], value_type()); - - destroy(); - - str_ = new_str; - size_ = new_size; - capacity_ = new_cap; - return (*this); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::append(basic_string const& other, size_type pos, size_type count) -{ - check_operability(); - - if (pos >= other.size()) - return (*this); - - count = other.clamp_suffix_size(pos, count); - - size_type new_size = size_ + count; - size_type new_cap = new_size + 1; - char_type* new_str = allocate(new_cap); - - traits_type::move(new_str, str_, size_); - traits_type::move(new_str + size_, other.begin().core() + pos, count); - traits_type::assign(new_str[new_size], value_type()); - - destroy(); - - str_ = new_str; - size_ = new_size; - capacity_ = new_cap; - return (*this); -} - -template -inline void basic_string<_CharTy>::reserve(const size_type new_cap) -{ - if (new_cap <= capacity_) - return; - - check_operability(); - - char_type* new_str = allocate(new_cap); - traits_type::move(new_str, str_, capacity_); - - destroy(); - - str_ = new_str; - capacity_ = new_cap; -} - -template -inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::hash() const -{ - static size_type fnv_prime = 16777619U; - size_type fnv_offset_basis = 2166136261U; - - for (size_type index = 0; index < size_; ++index) - { - fnv_offset_basis ^= static_cast(const_str_[index]); - fnv_offset_basis *= fnv_prime; - } - return fnv_offset_basis; -} - -template -inline int basic_string<_CharTy>::compare(const char_type* const str) const -{ - size_type count1 = size(); - size_type count2 = traits_type::length(str); - size_type rlen = std::min(count1, count2); - - int ret = traits_type::compare(const_str_, str, rlen); - if (ret != 0) - return ret; - - if (count1 < count2) - return -1; - - if (count1 > count2) - return 1; - - return 0; -} - -template -inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find(const char_type ch, size_type offset) const -{ - if (offset >= size_) - return basic_string<_CharTy>::npos; - - const_iterator citer = traits_type::find(cbegin().core() + offset, size_, ch); - return citer ? (citer - cbegin()) : basic_string<_CharTy>::npos; -} - -template -inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find(const char_type* const str, size_type offset, size_type count) const -{ - if (offset >= size_) - return basic_string<_CharTy>::npos; - return __string_details::TraitsFind(const_str_, size_, offset, str, count); -} - -template -inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find_first_of(const char_type* const str, size_type offset, size_type count) const -{ - if (offset >= size_) - return basic_string<_CharTy>::npos; - - const_iterator citer = std::find_first_of(cbegin().core() + offset, cend().core(), str, str + count); - return (citer != cend()) ? (citer - cbegin()) : basic_string<_CharTy>::npos; -} - -template -inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find_last_of(const char_type ch, size_type pos) const -{ - if (pos == 0 || pos > size_ || pos == npos) - return npos; - - const_reverse_iterator criter = std::find(crbegin(), crend(), ch); - return (criter != crend()) ? (criter.core() - cbegin()) : basic_string<_CharTy>::npos; -} - -template -inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::find_last_of(const char_type* const str, size_type pos, size_type count) const -{ - if (pos == 0 || pos > size_ || pos == npos) - return npos; - - return __string_details::TraitsFindLastOf(const_str_, size_, pos, str, count); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::replace(size_type pos, size_type count, const char_type* cstr, size_type count2) -{ - check_offset(pos); - check_operability(); - - count = clamp_suffix_size(pos, count); - if (count == count2) - { - traits_type::move(str_ + pos, cstr, count2); - return (*this); - } - - char_type* new_ptr = nullptr; - char_type* const old_ptr = str_; - const size_type old_size = size_; - const size_type old_capacity = capacity_; - const size_type suffix_size = old_size - count - pos + 1; - - if (count < count2 && (old_size + count2 - count) > capacity_) - { - const size_type growth = count2 - count; - size_ = old_size + growth; - capacity_ = size_; - new_ptr = allocate(capacity_ + 1); - - traits_type::move(new_ptr, old_ptr, pos); - } - else - { - size_ = old_size - (count - count2); - } - - char_type* const insert_at = (new_ptr ? new_ptr : old_ptr) + pos; - traits_type::move(insert_at, cstr, count2); - traits_type::move(insert_at + count2, old_ptr + count, suffix_size); - - if (new_ptr) - { - deallocate(str_, old_capacity + 1); - str_ = new_ptr; - } - - return (*this); -} - -template -inline basic_string<_CharTy>& basic_string<_CharTy>::replace(size_type pos, size_type count, size_type count2, const char_type ch) -{ - check_offset(pos); - check_operability(); - - count = clamp_suffix_size(pos, count); - if (count == count2) - { - traits_type::assign(str_ + pos, count2, ch); - return (*this); - } - - char_type* new_ptr = nullptr; - char_type* const old_ptr = str_; - const size_type old_size = size_; - const size_type old_capacity = capacity_; - const size_type suffix_size = old_size - count - pos + 1; - - if (count < count2 && (old_size + count2 - count) > capacity_) - { - const size_type growth = count2 - count; - size_ = old_size + growth; - capacity_ = size_; - new_ptr = allocate(capacity_ + 1); - - traits_type::move(new_ptr, old_ptr, pos); - } - else - { - size_ = old_size - (count - count2); - } - - char_type* const insert_at = (new_ptr ? new_ptr : old_ptr) + pos; - traits_type::assign(insert_at, count2, ch); - traits_type::move(insert_at + count2, old_ptr + count, suffix_size); - - if (new_ptr) - { - deallocate(str_, old_capacity + 1); - str_ = new_ptr; - } - - return (*this); -} - -template -inline typename basic_string<_CharTy>::size_type basic_string<_CharTy>::copy(char_type* cstr, size_type count, size_type pos) const -{ - if (count == 0 || cstr == const_str_) - return 0; - - check_offset(pos); - - count = clamp_suffix_size(pos, count); - traits_type::move(cstr, cbegin().core() + pos, count); - return count; -} - -template -inline typename basic_string<_CharTy>::char_type* basic_string<_CharTy>::allocate(size_type count) -{ - return get_allocator().allocate(count); -} - -template -inline void basic_string<_CharTy>::deallocate(char_type*& ptr, size_type count) -{ - get_allocator().deallocate(ptr, count); - ptr = nullptr; -} - -template -inline void basic_string<_CharTy>::destroy() -{ - if (operable_ && str_) - { - deallocate(str_, capacity_ + 1); - } - else - { - const_str_ = nullptr; - } - size_ = capacity_ = 0; -} - -template -inline void basic_string<_CharTy>::swap(basic_string& rhs) noexcept -{ - std::swap(const_str_, rhs.const_str_); - std::swap(size_, rhs.size_); - std::swap(capacity_, rhs.capacity_); - - // swap const datas - std::swap(*const_cast(&operable_), *const_cast(&rhs.operable_)); -} - -template -inline void basic_string<_CharTy>::discard_const_data() -{ - if (!operable_) - { - // force to enable operability - *const_cast(&operable_) = true; - const_str_ = nullptr; - capacity_ = size_ = 0; - } -} - -template -inline void basic_string<_CharTy>::check_operability() -{ - if (!operable_) - { - // create a new string, then swap it with self - basic_string(const_str_, false).swap(*this); - } -} - -// -// details of basic_string<>::parese -// - -template -inline basic_string<_CharTy> basic_string<_CharTy>::parse(int val) { return ::oc::to_basic_string(val); } - -template -inline basic_string<_CharTy> basic_string<_CharTy>::parse(unsigned int val) { return ::oc::to_basic_string(val); } - -template -inline basic_string<_CharTy> basic_string<_CharTy>::parse(long val) { return ::oc::to_basic_string(val); } - -template -inline basic_string<_CharTy> basic_string<_CharTy>::parse(unsigned long val) { return ::oc::to_basic_string(val); } - -template -inline basic_string<_CharTy> basic_string<_CharTy>::parse(long long val) { return ::oc::to_basic_string(val); } - -template -inline basic_string<_CharTy> basic_string<_CharTy>::parse(unsigned long long val) { return ::oc::to_basic_string(val); } - -template -inline basic_string<_CharTy> basic_string<_CharTy>::parse(float val) { return ::oc::to_basic_string(val); } - -template -inline basic_string<_CharTy> basic_string<_CharTy>::parse(double val) { return ::oc::to_basic_string(val); } - -template -inline basic_string<_CharTy> basic_string<_CharTy>::parse(long double val) { return ::oc::to_basic_string(val); } - -// -// details of basic_string::format -// - -template -template -inline basic_string<_CharTy> basic_string<_CharTy>::format(const char_type* fmt, _Args&& ... args) -{ - return ::oc::format_string(fmt, std::forward<_Args>(args)...); -} - -// -// details of operator<<>> -// - -template -inline std::basic_ostream::char_type>& operator<<(std::basic_ostream::char_type>& os, const basic_string<_CharTy>& str) -{ - using ostream = std::basic_ostream::char_type, typename basic_string<_CharTy>::traits_type>; - using size_type = typename basic_string<_CharTy>::size_type; - using traits = typename basic_string<_CharTy>::traits_type; - - const ostream::sentry ok(os); - std::ios_base::iostate state = std::ios_base::goodbit; - - if (!ok) - { - state |= std::ios_base::badbit; - } - else - { - const auto str_size = str.size(); - size_type pad = (os.width() <= 0 || static_cast(os.width()) <= str_size) ? 0 : static_cast(os.width()) - str_size; - - try - { - if ((os.flags() & std::ios_base::adjustfield) != std::ios_base::left) - { - for (; 0 < pad; --pad) - { - if (traits::eq_int_type(traits::eof(), os.rdbuf()->sputc(os.fill()))) - { - state |= std::ios_base::badbit; - break; - } - } - } - - if (state == std::ios_base::goodbit - && os.rdbuf()->sputn(str.data(), (std::streamsize)str_size) != (std::streamsize)str_size) - { - state |= std::ios_base::badbit; - } - else - { - for (; 0 < pad; --pad) - { - if (traits::eq_int_type(traits::eof(), os.rdbuf()->sputc(os.fill()))) - { - state |= std::ios_base::badbit; - break; - } - } - } - os.width(0); - } - catch (...) - { - os.setstate(std::ios_base::badbit, true); - } - } - - os.setstate(state); - return (os); -} - -template -inline std::basic_istream::char_type>& operator>>(std::basic_istream::char_type>& is, basic_string<_CharTy>& str) -{ - using ctype = std::ctype::char_type>; - using istream = std::basic_istream::char_type, typename basic_string<_CharTy>::traits_type>; - using size_type = typename basic_string<_CharTy>::size_type; - using traits = typename basic_string<_CharTy>::traits_type; - - bool changed = false; - const istream::sentry ok(is); - std::ios_base::iostate state = std::ios_base::goodbit; - - if (ok) - { - const ctype& ctype_fac = std::use_facet(is.getloc()); - str.erase(); - try - { - size_type size = (0 < is.width() && static_cast(is.width()) < str.max_size()) ? static_cast(is.width()) : str.max_size(); - typename traits::int_type meta = is.rdbuf()->sgetc(); - - for (; 0 < size; --size, meta = is.rdbuf()->snextc()) - { - if (traits::eq_int_type(traits::eof(), meta)) - { - state |= std::ios_base::eofbit; - break; - } - else if (ctype_fac.is(ctype::space, traits::to_char_type(meta))) - { - break; - } - else - { - str.push_back(traits::to_char_type(meta)); - changed = true; - } - } - } - catch (...) - { - is.setstate(std::ios_base::badbit, true); - } - } - - is.width(0); - if (!changed) - state |= std::ios_base::failbit; - is.setstate(state); - return is; -} - -// -// details of to_string functions -// - -namespace __to_string_detail -{ - template - struct FloatingToString - { - // template - // static basic_string<_CharTy> convert(const _Ty val); - }; - - template - struct IntegralToString - { - // template - // static basic_string<_CharTy> convert(const _Ty val); - }; -} - -template -inline basic_string<_CharTy> to_basic_string(int val) -{ - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); -} - -template -inline basic_string<_CharTy> to_basic_string(unsigned int val) -{ - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); -} - -template -inline basic_string<_CharTy> to_basic_string(long val) -{ - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); -} - -template -inline basic_string<_CharTy> to_basic_string(unsigned long val) -{ - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); -} - -template -inline basic_string<_CharTy> to_basic_string(long long val) -{ - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); -} - -template -inline basic_string<_CharTy> to_basic_string(unsigned long long val) -{ - return (__to_string_detail::IntegralToString<_CharTy>::convert(val)); -} - -template -inline basic_string<_CharTy> to_basic_string(float val) -{ - return (__to_string_detail::FloatingToString<_CharTy>::convert(val)); -} - -template -inline basic_string<_CharTy> to_basic_string(double val) -{ - return (__to_string_detail::FloatingToString<_CharTy>::convert(val)); -} - -template -inline basic_string<_CharTy> to_basic_string(long double val) -{ - return (__to_string_detail::FloatingToString<_CharTy>::convert(val)); -} - -template -inline basic_string format_string(const char* const fmt, _Args&& ... args) -{ - using string_type = basic_string; - const auto len = static_cast(::_scprintf(fmt, std::forward<_Args>(args)...)); - if (len) - { - string_type str(len, '\0'); - ::sprintf_s(&str[0], len + 1, fmt, std::forward<_Args>(args)...); - return str; - } - return string_type{}; -} - -template -inline basic_string format_string(const wchar_t* const fmt, _Args&& ... args) -{ - using string_type = basic_string; - const auto len = static_cast(::_scwprintf(fmt, std::forward<_Args>(args)...)); - if (len) - { - string_type str(len, L'\0'); - ::swprintf_s(&str[0], len + 1, fmt, std::forward<_Args>(args)...); - return str; - } - return string_type{}; -} - -namespace __to_string_detail -{ - template - _Elem* __IntegerToStringBufferEnd(const _Ty val, _Elem* const buffer_end) - { - using _UTy = std::make_unsigned_t<_Ty>; - - _Elem* next = buffer_end; - auto uval = static_cast<_UTy>(val); - - if (val < 0) - uval = 0 - uval; - - do - { - *--next = static_cast<_Elem>('0' + uval % 10); - uval /= 10; - } while (uval != 0); - - if (val < 0) - * --next = static_cast<_Elem>('-'); - - return next; - } - - template <> - struct IntegralToString - { - template - static basic_string convert(const _Ty val) - { - static_assert(std::is_integral<_Ty>::value, "_Ty must be integral"); - - using _Elem = typename basic_string::traits_type::char_type; - - _Elem buffer[21]; - _Elem* const buffer_end = std::end(buffer); - _Elem* buffer_begin = __IntegerToStringBufferEnd(val, buffer_end); - - return basic_string(buffer_begin, buffer_end); - } - }; - - template <> - struct IntegralToString - { - template - static basic_string convert(const _Ty val) - { - static_assert(std::is_integral<_Ty>::value, "_Ty must be integral"); - - using _Elem = typename basic_string::traits_type::char_type; - - _Elem buffer[21]; - _Elem* const buffer_end = std::end(buffer); - _Elem* buffer_begin = __IntegerToStringBufferEnd(val, buffer_end); - - return basic_string(buffer_begin, buffer_end); - } - }; - - template<> - struct FloatingToString - { - static inline basic_string convert(const float val) - { - return format_string(L"%g", val); - } - - static inline basic_string convert(const double val) - { - return format_string(L"%g", val); - } - - static inline basic_string convert(const long double val) - { - return format_string(L"%Lg", val); - } - }; - - template<> - struct FloatingToString - { - static inline basic_string convert(const float val) - { - return format_string("%g", val); - } - - static inline basic_string convert(const double val) - { - return format_string("%g", val); - } - - static inline basic_string convert(const long double val) - { - return format_string("%Lg", val); - } - }; -} - -} - -namespace oc -{ - -template -class string_convert -{ - enum : size_t { BUFFER_INCREASE = 8, BUFFER_MAX = 16 }; - -public: - using byte_string = ::oc::basic_string; - using wide_string = ::oc::basic_string<_Elem>; - using codecvt_type = _Codecvt; - using state_type = typename codecvt_type::state_type; - using int_type = typename wide_string::traits_type::int_type; - - string_convert() - : string_convert(new codecvt_type) - { - } - - explicit string_convert(const codecvt_type* cvt) - : state_{} - , cvt_(cvt) - , loc_() - , conv_num_(0) - { - loc_ = std::locale(loc_, cvt_); - } - - virtual ~string_convert() { } - - size_t converted() const noexcept { return conv_num_; } - - state_type state() const { return state_; } - - wide_string from_bytes(char _Byte) - { - return from_bytes(&_Byte, &_Byte + 1); - } - - wide_string from_bytes(const char* ptr) - { - return from_bytes(ptr, ptr + std::strlen(ptr)); - } - - wide_string from_bytes(const byte_string& byte_str) - { - const char* ptr = byte_str.c_str(); - return from_bytes(ptr, ptr + byte_str.size()); - } - - wide_string from_bytes(const char* first, const char* last) - { - wide_string wbuf, wstr; - const char* first_save = first; - - state_ = state_type{}; - - wbuf.append(BUFFER_INCREASE, (_Elem) '\0'); - for (conv_num_ = 0; first != last; conv_num_ = static_cast(first - first_save)) - { - _Elem* dest = &*wbuf.begin(); - _Elem* dnext; - - switch (cvt_->in(state_, first, last, first, dest, dest + wbuf.size(), dnext)) - { - case codecvt_type::partial: - case codecvt_type::ok: - { - if (dest < dnext) - { - wstr.append(dest, static_cast(dnext - dest)); - } - else if (wbuf.size() < BUFFER_MAX) - { - wbuf.append(BUFFER_INCREASE, '\0'); - } - else - { - throw std::range_error("bad conversion"); - } - break; - } - - case codecvt_type::noconv: - { - // no conversion, just copy code values - for (; first != last; ++first) - { - wstr.push_back(static_cast<_Elem>(*first)); - } - break; - } - - default: - throw std::range_error("bad conversion"); - } - } - return wstr; - } - - byte_string to_bytes(_Elem _Char) - { - return to_bytes(&_Char, &_Char + 1); - } - - byte_string to_bytes(const _Elem* _Wptr) - { - const _Elem* _Next = _Wptr; - while ((int_type)* _Next != 0) { ++_Next; } - - return to_bytes(_Wptr, _Next); - } - - byte_string to_bytes(const wide_string& _Wstr) - { - const _Elem* _Wptr = _Wstr.c_str(); - return to_bytes(_Wptr, _Wptr + _Wstr.size()); - } - - byte_string to_bytes(const _Elem* first, const _Elem* last) - { - byte_string bbuf, bstr; - const _Elem* first_save = first; - - state_ = state_type{}; - - bbuf.append(BUFFER_INCREASE, '\0'); - for (conv_num_ = 0; first != last; conv_num_ = static_cast(first - first_save)) - { - char* dest = &*bbuf.begin(); - char* dnext; - - switch (cvt_->out(state_, first, last, first, dest, dest + bbuf.size(), dnext)) - { - case codecvt_type::partial: - case codecvt_type::ok: - { - if (dest < dnext) - { - bstr.append(dest, (size_t)(dnext - dest)); - } - else if (bbuf.size() < BUFFER_MAX) - { - bbuf.append(BUFFER_INCREASE, '\0'); - } - else - { - throw (std::range_error("bad conversion")); - } - break; - } - - case codecvt_type::noconv: - { - // no conversion, just copy code values - for (; first != last; ++first) { - bstr.push_back((char)(int_type)* first); - } - break; - } - - default: - throw (std::range_error("bad conversion")); - } - } - return bstr; - } - - string_convert(const string_convert&) = delete; - string_convert& operator=(const string_convert&) = delete; - -private: - const codecvt_type* cvt_; - std::locale loc_; - state_type state_; - size_t conv_num_; -}; - -class chs_codecvt - : public std::codecvt_byname -{ -public: - chs_codecvt() : codecvt_byname("chs") {} - - static inline ::oc::wstring string_to_wide(::oc::string const& str) - { - string_convert conv; - return conv.from_bytes(str); - } - - static inline ::oc::string wide_to_string(::oc::wstring const& str) - { - string_convert conv; - return conv.to_bytes(str); - } -}; - -inline ::oc::wstring string_to_wide(::oc::string const& str) -{ - return oc::chs_codecvt::string_to_wide(str); -} - -inline ::oc::string wide_to_string(::oc::wstring const& str) -{ - return oc::chs_codecvt::wide_to_string(str); -} - -} // namespace oc - -namespace std -{ - -template<> -struct hash<::oc::string> -{ - inline size_t operator()(const ::oc::string& key) const - { - return key.hash(); - } -}; - -template<> -struct hash<::oc::wstring> -{ - inline size_t operator()(const ::oc::wstring& key) const - { - return key.hash(); - } -}; - -template<> -inline void swap<::oc::string>(::oc::string& lhs, ::oc::string& rhs) noexcept -{ - lhs.swap(rhs); -} - -template<> -inline void swap<::oc::wstring>(::oc::wstring& lhs, ::oc::wstring& rhs) noexcept -{ - lhs.swap(rhs); -} - -} diff --git a/src/3rd-party/OuterC/oc/vector.h b/src/3rd-party/OuterC/oc/vector.h deleted file mode 100644 index d73b16e0..00000000 --- a/src/3rd-party/OuterC/oc/vector.h +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include -#include -#include "vector/details.h" - -namespace oc -{ - -// -// vector<> -// Lightweight std::vector<>-like class -// -template > -class vector -{ -public: - using value_type = _Ty; - using size_type = size_t; - using difference_type = ptrdiff_t; - using reference = value_type&; - using const_reference = 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; - using allocator_type = typename _Alloc; - using manager = typename __vector_details::vector_memory_manager<_Ty, _Alloc>; - using initializer_list = std::initializer_list; - -public: - inline vector() : size_(0), capacity_(0), data_(nullptr) { } - inline vector(size_type count) : vector() { reserve(count); } - inline vector(size_type count, const _Ty& val) : vector() { assign(count, val); } - inline vector(initializer_list list) : vector() { assign(list); } - inline vector(const vector& src) : vector() { assign(src); } - inline vector(vector&& src) noexcept : vector() { swap(src); } - inline ~vector() { destroy(); } - - template - inline vector(_Iter first, _Iter last) : vector() { assign(first, last); } - - inline vector& operator=(const vector& src) { if (&src != this) { resize(src.size_); manager::copy_n(begin(), src.cbegin(), size_); } return (*this); } - inline vector& operator=(vector&& src) noexcept { swap(src); return *this; } - inline vector& operator=(initializer_list list) { if (list.size()) { assign(list.begin(), list.end()); } else clear(); return (*this); } - - inline vector& assign(size_type count, const _Ty& val) { if (count > 0) { resize(count); manager::fill_n(begin(), count, val); } else clear(); return (*this); } - inline vector& assign(const vector& src) { return operator=(src); } - inline vector& assign(initializer_list list) { return operator=(list); } - - template - inline void assign(_Iter first, _Iter last) { auto diff = std::distance(first, last); resize((size_type)diff); auto data = begin(); while (first != last) (*data++) = (*first++); } - - inline void clear() { destroy(); size_ = capacity_ = 0; data_ = nullptr; } - inline void swap(vector& rhs) noexcept { std::swap(size_, rhs.size_); std::swap(capacity_, rhs.capacity_); std::swap(data_, rhs.data_); } - - inline void resize(size_type new_size) { resize(new_size, _Ty()); } - void resize(size_type new_size, const _Ty& v); - void reserve(size_type new_capacity); - - inline void push_back(const _Ty& val) { resize(size_ + 1, val); } - inline void pop_back() { if (empty()) throw std::out_of_range("pop() called on empty vector"); resize(size_ - 1); } - inline void push_front(const _Ty& val) { if (size_ == 0) push_back(val); else insert(begin(), val); } - - inline iterator erase(const_iterator where) { return erase(where, where + 1); } - iterator erase(const_iterator first, const_iterator last); - - iterator insert(const_iterator where, const _Ty& v); - - inline bool empty() const { return size_ == 0; } - inline size_type size() const { return size_; } - inline size_type size_in_bytes() const { return size_ * ((size_type)sizeof(_Ty)); } - inline size_type max_size() const { return std::numeric_limits::max(); } - inline size_type capacity() const { return capacity_; } - inline reference operator[](size_type off) { if (off < 0 || off >= size_) throw std::out_of_range("vector subscript out of range"); return data_[off]; } - inline const_reference operator[](size_type off) const { if (off < 0 || off >= size_) throw std::out_of_range("vector subscript out of range"); return data_[off]; } - - - inline bool contains(const _Ty& v) const { auto data = cbegin(); const auto data_end = cend(); while (data != data_end) if (*(data++) == v) return true; return false; } - inline size_type index_of(const_iterator it) const { check_offset(it - cbegin(), "invalid array position"); return it - data_; } - - inline iterator begin() { return iterator(data_); } - inline const_iterator begin() const { return const_iterator(data_); } - inline const_iterator cbegin() const { return begin(); } - inline iterator end() { return iterator(data_ + size_); } - inline const_iterator end() const { return const_iterator(data_ + size_); } - inline const_iterator cend() const { return end(); } - inline reverse_iterator rbegin() { return reverse_iterator(end()); } - inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - inline const_reverse_iterator crbegin() const { return rbegin(); } - inline reverse_iterator rend() { return reverse_iterator(begin()); } - inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } - inline const_reverse_iterator crend() const { return rend(); } - inline reference front() { if (empty()) throw std::out_of_range("front() called on empty array"); return data_[0]; } - inline const_reference front() const { if (empty()) throw std::out_of_range("front() called on empty array"); return data_[0]; } - inline reference back() { if (empty()) throw std::out_of_range("back() called on empty array"); return data_[size_ - 1]; } - inline const_reference back() const { if (empty()) throw std::out_of_range("back() called on empty array"); return data_[size_ - 1]; } - -private: - inline size_type grow_capacity(size_type sz) const { size_type new_capacity = capacity_ ? (capacity_ + capacity_ / 2) : 8; return new_capacity > sz ? new_capacity : sz; } - inline void check_offset(const size_type off) const { if (off < 0 || off >= size_) throw std::out_of_range("invalid vector position"); } - - inline void destroy() { manager::destroy(data_, size_); manager::deallocate(data_, capacity_); } -protected: - size_type size_; - size_type capacity_; - _Ty* data_; -}; - -template -void vector<_Ty, _Alloc>::resize(size_type new_size, const _Ty& val) -{ - if (new_size > size_) - { - if (new_size > capacity_) - { - reserve(grow_capacity(new_size)); - } - manager::construct(begin() + size_, new_size - size_, val); - } - else - { - manager::destroy(begin() + new_size, size_ - new_size); - } - size_ = new_size; -} - -template -void vector<_Ty, _Alloc>::reserve(size_type new_capacity) -{ - if (new_capacity <= capacity_) - return; - - auto new_data = manager::allocate(new_capacity); - if (data_) - { - manager::construct_n(new_data, data_, size_/* only construct needed size */); - /* destroy old memory, but not resize */ - destroy(); - } - data_ = new_data; - capacity_ = new_capacity; -} - -template -typename vector<_Ty, _Alloc>::iterator - vector<_Ty, _Alloc>::erase(const_iterator first, const_iterator last) -{ - const auto off = first - begin(); - const auto count = last - first; - - if (count != 0) - { - check_offset(off); - - manager::move(begin() + off, begin() + off + count, size_ - off - count); - resize(size_ - count); // do destruction - } - return begin() + off; -} - -template -typename vector<_Ty, _Alloc>::iterator - vector<_Ty, _Alloc>::insert(const_iterator where, const _Ty& v) -{ - const auto off = where - begin(); - const auto insert_at = begin() + off; - - check_offset(off); - - resize(size_ + 1); - manager::move(insert_at + 1, insert_at, size_ - off - 1); - data_[off] = v; - return begin() + off; -} - -} // namespace oc diff --git a/src/3rd-party/OuterC/oc/vector/details.h b/src/3rd-party/OuterC/oc/vector/details.h deleted file mode 100644 index 7acf836e..00000000 --- a/src/3rd-party/OuterC/oc/vector/details.h +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) 2019-2020 OuterC - Nomango - -#pragma once -#include -#include -#include -#include - -namespace oc -{ - -namespace __vector_details -{ - -// vector_memory_manager<> with memory operations -template::value> -struct vector_memory_manager; - - -// -// vector_memory_manager for common type -// -template -struct vector_memory_manager<_Ty, _Alloc, true> -{ - using value_type = _Ty; - using size_type = size_t; - using allocator_type = typename _Alloc; - - static void fill_n(value_type* const dest, ptrdiff_t count, const value_type& val) - { - for (ptrdiff_t i = 0; i < count; ++i) - std::memcpy(std::addressof(dest[i]), std::addressof(val), sizeof(value_type)); - } - - static void copy_n(value_type* const dest, const value_type* src, ptrdiff_t count) - { - if (src == dest) - return; - std::memcpy(dest, src, count * sizeof(value_type)); - } - - static void move(value_type* const dest, const value_type* src, ptrdiff_t count) - { - if (src == dest) - return; - std::memmove(dest, src, count * sizeof(value_type)); - } - - static void construct(value_type* const ptr, ptrdiff_t count, const value_type& val) - { - fill_n(ptr, count, val); - } - - static void construct_n(value_type* const ptr, const value_type* src, ptrdiff_t count) - { - copy_n(ptr, src, count); - } - - static void destroy(value_type* const ptr, ptrdiff_t count) - { - } - - static value_type* allocate(ptrdiff_t count) - { - return get_allocator().allocate(count); - } - - static void deallocate(value_type*& ptr, ptrdiff_t count) - { - if (ptr) - { - get_allocator().deallocate(ptr, count); - ptr = nullptr; - } - } - -private: - static inline allocator_type& get_allocator() - { - static allocator_type allocator_; - return allocator_; - } -}; - -// -// vector_memory_manager for classes -// -template -struct vector_memory_manager<_Ty, _Alloc, false> -{ - using value_type = _Ty; - using size_type = size_t; - using allocator_type = typename _Alloc; - - static void fill_n(value_type* const dest, ptrdiff_t count, const value_type& val) - { - // Avoid warning C4996 - // std::fill_n(dest, count, val); - for (ptrdiff_t i = 0; i < count; ++i) - dest[i] = val; - } - - static void copy_n(value_type* const dest, const value_type* src, ptrdiff_t count) - { - if (src == dest) - return; - - // Avoid warning C4996 - // std::copy_n(src, count, dest); - for (ptrdiff_t i = 0; i < count; ++i) - dest[i] = src[i]; - } - - static void move(value_type* const dest, const value_type* src, ptrdiff_t count) - { - if (src == dest) - return; - - if (dest > src && dest < src + count) - { - // Avoid warning C4996 - // std::copy_backward(src, src + count, dest); - for (ptrdiff_t i = 0; i < count; ++i) - dest[count - i - 1] = src[count - i - 1]; - } - else - copy_n(dest, src, count); - } - - static void construct(value_type* const ptr, ptrdiff_t count, const value_type& val) - { - for (ptrdiff_t i = 0; i < count; ++i) - get_allocator().construct(std::addressof(ptr[i]), val); - } - - static void construct_n(value_type* const ptr, const value_type* src, ptrdiff_t count) - { - for (ptrdiff_t i = 0; i < count; ++i) - get_allocator().construct(std::addressof(ptr[i]), src[i]); - } - - static void destroy(value_type* const ptr, ptrdiff_t count) - { - for (ptrdiff_t i = 0; i < count; ++i) - get_allocator().destroy(std::addressof(ptr[i])); - } - - static value_type* allocate(ptrdiff_t count) - { - return get_allocator().allocate(count); - } - - static void deallocate(value_type*& ptr, ptrdiff_t count) - { - if (ptr) - { - get_allocator().deallocate(ptr, count); - ptr = nullptr; - } - } - -private: - static inline allocator_type& get_allocator() - { - static allocator_type allocator_; - return allocator_; - } -}; - -} // namespace __vector_details -} // namespace oc diff --git a/src/kiwano-audio/AudioModule.cpp b/src/kiwano-audio/AudioModule.cpp index 5db90bca..8b0fbeb2 100644 --- a/src/kiwano-audio/AudioModule.cpp +++ b/src/kiwano-audio/AudioModule.cpp @@ -51,7 +51,7 @@ void AudioModule::SetupModule() hr = x_audio2_->CreateMasteringVoice(&mastering_voice_); } - ThrowIfFailed(hr, "Create audio resources failed"); + KGE_THROW_IF_FAILED(hr, "Create audio resources failed"); } void AudioModule::DestroyModule() diff --git a/src/kiwano-audio/SoundPlayer.cpp b/src/kiwano-audio/SoundPlayer.cpp index f97ceb1f..58ca92c6 100644 --- a/src/kiwano-audio/SoundPlayer.cpp +++ b/src/kiwano-audio/SoundPlayer.cpp @@ -43,9 +43,9 @@ SoundPlayer::~SoundPlayer() size_t SoundPlayer::Load(String const& file_path) { - int hash_code = static_cast(file_path.hash()); - if (sound_cache_.end() != sound_cache_.find(hash_code)) - return hash_code; + size_t hash = std::hash()(file_path); + if (sound_cache_.end() != sound_cache_.find(hash)) + return hash; SoundPtr sound = new (std::nothrow) Sound; @@ -54,8 +54,8 @@ size_t SoundPlayer::Load(String const& file_path) if (sound->Load(file_path)) { sound->SetVolume(volume_); - sound_cache_.insert(std::make_pair(hash_code, sound)); - return hash_code; + sound_cache_.insert(std::make_pair(hash, sound)); + return hash; } } return 0; diff --git a/src/kiwano-audio/Transcoder.cpp b/src/kiwano-audio/Transcoder.cpp index a2962446..d55484e5 100644 --- a/src/kiwano-audio/Transcoder.cpp +++ b/src/kiwano-audio/Transcoder.cpp @@ -76,11 +76,11 @@ HRESULT Transcoder::LoadMediaFile(String const& file_path) ComPtr reader; - hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromURL(MultiByteToWide(file_path).c_str(), nullptr, &reader); + hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromURL(string::ToWide(file_path).c_str(), nullptr, &reader); if (SUCCEEDED(hr)) { - hr = ReadSource(reader.get()); + hr = ReadSource(reader.Get()); } return hr; @@ -111,17 +111,17 @@ HRESULT Transcoder::LoadMediaResource(Resource const& res) if (SUCCEEDED(hr)) { - hr = dlls::MediaFoundation::Get().MFCreateMFByteStreamOnStream(stream.get(), &byte_stream); + hr = dlls::MediaFoundation::Get().MFCreateMFByteStreamOnStream(stream.Get(), &byte_stream); } if (SUCCEEDED(hr)) { - hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromByteStream(byte_stream.get(), nullptr, &reader); + hr = dlls::MediaFoundation::Get().MFCreateSourceReaderFromByteStream(byte_stream.Get(), nullptr, &reader); } if (SUCCEEDED(hr)) { - hr = ReadSource(reader.get()); + hr = ReadSource(reader.Get()); } return hr; @@ -150,7 +150,7 @@ HRESULT Transcoder::ReadSource(IMFSourceReader* reader) // 设置 source reader 的媒体类型,它将使用合适的解码器去解码这个音频 if (SUCCEEDED(hr)) { - hr = reader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, partial_type.get()); + hr = reader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, partial_type.Get()); } // 从 IMFMediaType 中获取 WAVEFORMAT 结构 @@ -170,7 +170,7 @@ HRESULT Transcoder::ReadSource(IMFSourceReader* reader) { uint32_t size = 0; hr = dlls::MediaFoundation::Get().MFCreateWaveFormatExFromMFMediaType( - uncompressed_type.get(), &wave_format_, &size, (DWORD)MFWaveFormatExConvertFlag_Normal); + uncompressed_type.Get(), &wave_format_, &size, (DWORD)MFWaveFormatExConvertFlag_Normal); } // 估算音频流大小 diff --git a/src/kiwano-network/HttpModule.cpp b/src/kiwano-network/HttpModule.cpp index b1edbdc3..adb70de4 100644 --- a/src/kiwano-network/HttpModule.cpp +++ b/src/kiwano-network/HttpModule.cpp @@ -310,7 +310,7 @@ void HttpModule::DispatchResponseCallback() if (callback) { - callback(request.get(), response.get()); + callback(request.Get(), response.Get()); } } } diff --git a/src/kiwano-network/HttpRequest.h b/src/kiwano-network/HttpRequest.h index d95106e2..bb6874fc 100644 --- a/src/kiwano-network/HttpRequest.h +++ b/src/kiwano-network/HttpRequest.h @@ -21,7 +21,7 @@ #pragma once #include #include -#include +#include namespace kiwano { diff --git a/src/kiwano-physics/Body.cpp b/src/kiwano-physics/Body.cpp index 2d54a12d..50f43465 100644 --- a/src/kiwano-physics/Body.cpp +++ b/src/kiwano-physics/Body.cpp @@ -84,7 +84,7 @@ Fixture* Body::AddCircleShape(float radius, float density, float friction, float Fixture::Param param(density, friction, restitution, is_sensor); FixturePtr fixture = Fixture::CreateCircle(this, param, radius); AddFixture(fixture); - return fixture.get(); + return fixture.Get(); } Fixture* Body::AddRectShape(Vec2 const& size, float density, float friction, float restitution, bool is_sensor) @@ -92,7 +92,7 @@ Fixture* Body::AddRectShape(Vec2 const& size, float density, float friction, flo Fixture::Param param(density, friction, restitution, is_sensor); FixturePtr fixture = Fixture::CreateRect(this, param, size); AddFixture(fixture); - return fixture.get(); + return fixture.Get(); } Fixture* Body::AddPolygonShape(Vector const& vertexs, float density, float friction, float restitution, @@ -101,7 +101,7 @@ Fixture* Body::AddPolygonShape(Vector const& vertexs, float density, floa Fixture::Param param(density, friction, restitution, is_sensor); FixturePtr fixture = Fixture::CreatePolygon(this, param, vertexs); AddFixture(fixture); - return fixture.get(); + return fixture.Get(); } Fixture* Body::AddEdgeShape(Point const& p1, Point const& p2, float density, float friction, float restitution, @@ -110,7 +110,7 @@ Fixture* Body::AddEdgeShape(Point const& p1, Point const& p2, float density, flo Fixture::Param param(density, friction, restitution, is_sensor); FixturePtr fixture = Fixture::CreateEdge(this, param, p1, p2); AddFixture(fixture); - return fixture.get(); + return fixture.Get(); } Fixture* Body::AddChainShape(Vector const& vertexs, bool loop, float density, float friction, float restitution, @@ -119,7 +119,7 @@ Fixture* Body::AddChainShape(Vector const& vertexs, bool loop, float dens Fixture::Param param(density, friction, restitution, is_sensor); FixturePtr fixture = Fixture::CreateChain(this, param, vertexs, loop); AddFixture(fixture); - return fixture.get(); + return fixture.Get(); } void Body::RemoveFixture(FixturePtr fixture) diff --git a/src/kiwano-physics/Body.h b/src/kiwano-physics/Body.h index 172835b4..5b46cde1 100644 --- a/src/kiwano-physics/Body.h +++ b/src/kiwano-physics/Body.h @@ -343,12 +343,12 @@ private: inline BodyPtr Body::Create(World* world, ActorPtr actor, Type type) { - return Body::Create(world, actor.get(), type); + return Body::Create(world, actor.Get(), type); } inline bool Body::InitBody(World* world, ActorPtr actor) { - return InitBody(world, actor.get()); + return InitBody(world, actor.Get()); } inline FixtureList Body::GetFixtureList() const diff --git a/src/kiwano-physics/Fixture.cpp b/src/kiwano-physics/Fixture.cpp index 10b7969a..fd2d5588 100644 --- a/src/kiwano-physics/Fixture.cpp +++ b/src/kiwano-physics/Fixture.cpp @@ -49,7 +49,7 @@ FixturePtr CreateFixture(Body* body, b2Shape* shape, const Fixture::Param& param b2Fixture* fixture = b2body->CreateFixture(&fd); if (fixture) { - fixture->SetUserData(ptr.get()); + fixture->SetUserData(ptr.Get()); ptr->SetB2Fixture(fixture); return ptr; } diff --git a/src/kiwano-physics/Joint.h b/src/kiwano-physics/Joint.h index 1e63e1a1..8301637d 100644 --- a/src/kiwano-physics/Joint.h +++ b/src/kiwano-physics/Joint.h @@ -81,8 +81,8 @@ public: } ParamBase(BodyPtr body_a, BodyPtr body_b) - : body_a(body_a.get()) - , body_b(body_b.get()) + : body_a(body_a.Get()) + , body_b(body_b.Get()) { } }; @@ -146,7 +146,7 @@ public: Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor_a, Point const& anchor_b, float frequency_hz = 0.f, float damping_ratio = 0.f) - : Param(body_a.get(), body_b.get(), anchor_a, anchor_b, frequency_hz, damping_ratio) + : Param(body_a.Get(), body_b.Get(), anchor_a, anchor_b, frequency_hz, damping_ratio) { } }; @@ -211,7 +211,7 @@ public: } Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, float max_force = 0.f, float max_torque = 0.f) - : Param(body_a.get(), body_b.get(), anchor, max_force, max_torque) + : Param(body_a.Get(), body_b.Get(), anchor, max_force, max_torque) { } }; @@ -270,7 +270,7 @@ public: } Param(JointPtr joint_a, JointPtr joint_b, float ratio = 1.f) - : Param(joint_a.get(), joint_b.get(), ratio) + : Param(joint_a.Get(), joint_b.Get(), ratio) { } }; @@ -323,7 +323,7 @@ public: Param(BodyPtr body_a, BodyPtr body_b, float max_force = 0.f, float max_torque = 0.f, float correction_factor = 0.3f) - : Param(body_a.get(), body_b.get(), max_force, max_torque, correction_factor) + : Param(body_a.Get(), body_b.Get(), max_force, max_torque, correction_factor) { } }; @@ -396,7 +396,7 @@ public: Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, Vec2 const& axis, bool enable_limit = false, float lower_translation = 0.0f, float upper_translation = 0.0f, bool enable_motor = false, float max_motor_force = 0.0f, float motor_speed = 0.0f) - : Param(body_a.get(), body_b.get(), anchor, axis, enable_limit, lower_translation, upper_translation, + : Param(body_a.Get(), body_b.Get(), anchor, axis, enable_limit, lower_translation, upper_translation, enable_motor, max_motor_force, motor_speed) { } @@ -502,7 +502,7 @@ public: Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor_a, Point const& anchor_b, Point const& ground_anchor_a, Point const& ground_anchor_b, float ratio = 1.0f) - : Param(body_a.get(), body_b.get(), anchor_a, anchor_b, ground_anchor_a, ground_anchor_b, ratio) + : Param(body_a.Get(), body_b.Get(), anchor_a, anchor_b, ground_anchor_a, ground_anchor_b, ratio) { } }; @@ -585,7 +585,7 @@ public: Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, bool enable_limit = false, float lower_angle = 0.0f, float upper_angle = 0.0f, bool enable_motor = false, float max_motor_torque = 0.0f, float motor_speed = 0.0f) - : Param(body_a.get(), body_b.get(), anchor, enable_limit, lower_angle, upper_angle, enable_motor, + : Param(body_a.Get(), body_b.Get(), anchor, enable_limit, lower_angle, upper_angle, enable_motor, max_motor_torque, motor_speed) { } @@ -687,7 +687,7 @@ public: Param(BodyPtr body_a, BodyPtr body_b, Point const& local_anchor_a, Point const& local_anchor_b, float max_length = 0.f) - : Param(body_a.get(), body_b.get(), local_anchor_a, local_anchor_b, max_length) + : Param(body_a.Get(), body_b.Get(), local_anchor_a, local_anchor_b, max_length) { } }; @@ -738,7 +738,7 @@ public: } Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, float frequency_hz = 0.f, float damping_ratio = 0.f) - : Param(body_a.get(), body_b.get(), anchor, frequency_hz, damping_ratio) + : Param(body_a.Get(), body_b.Get(), anchor, frequency_hz, damping_ratio) { } }; @@ -813,7 +813,7 @@ public: Param(BodyPtr body_a, BodyPtr body_b, Point const& anchor, Vec2 const& axis, float frequency_hz = 2.0f, float damping_ratio = 0.7f, bool enable_motor = false, float max_motor_torque = 0.0f, float motor_speed = 0.0f) - : Param(body_a.get(), body_b.get(), anchor, axis, frequency_hz, damping_ratio, enable_motor, + : Param(body_a.Get(), body_b.Get(), anchor, axis, frequency_hz, damping_ratio, enable_motor, max_motor_torque, motor_speed) { } @@ -918,7 +918,7 @@ public: Param(BodyPtr body_a, BodyPtr body_b, Point const& target, float max_force, float frequency_hz = 5.0f, float damping_ratio = 0.7f) - : Param(body_a.get(), body_b.get(), target, max_force, frequency_hz, damping_ratio) + : Param(body_a.Get(), body_b.Get(), target, max_force, frequency_hz, damping_ratio) { } }; diff --git a/src/kiwano-physics/World.cpp b/src/kiwano-physics/World.cpp index 86e828a6..0b0f4cbc 100644 --- a/src/kiwano-physics/World.cpp +++ b/src/kiwano-physics/World.cpp @@ -68,7 +68,7 @@ public: contact.SetB2Contact(b2contact); ContactBeginEventPtr evt = new ContactBeginEvent(contact); - world_->DispatchEvent(evt.get()); + world_->DispatchEvent(evt.Get()); } void EndContact(b2Contact* b2contact) override @@ -77,7 +77,7 @@ public: contact.SetB2Contact(b2contact); ContactEndEventPtr evt = new ContactEndEvent(contact); - world_->DispatchEvent(evt.get()); + world_->DispatchEvent(evt.Get()); } void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp index faca7585..458f0353 100644 --- a/src/kiwano/2d/Actor.cpp +++ b/src/kiwano/2d/Actor.cpp @@ -83,12 +83,12 @@ void Actor::Update(Duration dt) OnUpdate(dt); } - if (!children_.empty()) + if (!children_.IsEmpty()) { ActorPtr next; - for (auto child = children_.first_item(); child; child = next) + for (auto child = children_.GetFirst(); child; child = next) { - next = child->next_item(); + next = child->GetNext(); child->Update(dt); } } @@ -101,7 +101,7 @@ void Actor::Render(RenderContext& ctx) UpdateTransform(); - if (children_.empty()) + if (children_.IsEmpty()) { if (CheckVisibility(ctx)) { @@ -112,14 +112,14 @@ void Actor::Render(RenderContext& ctx) else { // render children those are less than 0 in Z-Order - Actor* child = children_.first_item().get(); + ActorPtr child = children_.GetFirst(); while (child) { if (child->GetZOrder() >= 0) break; child->Render(ctx); - child = child->next_item().get(); + child = child->GetNext(); } if (CheckVisibility(ctx)) @@ -131,7 +131,7 @@ void Actor::Render(RenderContext& ctx) while (child) { child->Render(ctx); - child = child->next_item().get(); + child = child->GetNext(); } } } @@ -157,9 +157,9 @@ void Actor::RenderBorder(RenderContext& ctx) ctx.DrawRectangle(bounds, nullptr, 2.f); } - for (auto child = children_.first_item(); child; child = child->next_item()) + for (auto& child : children_) { - child->RenderBorder(ctx); + child.RenderBorder(ctx); } } @@ -187,7 +187,7 @@ bool Actor::DispatchEvent(Event* evt) return true; // Dispatch to children those are greater than 0 in Z-Order - Actor* child = children_.last_item().get(); + ActorPtr child = children_.GetLast(); while (child) { if (child->GetZOrder() < 0) @@ -196,7 +196,7 @@ bool Actor::DispatchEvent(Event* evt) if (!child->DispatchEvent(evt)) return false; - child = child->prev_item().get(); + child = child->GetPrev(); } if (!EventDispatcher::DispatchEvent(evt)) @@ -209,7 +209,7 @@ bool Actor::DispatchEvent(Event* evt) if (!child->DispatchEvent(evt)) return false; - child = child->prev_item().get(); + child = child->GetPrev(); } return true; } @@ -228,7 +228,7 @@ void Actor::HandleEvent(Event* evt) MouseHoverEventPtr hover = new MouseHoverEvent; hover->pos = mouse_evt->pos; - EventDispatcher::DispatchEvent(hover.get()); + EventDispatcher::DispatchEvent(hover.Get()); } else if (hover_ && !contains) { @@ -237,7 +237,7 @@ void Actor::HandleEvent(Event* evt) MouseOutEventPtr out = new MouseOutEvent; out->pos = mouse_evt->pos; - EventDispatcher::DispatchEvent(out.get()); + EventDispatcher::DispatchEvent(out.Get()); } } @@ -255,7 +255,7 @@ void Actor::HandleEvent(Event* evt) MouseClickEventPtr click = new MouseClickEvent; click->pos = mouse_up_evt->pos; click->button = mouse_up_evt->button; - EventDispatcher::DispatchEvent(click.get()); + EventDispatcher::DispatchEvent(click.Get()); } } } @@ -304,8 +304,8 @@ void Actor::UpdateTransform() const } // update children's transform - for (auto child = children_.first_item().get(); child; child = child->next_item().get()) - child->dirty_transform_ = true; + for (const auto& child : children_) + child.dirty_transform_ = true; } void Actor::UpdateOpacity() @@ -319,9 +319,9 @@ void Actor::UpdateOpacity() displayed_opacity_ = opacity_; } - for (Actor* child = children_.first_item().get(); child; child = child->next_item().get()) + for (auto& child : children_) { - child->UpdateOpacity(); + child.UpdateOpacity(); } } @@ -330,9 +330,9 @@ void Actor::SetStage(Stage* stage) if (stage_ != stage) { stage_ = stage; - for (Actor* child = children_.first_item().get(); child; child = child->next_item().get()) + for (auto& child : children_) { - child->stage_ = stage; + child.stage_ = stage; } } } @@ -343,28 +343,28 @@ void Actor::Reorder() { ActorPtr me = this; - parent_->children_.remove(me); + parent_->children_.Remove(me.Get()); - Actor* sibling = parent_->children_.last_item().get(); + ActorPtr sibling = parent_->children_.GetLast(); if (sibling && sibling->GetZOrder() > z_order_) { - sibling = sibling->prev_item().get(); + sibling = sibling->GetPrev(); while (sibling) { if (sibling->GetZOrder() <= z_order_) break; - sibling = sibling->prev_item().get(); + sibling = sibling->GetPrev(); } } if (sibling) { - parent_->children_.insert_after(me, sibling); + parent_->children_.InsertAfter(me.Get(), sibling); } else { - parent_->children_.push_front(me); + parent_->children_.PushFront(me.Get()); } } } @@ -520,7 +520,7 @@ void Actor::AddChild(Actor* child, int zorder) #endif // KGE_DEBUG - children_.push_back(child); + children_.PushBack(child); child->parent_ = this; child->SetStage(this->stage_); @@ -533,7 +533,7 @@ void Actor::AddChild(Actor* child, int zorder) void Actor::AddChild(ActorPtr child, int zorder) { - AddChild(child.get()); + AddChild(child.Get()); } void Actor::AddChildren(Vector const& children) @@ -559,25 +559,25 @@ Vector Actor::GetChildren(String const& name) const Vector children; size_t hash_code = std::hash{}(name); - for (auto child = children_.first_item().get(); child; child = child->next_item().get()) + for (const auto& child : children_) { - if (child->hash_name_ == hash_code && child->IsName(name)) + if (child.hash_name_ == hash_code && child.IsName(name)) { - children.push_back(const_cast(child)); + children.push_back(const_cast(&child)); } } return children; } -Actor* Actor::GetChild(String const& name) const +ActorPtr Actor::GetChild(String const& name) const { size_t hash_code = std::hash{}(name); - for (auto child = children_.first_item().get(); child; child = child->next_item().get()) + for (const auto& child : children_) { - if (child->hash_name_ == hash_code && child->IsName(name)) + if (child.hash_name_ == hash_code && child.IsName(name)) { - return const_cast(child); + return const_cast(&child); } } return nullptr; @@ -603,14 +603,14 @@ void Actor::RemoveFromParent() void Actor::RemoveChild(ActorPtr child) { - RemoveChild(child.get()); + RemoveChild(child.Get()); } void Actor::RemoveChild(Actor* child) { KGE_ASSERT(child && "Actor::RemoveChild failed, NULL pointer exception"); - if (children_.empty()) + if (children_.IsEmpty()) return; if (child) @@ -618,23 +618,23 @@ void Actor::RemoveChild(Actor* child) child->parent_ = nullptr; if (child->stage_) child->SetStage(nullptr); - children_.remove(ActorPtr(child)); + children_.Remove(child); } } void Actor::RemoveChildren(String const& child_name) { - if (children_.empty()) + if (children_.IsEmpty()) { return; } size_t hash_code = std::hash{}(child_name); - Actor* next; - for (Actor* child = children_.first_item().get(); child; child = next) + ActorPtr next; + for (ActorPtr child = children_.GetFirst(); child; child = next) { - next = child->next_item().get(); + next = child->GetNext(); if (child->hash_name_ == hash_code && child->IsName(child_name)) { @@ -645,7 +645,7 @@ void Actor::RemoveChildren(String const& child_name) void Actor::RemoveAllChildren() { - children_.clear(); + children_.Clear(); } void Actor::SetResponsible(bool enable) diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h index 49cd0c92..bbcb2df2 100644 --- a/src/kiwano/2d/Actor.h +++ b/src/kiwano/2d/Actor.h @@ -24,6 +24,7 @@ #include #include #include +#include #include namespace kiwano @@ -55,7 +56,7 @@ class KGE_API Actor , public TimerManager , public ActionManager , public EventDispatcher - , protected IntrusiveListItem + , protected IntrusiveListValue { friend class Director; friend class Transition; @@ -334,7 +335,7 @@ public: /// \~chinese /// @brief 获取名称相同的子角色 - Actor* GetChild(String const& name) const; + ActorPtr GetChild(String const& name) const; /// \~chinese /// @brief 获取所有名称相同的子角色 diff --git a/src/kiwano/2d/action/Action.h b/src/kiwano/2d/action/Action.h index 21826b5c..da1a4acf 100644 --- a/src/kiwano/2d/action/Action.h +++ b/src/kiwano/2d/action/Action.h @@ -23,6 +23,7 @@ #include #include #include +#include #include namespace kiwano @@ -46,7 +47,7 @@ KGE_DECLARE_SMART_PTR(Action); /// @brief 动画 class KGE_API Action : public virtual ObjectBase - , protected IntrusiveListItem + , protected IntrusiveListValue { friend class ActionManager; friend class ActionGroup; diff --git a/src/kiwano/2d/action/ActionGroup.cpp b/src/kiwano/2d/action/ActionGroup.cpp index 2bade281..77587726 100644 --- a/src/kiwano/2d/action/ActionGroup.cpp +++ b/src/kiwano/2d/action/ActionGroup.cpp @@ -49,23 +49,25 @@ ActionGroup::~ActionGroup() {} void ActionGroup::Init(Actor* target) { - if (actions_.empty()) + if (actions_.IsEmpty()) { Done(); return; } - current_ = actions_.first_item(); - current_->Restart(target); // init first action - if (sync_) { // init all actions - for (; current_; current_ = current_->next_item()) + for (current_ = actions_.GetFirst(); current_; current_ = current_->GetNext()) { current_->Restart(target); } } + else + { + current_ = actions_.GetFirst(); + current_->Restart(target); // init first action + } } void ActionGroup::Update(Actor* target, Duration dt) @@ -78,7 +80,7 @@ void ActionGroup::Update(Actor* target, Duration dt) if (current_->IsDone()) { - current_ = current_->next_item(); + current_ = current_->GetNext(); if (current_) current_->Restart(target); // init next action @@ -90,7 +92,7 @@ void ActionGroup::Update(Actor* target, Duration dt) else { bool done = true; - for (current_ = actions_.first_item(); current_; current_ = current_->next_item()) + for (current_ = actions_.GetFirst(); current_; current_ = current_->GetNext()) { if (!current_->IsDone()) { @@ -110,7 +112,7 @@ void ActionGroup::AddAction(ActionPtr action) { if (action) { - actions_.push_back(action); + actions_.PushBack(action); } } @@ -123,9 +125,9 @@ void ActionGroup::AddActions(Vector const& actions) ActionPtr ActionGroup::Clone() const { Vector actions; - if (!actions_.empty()) + if (!actions_.IsEmpty()) { - for (auto action = actions_.last_item(); action; action = action->prev_item()) + for (auto action = actions_.GetLast(); action; action = action->GetPrev()) { actions.push_back(action->Clone()); } @@ -136,9 +138,9 @@ ActionPtr ActionGroup::Clone() const ActionPtr ActionGroup::Reverse() const { Vector actions; - if (!actions_.empty()) + if (!actions_.IsEmpty()) { - for (auto action = actions_.last_item(); action; action = action->prev_item()) + for (auto action = actions_.GetLast(); action; action = action->GetPrev()) { actions.push_back(action->Reverse()); } diff --git a/src/kiwano/2d/action/ActionManager.cpp b/src/kiwano/2d/action/ActionManager.cpp index 1fb6683b..426636e1 100644 --- a/src/kiwano/2d/action/ActionManager.cpp +++ b/src/kiwano/2d/action/ActionManager.cpp @@ -26,25 +26,25 @@ namespace kiwano { void ActionManager::UpdateActions(Actor* target, Duration dt) { - if (actions_.empty() || !target) + if (actions_.IsEmpty() || !target) return; ActionPtr next; - for (auto action = actions_.first_item(); action; action = next) + for (auto action = actions_.GetFirst(); action; action = next) { - next = action->next_item(); + next = action->GetNext(); if (action->IsRunning()) action->UpdateStep(target, dt); if (action->IsRemoveable()) - actions_.remove(action); + actions_.Remove(action); } } Action* ActionManager::AddAction(ActionPtr action) { - return AddAction(action.get()); + return AddAction(action.Get()); } Action* ActionManager::AddAction(Action* action) @@ -53,14 +53,14 @@ Action* ActionManager::AddAction(Action* action) if (action) { - actions_.push_back(action); + actions_.PushBack(action); } return action; } void ActionManager::ResumeAllActions() { - if (actions_.empty()) + if (actions_.IsEmpty()) return; for (auto& action : actions_) @@ -71,7 +71,7 @@ void ActionManager::ResumeAllActions() void ActionManager::PauseAllActions() { - if (actions_.empty()) + if (actions_.IsEmpty()) return; for (auto& action : actions_) @@ -82,7 +82,7 @@ void ActionManager::PauseAllActions() void ActionManager::StopAllActions() { - if (actions_.empty()) + if (actions_.IsEmpty()) return; for (auto& action : actions_) @@ -93,7 +93,7 @@ void ActionManager::StopAllActions() ActionPtr ActionManager::GetAction(String const& name) { - if (actions_.empty()) + if (actions_.IsEmpty()) return nullptr; for (auto& action : actions_) diff --git a/src/kiwano/core/Any.h b/src/kiwano/core/Any.h new file mode 100644 index 00000000..d4a177f7 --- /dev/null +++ b/src/kiwano/core/Any.h @@ -0,0 +1,464 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include +#include + +namespace kiwano +{ + +/// \~chinese +/// @brief 可储存单个任意对象的容器 +class Any +{ +public: + Any() + : storage_{} + { + } + + template ::type, + typename std::enable_if::value, int>::type = 0> + Any(_Ty&& val) + : storage_{} + { + Emplace<_Decayed>(std::forward<_Ty>(val)); + } + + template + Any(_Args&&... args) + : storage_{} + { + using _Decayed = typename std::decay<_Ty>::type; + + Clear(); + EmplaceDecayed<_Decayed>(std::forward<_Args>(args)...); + } + + Any(const Any& rhs) + : storage_{} + { + CopyFrom(rhs); + } + + Any(Any&& rhs) noexcept + : storage_{} + { + MoveFrome(std::move(rhs)); + } + + ~Any() + { + Clear(); + } + + /// \~chinese + /// @brief 获取含有对象类型 + inline const type_info& GetType() const noexcept + { + const type_info* const info = GetTypeinfo(); + if (info) + { + return *info; + } + return typeid(void); + } + + /// \~chinese + /// @brief 是否含有对象 + inline bool HasValue() const noexcept + { + return GetTypeinfo() != nullptr; + } + + /// \~chinese + /// @brief 从参数构造对象 + template + void Emplace(_Args&&... args) + { + using _Decayed = typename std::decay<_Ty>::type; + + Clear(); + EmplaceDecayed<_Decayed>(std::forward<_Args>(args)...); + } + + /// \~chinese + /// @brief 交换容器 + void Swap(Any& rhs) noexcept + { + Any old = std::move(rhs); + rhs = std::move(*this); + *this = std::move(old); + } + + /// \~chinese + /// @brief 销毁所含对象 + inline void Clear() noexcept + { + Tidy(); + } + + /// \~chinese + /// @brief 转换为指定类型的指针 + template + _Ty* CastPtr() noexcept + { + return const_cast<_Ty*>(const_cast(this)->CastPtr<_Ty>()); + } + + /// \~chinese + /// @brief 转换为指定类型的指针 + template + const _Ty* CastPtr() const noexcept + { + static_assert(!std::is_void<_Ty>::value, "oc::Any cannot contain void"); + + const type_info* const info = GetTypeinfo(); + if (info && (*info == typeid(std::decay<_Ty>::type))) + { + if (HasSmallType()) + { + return static_cast(GetSmallData()); + } + else + { + return static_cast(GetBigData()); + } + } + return nullptr; + } + + /// \~chinese + /// @brief 转换为指定类型 + /// @throw std::bad_cast 转换失败时抛出 + template + _Ty Cast() + { + using _Decayed = typename std::decay<_Ty>::type; + + const auto ptr = CastPtr<_Decayed>(); + if (!ptr) + { + throw std::bad_cast(); + } + return static_cast<_Ty>(*ptr); + } + + /// \~chinese + /// @brief 转换为指定类型 + /// @throw std::bad_cast 转换失败时抛出 + template + _Ty Cast() const + { + using _Decayed = typename std::decay<_Ty>::type; + + const auto ptr = CastPtr<_Decayed>(); + if (!ptr) + { + throw std::bad_cast(); + } + return static_cast<_Ty>(*ptr); + } + + Any& operator=(const Any& rhs) + { + *this = Any(rhs); + return (*this); + } + + Any& operator=(Any&& rhs) noexcept + { + Clear(); + MoveFrome(std::move(rhs)); + return (*this); + } + +private: + const type_info*& GetTypeinfo() + { + return storage_.small_.info_; + } + + const type_info* GetTypeinfo() const + { + return storage_.small_.info_; + } + + template + inline void EmplaceDecayed(_Args&&... args) + { + Store<_Decayed>(IsSmallSize<_Decayed>{}, std::forward<_Args>(args)...); + } + + template + void Store(std::true_type, _Args&&... args) + { + storage_.is_small_ = true; + GetTypeinfo() = &typeid(_Decayed); + GetSmallRTTI() = SmallStorageRTTI::make<_Decayed>(); + + ::new (GetSmallData()) _Decayed(std::forward<_Args>(args)...); + } + + template + void Store(std::false_type, _Args&&... args) + { + storage_.is_small_ = false; + GetTypeinfo() = &typeid(_Decayed); + GetBigRTTI() = BigStorageRTTI::make<_Decayed>(); + + GetBigData() = ::new _Decayed(std::forward<_Args>(args)...); + } + + void Tidy() noexcept + { + if (HasValue()) + { + if (HasSmallType()) + { + GetSmallRTTI().destroy(GetSmallData()); + } + else + { + GetBigRTTI().destroy(GetBigData()); + GetBigData() = nullptr; + } + GetTypeinfo() = nullptr; + } + } + + void CopyFrom(const Any& rhs) + { + if (rhs.HasValue()) + { + GetTypeinfo() = rhs.GetTypeinfo(); + storage_.is_small_ = rhs.storage_.is_small_; + + if (rhs.HasSmallType()) + { + GetSmallRTTI() = rhs.GetSmallRTTI(); + GetSmallRTTI().copy(GetSmallData(), rhs.GetSmallData()); + } + else + { + GetBigRTTI() = rhs.GetBigRTTI(); + GetBigData() = GetBigRTTI().copy(rhs.GetBigData()); + } + } + } + + void MoveFrome(Any&& rhs) noexcept + { + if (rhs.HasValue()) + { + GetTypeinfo() = rhs.GetTypeinfo(); + storage_.is_small_ = rhs.storage_.is_small_; + + if (rhs.HasSmallType()) + { + GetSmallRTTI() = rhs.GetSmallRTTI(); + GetSmallRTTI().move(GetSmallData(), rhs.GetSmallData()); + } + else + { + GetBigRTTI() = rhs.GetBigRTTI(); + GetBigData() = rhs.GetBigData(); + rhs.GetTypeinfo() = nullptr; + } + } + } + + inline void* GetSmallData() + { + return storage_.small_.buffer_; + } + + inline const void* GetSmallData() const + { + return storage_.small_.buffer_; + } + + inline void*& GetBigData() + { + return storage_.big_.ptr_; + } + + inline void* GetBigData() const + { + return storage_.big_.ptr_; + } + + inline bool HasSmallType() const + { + return storage_.is_small_; + } + +private: + static const auto ANY_SMALL_SPACE_SIZE = 8U; + + template + struct IsSmallSize : public std::bool_constant + { + }; + + struct BigStorageRTTI + { + using DestroyFunc = void(void*); + using CopyFunc = void*(const void*); + + BigStorageRTTI() + { + destroy = nullptr; + copy = nullptr; + } + + template + static inline BigStorageRTTI make() + { + BigStorageRTTI rtti; + rtti.destroy = &BigStorageRTTI::Destroy<_Ty>; + rtti.copy = &BigStorageRTTI::Copy<_Ty>; + return rtti; + } + + template + static void Destroy(void* const ptr) noexcept + { + ::delete static_cast<_Ty*>(ptr); + } + + template + static void* Copy(const void* const ptr) noexcept + { + return ::new _Ty(*static_cast(ptr)); + } + + DestroyFunc* destroy; + CopyFunc* copy; + }; + + struct SmallStorageRTTI + { + using DestroyFunc = void(void*); + using CopyFunc = void*(void*, const void*); + using MoveFunc = void*(void*, void*); + + SmallStorageRTTI() + { + destroy = nullptr; + copy = nullptr; + move = nullptr; + } + + template + static inline SmallStorageRTTI make() + { + SmallStorageRTTI rtti; + rtti.destroy = &SmallStorageRTTI::Destroy<_Ty>; + rtti.copy = &SmallStorageRTTI::Copy<_Ty>; + rtti.move = &SmallStorageRTTI::Move<_Ty>; + return rtti; + } + + template + static void Destroy(void* const ptr) noexcept + { + if (ptr) + { + _Ty& obj = *(static_cast<_Ty* const>(ptr)); + obj.~_Ty(); + } + } + + template + static void* Copy(void* const target, const void* const ptr) noexcept + { + return ::new (static_cast<_Ty*>(target)) _Ty(*static_cast(ptr)); + } + + template + static void* Move(void* const target, void* const ptr) noexcept + { + return ::new (static_cast<_Ty*>(target)) _Ty(std::move(*static_cast<_Ty*>(ptr))); + } + + DestroyFunc* destroy; + CopyFunc* copy; + MoveFunc* move; + }; + +private: + inline SmallStorageRTTI& GetSmallRTTI() + { + return storage_.small_.rtti_; + } + + inline const SmallStorageRTTI& GetSmallRTTI() const + { + return storage_.small_.rtti_; + } + + inline BigStorageRTTI& GetBigRTTI() + { + return storage_.big_.rtti_; + } + + inline const BigStorageRTTI& GetBigRTTI() const + { + return storage_.big_.rtti_; + } + +private: + struct SmallStorage + { + const type_info* info_; + SmallStorageRTTI rtti_; + char buffer_[ANY_SMALL_SPACE_SIZE]; + }; + + struct BigStorage + { + const type_info* info_; + BigStorageRTTI rtti_; + void* ptr_; + }; + + struct Storage + { + bool is_small_; + union + { + SmallStorage small_; + BigStorage big_; + }; + + Storage() + : is_small_(false) + , small_() + { + } // fix error C2280 for VisualStudio 2015 + }; + + Storage storage_; +}; + +} // namespace kiwano diff --git a/src/kiwano/core/Common.h b/src/kiwano/core/Common.h index 283970a7..cb7a74cf 100644 --- a/src/kiwano/core/Common.h +++ b/src/kiwano/core/Common.h @@ -29,9 +29,10 @@ #include #include #include +#include +#include #include -#include <3rd-party/OuterC/oc/oc.h> -#include <3rd-party/nlohmann/json.hpp> +#include namespace kiwano { @@ -44,14 +45,6 @@ using InputStream = std::istream; /// @brief 输出流 using OutputStream = std::ostream; -/// \~chinese -/// @brief 字符串容器 -using String = oc::string; - -/// \~chinese -/// @brief 宽字符串容器 -using WideString = oc::wstring; - /// \~chinese /// @brief 字符串流 using StringStream = std::stringstream; @@ -105,84 +98,17 @@ using Map = std::map<_Kty, _Ty, _Args...>; template using UnorderedMap = std::unordered_map<_Kty, _Ty, _Args...>; -/// \~chinese -/// @brief 函数封装器 -template -using Function = oc::function<_FuncTy>; - -/// \~chinese -/// @brief 单值容器 -using Any = oc::any; - -/// \~chinese -/// @brief 侵入式链表容器 -template -using IntrusiveList = oc::intrusive_list<_Ty>; - -/// \~chinese -/// @brief 侵入式链表元素 -template -using IntrusiveListItem = oc::intrusive_list_item<_Ty>; - -/// \~chinese -/// @brief 侵入式智能指针 -template -using IntrusivePtr = oc::intrusive_ptr<_Ty, _RefProxyTy>; - -/// \~chinese -/// @brief JSON对象容器 -using Json = nlohmann::basic_json; - /// \~chinese /// @brief 不可拷贝对象 -using Noncopyable = oc::noncopyable; - -/// \~chinese -/// @brief 闭包函数 -template -inline Function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret (_Ty::*func)(_Args...)) +class Noncopyable { - return oc::closure(ptr, func); -} +protected: + Noncopyable() = default; -/// \~chinese -/// @brief 闭包函数 -template -inline Function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret (_Ty::*func)(_Args...) const) -{ - return oc::closure(ptr, func); -} +private: + Noncopyable(const Noncopyable&) = delete; -#if defined(KGE_WIN32) - -inline String WideToMultiByte(const WideString& str) -{ - int chars_num = ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, NULL, 0, NULL, NULL); - if (chars_num) - { - String result; - result.resize(chars_num); - - ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, &result[0], chars_num, NULL, NULL); - return result; - } - return String(); -} - -inline WideString MultiByteToWide(const String& str) -{ - int wchars_num = ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0); - if (wchars_num) - { - WideString result; - result.resize(wchars_num); - - ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &result[0], wchars_num); - return result; - } - return WideString(); -} - -#endif // KGE_WIN32 + Noncopyable& operator=(const Noncopyable&) = delete; +}; } // namespace kiwano diff --git a/src/kiwano/core/Director.cpp b/src/kiwano/core/Director.cpp index 1c02bed2..d3fb8373 100644 --- a/src/kiwano/core/Director.cpp +++ b/src/kiwano/core/Director.cpp @@ -104,7 +104,7 @@ void Director::ShowDebugInfo(bool show) } else { - debug_actor_.reset(); + debug_actor_.Reset(); } } @@ -113,10 +113,10 @@ void Director::ClearStages() while (!stages_.empty()) stages_.pop(); - current_stage_.reset(); - next_stage_.reset(); - transition_.reset(); - debug_actor_.reset(); + current_stage_.Reset(); + next_stage_.Reset(); + transition_.Reset(); + debug_actor_.Reset(); } void Director::OnUpdate(Duration dt) diff --git a/src/kiwano/core/EventDispatcher.cpp b/src/kiwano/core/EventDispatcher.cpp index 01214939..3c349f19 100644 --- a/src/kiwano/core/EventDispatcher.cpp +++ b/src/kiwano/core/EventDispatcher.cpp @@ -25,19 +25,19 @@ namespace kiwano { bool EventDispatcher::DispatchEvent(Event* evt) { - if (listeners_.empty()) + if (listeners_.IsEmpty()) return true; EventListenerPtr next; - for (auto listener = listeners_.first_item(); listener; listener = next) + for (auto listener = listeners_.GetFirst(); listener; listener = next) { - next = listener->next_item(); + next = listener->GetNext(); if (listener->IsRunning()) listener->Receive(evt); if (listener->IsRemoveable()) - listeners_.remove(listener); + listeners_.Remove(listener); if (listener->IsSwallowEnabled()) return false; @@ -47,7 +47,7 @@ bool EventDispatcher::DispatchEvent(Event* evt) EventListener* EventDispatcher::AddListener(EventListenerPtr listener) { - return AddListener(listener.get()); + return AddListener(listener.Get()); } EventListener* EventDispatcher::AddListener(EventListener* listener) @@ -56,7 +56,7 @@ EventListener* EventDispatcher::AddListener(EventListener* listener) if (listener) { - listeners_.push_back(listener); + listeners_.PushBack(listener); } return listener; } diff --git a/src/kiwano/core/EventListener.h b/src/kiwano/core/EventListener.h index 233ef52e..c9044427 100644 --- a/src/kiwano/core/EventListener.h +++ b/src/kiwano/core/EventListener.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,7 @@ KGE_DECLARE_SMART_PTR(EventListener); */ class KGE_API EventListener : public virtual ObjectBase - , protected IntrusiveListItem + , protected IntrusiveListValue { friend class EventDispatcher; friend IntrusiveList; diff --git a/src/kiwano/core/Exception.cpp b/src/kiwano/core/Exception.cpp index 81876f92..f01111f9 100644 --- a/src/kiwano/core/Exception.cpp +++ b/src/kiwano/core/Exception.cpp @@ -22,7 +22,7 @@ #include #include -#if defined(KGE_WIN32) +#if defined(KGE_PLATFORM_WINDOWS) #include namespace kiwano @@ -42,12 +42,7 @@ public: // converted to an ANSI string using the CP_ACP codepage. std::string message(int hr) const override { -#ifdef _UNICODE - auto message = WideToMultiByte(_com_error{ hr }.ErrorMessage()); - return message.c_str(); -#else - return _com_error{ hr }.ErrorMessage(); -#endif + return string::ToNarrow(_com_error{ hr }.ErrorMessage()); } // Make error_condition for error code (generic if possible) @@ -60,7 +55,7 @@ public: return std::system_category().default_error_condition(HRESULT_CODE(hr)); else // special error condition - return { hr, com_category() }; + return make_error_condition(error_enum(hr)); } }; diff --git a/src/kiwano/core/Exception.h b/src/kiwano/core/Exception.h index 22149590..6b001c48 100644 --- a/src/kiwano/core/Exception.h +++ b/src/kiwano/core/Exception.h @@ -23,23 +23,35 @@ #include #include -#define KGE_THROW(MESSAGE) \ - do \ - { \ - kiwano::StackTracer().Print(); \ - throw std::runtime_error(MESSAGE); \ +#define KGE_THROW(MESSAGE) \ + do \ + { \ + kiwano::StackTracer().Print(); \ + throw kiwano::RuntimeError(MESSAGE); \ } while (0) -#define KGE_THROW_SYSTEM_ERROR(ERRCODE, MESSAGE) \ - do \ - { \ - kiwano::StackTracer().Print(); \ - throw std::system_error(std::error_code(kiwano::error_enum(ERRCODE)), MESSAGE); \ +#define KGE_THROW_SYSTEM_ERROR(ERRCODE, MESSAGE) \ + do \ + { \ + kiwano::StackTracer().Print(); \ + throw kiwano::SystemError(std::error_code(kiwano::error_enum(ERRCODE)), MESSAGE); \ } while (0) namespace kiwano { +/// \~chinese +/// @brief 异常 +typedef std::exception Exception; + +/// \~chinese +/// @brief 运行时异常 +typedef std::runtime_error RuntimeError; + +/// \~chinese +/// @brief 系统异常 +typedef std::system_error SystemError; + class StackTracer { public: @@ -48,7 +60,7 @@ public: void Print() const; }; -#ifdef KGE_WIN32 +#ifdef KGE_PLATFORM_WINDOWS // Enables classifying error codes // @note We don't bother listing all possible values @@ -64,7 +76,7 @@ typedef std::errc error_enum; } // namespace kiwano -#ifdef KGE_WIN32 +#ifdef KGE_PLATFORM_WINDOWS namespace std { @@ -89,14 +101,12 @@ inline std::error_condition make_error_condition(kiwano::error_enum errc) noexce return std::error_condition(static_cast(errc), kiwano::com_category()); } -inline void ThrowIfFailed(HRESULT hr, const String& message) -{ - if (FAILED(hr)) - { - KGE_THROW_SYSTEM_ERROR(hr, message.c_str()); +#define KGE_THROW_IF_FAILED(HR, MESSAGE) \ + if (FAILED(HR)) \ + { \ + KGE_THROW_SYSTEM_ERROR(HR, MESSAGE); \ } -} } // namespace kiwano -#endif // KGE_WIN32 +#endif // KGE_PLATFORM_WINDOWS diff --git a/src/kiwano/core/Function.h b/src/kiwano/core/Function.h new file mode 100644 index 00000000..0f85e1af --- /dev/null +++ b/src/kiwano/core/Function.h @@ -0,0 +1,388 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include +#include +#include + +namespace kiwano +{ +namespace details +{ + +template +struct IsCallableHelper +{ + template + struct ClassMember; + + template + struct ClassConstMember; + + template + static int Test(...); + + template + static char Test(ClassMember<_Uty, &_Uty::operator()>*); + + template + static char Test(ClassConstMember<_Uty, &_Uty::operator()>*); + + template < + typename _Uty, + typename _Uret = typename std::decay().operator()(std::declval<_Args>()...))>::type, + typename = typename std::enable_if::value>::type> + static char Test(int); + + static constexpr bool value = sizeof(Test<_Ty>(0)) == sizeof(char); +}; + +template +struct IsCallable : public std::bool_constant::value> +{ +}; + +// +// Callable +// + +template +class Callable +{ +public: + virtual ~Callable() {} + + virtual void Retain() = 0; + virtual void Release() = 0; + virtual _Ret Invoke(_Args&&... args) const = 0; + + virtual const type_info& TargetType() const noexcept = 0; + + virtual const void* Target(const type_info& type) const noexcept = 0; +}; + +template +class RefCountCallable : public Callable<_Ret, _Args...> +{ +public: + RefCountCallable() + : ref_count_(0) + { + } + + virtual void Retain() override + { + ++ref_count_; + } + + virtual void Release() override + { + --ref_count_; + if (ref_count_ <= 0) + { + delete this; + } + } + +private: + int ref_count_; +}; + +template +class ProxyCallable : public RefCountCallable<_Ret, _Args...> +{ +public: + ProxyCallable(_Ty&& val) + : callee_(std::move(val)) + { + } + + virtual _Ret Invoke(_Args&&... args) const override + { + return std::invoke(callee_, std::forward<_Args>(args)...); + } + + virtual const type_info& TargetType() const noexcept + { + return typeid(_Ty); + } + + virtual const void* Target(const type_info& type) const noexcept + { + if (type == this->TargetType()) + return &callee_; + return nullptr; + } + + static inline Callable<_Ret, _Args...>* Make(_Ty&& val) + { + return new (std::nothrow) ProxyCallable<_Ty, _Ret, _Args...>(std::move(val)); + } + +private: + _Ty callee_; +}; + +template +class ProxyMemCallable : public RefCountCallable<_Ret, _Args...> +{ +public: + typedef _Ret (_Ty::*_FuncType)(_Args...); + + virtual _Ret Invoke(_Args&&... args) const override + { + return std::invoke(func_, ptr_, std::forward<_Args>(args)...); + } + + virtual const type_info& TargetType() const noexcept + { + return typeid(ProxyMemCallable); + } + + virtual const void* Target(const type_info& type) const noexcept + { + if (type == this->TargetType()) + return this; + return nullptr; + } + + static inline Callable<_Ret, _Args...>* Make(_Ty* ptr, _FuncType func) + { + return new (std::nothrow) ProxyMemCallable<_Ty, _Ret, _Args...>(ptr, func); + } + +protected: + ProxyMemCallable(_Ty* ptr, _FuncType func) + : ptr_(ptr) + , func_(func) + { + } + +protected: + _Ty* ptr_; + _FuncType func_; +}; + +template +class ProxyConstMemCallable : public RefCountCallable<_Ret, _Args...> +{ +public: + typedef _Ret (_Ty::*_FuncType)(_Args...) const; + + virtual _Ret Invoke(_Args&&... args) const override + { + return std::invoke(func_, ptr_, std::forward<_Args>(args)...); + } + + virtual const type_info& TargetType() const noexcept + { + return typeid(ProxyConstMemCallable); + } + + virtual const void* Target(const type_info& type) const noexcept + { + if (type == this->TargetType()) + return this; + return nullptr; + } + + static inline Callable<_Ret, _Args...>* Make(_Ty* ptr, _FuncType func) + { + return new (std::nothrow) ProxyConstMemCallable<_Ty, _Ret, _Args...>(ptr, func); + } + +protected: + ProxyConstMemCallable(_Ty* ptr, _FuncType func) + : ptr_(ptr) + , func_(func) + { + } + +protected: + _Ty* ptr_; + _FuncType func_; +}; + +} // namespace details + +template +class Function; + +template +class Function<_Ret(_Args...)> +{ +public: + Function() + : callable_(nullptr) + { + } + + Function(std::nullptr_t) + : callable_(nullptr) + { + } + + Function(const Function& rhs) + : callable_(nullptr) + { + SetCallable(rhs.callable_); + } + + Function(Function&& rhs) noexcept + : callable_(rhs.callable_) + { + rhs.callable_ = nullptr; + } + + Function(_Ret (*func)(_Args...)) + : callable_(nullptr) + { + SetCallable(details::ProxyCallable<_Ret (*)(_Args...), _Ret, _Args...>::Make(std::move(func))); + } + + template ::value, int>::type> + Function(_Ty val) + : callable_(nullptr) + { + SetCallable(details::ProxyCallable<_Ty, _Ret, _Args...>::Make(std::move(val))); + } + + template ::value || std::is_base_of<_Ty, _Uty>::value, + int>::type> + Function(_Uty* ptr, _Ret (_Ty::*func)(_Args...)) + : callable_(nullptr) + { + SetCallable(details::ProxyMemCallable<_Ty, _Ret, _Args...>::Make(ptr, func)); + } + + template ::value || std::is_base_of<_Ty, _Uty>::value, + int>::type> + Function(_Uty* ptr, _Ret (_Ty::*func)(_Args...) const) + : callable_(nullptr) + { + SetCallable(details::ProxyConstMemCallable<_Ty, _Ret, _Args...>::Make(ptr, func)); + } + + ~Function() + { + SetCallable(nullptr); + } + + inline _Ret operator()(_Args... args) const + { + if (!callable_) + throw std::bad_function_call(); + return callable_->Invoke(std::forward<_Args>(args)...); + } + + inline operator bool() const + { + return !!callable_; + } + + inline Function& operator=(const Function& rhs) + { + SetCallable(rhs.callable_); + return (*this); + } + + inline Function& operator=(Function&& rhs) + { + SetCallable(nullptr); + callable_ = rhs.callable_; + rhs.callable_ = nullptr; + return (*this); + } + + inline void swap(const Function& rhs) + { + std::swap(callable_, rhs.callable_); + } + + const type_info& target_type() const noexcept + { + return callable_->TargetType(); + } + + template + _Fx* target() noexcept + { + return reinterpret_cast<_Fx*>(const_cast(callable_->Target(typeid(_Fx)))); + } + + template + const _Fx* target() const noexcept + { + return reinterpret_cast(callable_->Target(typeid(_Fx))); + } + +private: + inline void SetCallable(details::Callable<_Ret, _Args...>* callable) + { + if (callable_ != callable) + { + if (callable_) + { + callable_->Release(); + callable_ = nullptr; + } + + callable_ = callable; + if (callable_) + { + callable_->Retain(); + } + } + } + +private: + details::Callable<_Ret, _Args...>* callable_; +}; + +template < + typename _Ty, typename _Uty, + typename = typename std::enable_if::value || std::is_base_of<_Ty, _Uty>::value, int>::type, + typename _Ret, typename... _Args> +inline Function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret (_Ty::*func)(_Args...)) +{ + return Function<_Ret(_Args...)>(ptr, func); +} + +template < + typename _Ty, typename _Uty, + typename = typename std::enable_if::value || std::is_base_of<_Ty, _Uty>::value, int>::type, + typename _Ret, typename... _Args> +inline Function<_Ret(_Args...)> Closure(_Uty* ptr, _Ret (_Ty::*func)(_Args...) const) +{ + return Function<_Ret(_Args...)>(ptr, func); +} + +template +inline void swap(kiwano::Function<_Ret(_Args...)>& lhs, kiwano::Function<_Ret(_Args...)>& rhs) noexcept +{ + lhs.swap(rhs); +} + +} // namespace kiwano diff --git a/src/kiwano/core/IntrusiveList.h b/src/kiwano/core/IntrusiveList.h new file mode 100644 index 00000000..dc15d560 --- /dev/null +++ b/src/kiwano/core/IntrusiveList.h @@ -0,0 +1,495 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include +#include +#include + +namespace kiwano +{ + +/// \~chinese +/// @brief 侵入式链表 +template +class IntrusiveList +{ +public: + using value_type = typename std::pointer_traits<_PtrTy>::element_type; + using pointer = typename std::pointer_traits<_PtrTy>::pointer; + using reference = value_type&; + + IntrusiveList() + : first_() + , last_() + { + } + + ~IntrusiveList() + { + Clear(); + } + + /// \~chinese + /// @brief 获取首元素 + const pointer GetFirst() const + { + return first_; + } + + /// \~chinese + /// @brief 获取首元素 + pointer GetFirst() + { + return first_; + } + + /// \~chinese + /// @brief 获取尾元素 + const pointer GetLast() const + { + return last_; + } + + /// \~chinese + /// @brief 获取尾元素 + pointer GetLast() + { + return last_; + } + + /// \~chinese + /// @brief 链表是否为空 + inline bool IsEmpty() const + { + return first_ == nullptr; + } + + /// \~chinese + /// @brief 在链表尾部添加对象 + void PushBack(pointer child) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + child->prev_ = last_; + child->next_ = nullptr; + + if (first_) + { + last_->next_ = child; + } + else + { + first_ = child; + } + + last_ = child; + } + + /// \~chinese + /// @brief 在链表头部添加对象 + void PushFront(pointer child) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + child->prev_ = nullptr; + child->next_ = first_; + + if (first_) + { + first_->prev_ = child; + } + else + { + last_ = child; + } + + first_ = child; + } + + /// \~chinese + /// @brief 在链表的对象前插入新对象 + void InsertBefore(pointer child, pointer before) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + if (before->prev_) + before->prev_->next_ = child; + else + first_ = child; + + child->prev_ = before->prev_; + child->next_ = before; + before->prev_ = child; + } + + /// \~chinese + /// @brief 在链表的对象后插入新对象 + void InsertAfter(pointer child, pointer after) + { + if (child->prev_) + child->prev_->next_ = child->next_; + if (child->next_) + child->next_->prev_ = child->prev_; + + if (after->next_) + after->next_->prev_ = child; + else + last_ = child; + + child->next_ = after->next_; + child->prev_ = after; + after->next_ = child; + } + + /// \~chinese + /// @brief 移除对象 + void Remove(pointer child) + { + if (child->next_) + { + child->next_->prev_ = child->prev_; + } + else + { + last_ = child->prev_; + } + + if (child->prev_) + { + child->prev_->next_ = child->next_; + } + else + { + first_ = child->next_; + } + + child->prev_ = nullptr; + child->next_ = nullptr; + } + + /// \~chinese + /// @brief 清空所有对象 + void Clear() + { + pointer p = first_; + while (p) + { + pointer tmp = p; + p = p->next_; + if (tmp) + { + tmp->next_ = nullptr; + tmp->prev_ = nullptr; + } + } + first_ = nullptr; + last_ = nullptr; + } + + /// \~chinese + /// @brief 检查链表是否有效 + bool CheckValid() + { + if (!first_) + return true; + + int pos = 0; + pointer p = first_; + pointer tmp = p; + do + { + tmp = p; + p = p->next_; + ++pos; + + if (p) + { + if (p->prev_ != tmp) + return false; + } + else + { + if (tmp != last_) + return false; + } + } while (p); + return true; + } + +public: + template + struct Iterator + { + using iterator_category = std::bidirectional_iterator_tag; + using pointer = _PTy; + using reference = IntrusiveList::reference; + using difference_type = ptrdiff_t; + + inline Iterator(pointer ptr = nullptr, bool is_end = false) + : base_(ptr) + , is_end_(is_end) + { + } + + inline pointer Get() const + { + KGE_ASSERT(!is_end_); + return const_cast(base_); + } + + inline reference operator*() const + { + KGE_ASSERT(base_ && !is_end_); + return const_cast(*base_); + } + + inline pointer operator->() const + { + KGE_ASSERT(base_ && !is_end_); + return const_cast(base_); + } + + inline Iterator& operator++() + { + KGE_ASSERT(base_ && !is_end_); + pointer next = base_->GetNext(); + if (next) + base_ = next; + else + is_end_ = true; + return (*this); + } + + inline Iterator operator++(int) + { + Iterator old = (*this); + ++(*this); + return old; + } + + inline Iterator& operator--() + { + KGE_ASSERT(base_); + if (is_end_) + is_end_ = false; + else + base_ = base_->GetPrev(); + return (*this); + } + + inline Iterator operator--(int) + { + Iterator old = (*this); + --(*this); + return old; + } + + inline bool operator==(Iterator const& other) const + { + return base_ == other.base_ && is_end_ == other.is_end_; + } + + inline bool operator!=(Iterator const& other) const + { + return !(*this == other); + } + + inline operator bool() const + { + return base_ != nullptr && !is_end_; + } + + private: + bool is_end_; + IntrusiveList::pointer base_; + }; + +public: + using iterator = Iterator; + using const_iterator = Iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + inline iterator begin() + { + return iterator(first_, first_ == nullptr); + } + + inline const_iterator begin() const + { + return const_iterator(first_, first_ == nullptr); + } + + inline const_iterator cbegin() const + { + return begin(); + } + + inline iterator end() + { + return iterator(last_, true); + } + + inline const_iterator end() const + { + return const_iterator(last_, true); + } + + inline const_iterator cend() const + { + return end(); + } + + inline reverse_iterator rbegin() + { + return reverse_iterator(end()); + } + + inline const_reverse_iterator rbegin() const + { + return const_reverse_iterator(end()); + } + + inline const_reverse_iterator crbegin() const + { + return rbegin(); + } + + inline reverse_iterator rend() + { + return reverse_iterator(begin()); + } + + inline const_reverse_iterator rend() const + { + return const_reverse_iterator(begin()); + } + + inline const_reverse_iterator crend() const + { + return rend(); + } + + inline pointer front() + { + if (IsEmpty()) + throw std::out_of_range("front() called on empty list"); + return first_; + } + + inline const pointer front() const + { + if (IsEmpty()) + throw std::out_of_range("front() called on empty list"); + return first_; + } + + inline pointer back() + { + if (IsEmpty()) + throw std::out_of_range("back() called on empty list"); + return last_; + } + + inline const pointer back() const + { + if (IsEmpty()) + throw std::out_of_range("back() called on empty list"); + return last_; + } + +private: + pointer first_; + pointer last_; +}; + + +/// \~chinese +/// @brief 侵入式链表元素 +template +class IntrusiveListValue +{ +public: + using pointer = typename std::pointer_traits<_PtrTy>::pointer; + + IntrusiveListValue() + : prev_(nullptr) + , next_(nullptr) + { + } + + IntrusiveListValue(pointer rhs) + : prev_(nullptr) + , next_(nullptr) + { + if (rhs) + { + prev_ = rhs->prev_; + next_ = rhs->next_; + } + } + + /// \~chinese + /// @brief 获取前一元素 + const pointer GetPrev() const + { + return prev_; + } + + /// \~chinese + /// @brief 获取前一元素 + pointer GetPrev() + { + return prev_; + } + + /// \~chinese + /// @brief 获取下一元素 + const pointer GetNext() const + { + return next_; + } + + /// \~chinese + /// @brief 获取下一元素 + pointer GetNext() + { + return next_; + } + +private: + pointer prev_; + pointer next_; + + friend class IntrusiveList<_PtrTy>; +}; + +} // namespace kiwano diff --git a/src/kiwano/core/Json.h b/src/kiwano/core/Json.h new file mode 100644 index 00000000..bb92f36a --- /dev/null +++ b/src/kiwano/core/Json.h @@ -0,0 +1,32 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include <3rd-party/nlohmann/json.hpp> + +namespace kiwano +{ + +/// \~chinese +/// @brief JSON对象容器 +using Json = nlohmann::basic_json; + +} // namespace kiwano diff --git a/src/kiwano/core/Logger.cpp b/src/kiwano/core/Logger.cpp index 67666371..447fe8a7 100644 --- a/src/kiwano/core/Logger.cpp +++ b/src/kiwano/core/Logger.cpp @@ -137,7 +137,7 @@ const WORD red_bg = white | BACKGROUND_RED | BACKGROUND_INTENSITY; const WORD yellow_bg = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; const WORD white_bg = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY; -const WORD reset = white; +const WORD Reset = white; } // namespace console_colors #define DECLARE_HANDLE_COLOR(NAME, HANDLE_NAME, COLOR) \ @@ -162,7 +162,7 @@ DECLARE_COLOR(green); DECLARE_COLOR(yellow); DECLARE_COLOR(blue); DECLARE_COLOR(white); -DECLARE_COLOR(reset); +DECLARE_COLOR(Reset); DECLARE_BG_COLOR(red); DECLARE_BG_COLOR(green); diff --git a/src/kiwano/core/ObjectBase.cpp b/src/kiwano/core/ObjectBase.cpp index 3d4b1b46..b80052fa 100644 --- a/src/kiwano/core/ObjectBase.cpp +++ b/src/kiwano/core/ObjectBase.cpp @@ -18,8 +18,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include #include +#include +#include #include namespace kiwano @@ -88,7 +89,7 @@ void ObjectBase::SetName(String const& name) String ObjectBase::DumpObject() { - return String::format("{ class=\"%s\" id=%d refcount=%d name=\"%s\" }", typeid(*this).name(), GetObjectID(), + return string::Format("{ class=\"%s\" id=%d refcount=%d name=\"%s\" }", typeid(*this).name(), GetObjectID(), GetRefCount(), GetName().c_str()); } diff --git a/src/kiwano/core/RefCounter.h b/src/kiwano/core/RefCounter.h index cff116c9..c61572ba 100644 --- a/src/kiwano/core/RefCounter.h +++ b/src/kiwano/core/RefCounter.h @@ -19,8 +19,8 @@ // THE SOFTWARE. #pragma once +#include #include -#include namespace kiwano { @@ -41,7 +41,7 @@ public: /// \~chinese /// @brief 获取引用计数 - long GetRefCount() const; + uint32_t GetRefCount() const; protected: RefCounter(); @@ -49,11 +49,12 @@ protected: virtual ~RefCounter(); private: - long ref_count_; + std::atomic ref_count_; }; -inline long RefCounter::GetRefCount() const +inline uint32_t RefCounter::GetRefCount() const { return ref_count_; } + } // namespace kiwano diff --git a/src/kiwano/core/SmartPtr.hpp b/src/kiwano/core/SmartPtr.hpp index 8cf32c6c..9b6ea8a3 100644 --- a/src/kiwano/core/SmartPtr.hpp +++ b/src/kiwano/core/SmartPtr.hpp @@ -19,24 +19,27 @@ // THE SOFTWARE. #pragma once +#include +#include #include #include namespace kiwano { + /** * \~chinese - * @brief 默认的智能指针代理 + * @brief 默认的智能指针引用计数代理 */ struct DefaultSmartPtrRefProxy { - static inline void add_ref(RefCounter* ptr) + static inline void AddRef(RefCounter* ptr) { if (ptr) ptr->Retain(); } - static inline void release(RefCounter* ptr) + static inline void Release(RefCounter* ptr) { if (ptr) ptr->Release(); @@ -45,10 +48,232 @@ struct DefaultSmartPtrRefProxy /** * \~chinese - * @brief 智能指针 + * @brief 侵入式智能指针 */ -template -using SmartPtr = IntrusivePtr<_Ty, DefaultSmartPtrRefProxy>; +template +class SmartPtr +{ +public: + using value_type = _Ty; + using pointer_type = _Ty*; + using const_pointer_type = const _Ty*; + using reference_type = _Ty&; + using const_reference_type = const _Ty&; + + SmartPtr() noexcept + : ptr_(nullptr) + { + } + + SmartPtr(std::nullptr_t) noexcept + : ptr_(nullptr) + { + } + + SmartPtr(pointer_type p) + : ptr_(p) + { + typename _ProxyTy::AddRef(ptr_); + } + + SmartPtr(const SmartPtr& other) + : ptr_(other.ptr_) + { + typename _ProxyTy::AddRef(ptr_); + } + + SmartPtr(SmartPtr&& other) noexcept + : ptr_(nullptr) + { + Swap(other); + } + + ~SmartPtr() + { + Tidy(); + } + + template ::value, int>::type = 0> + SmartPtr(const SmartPtr<_UTy, _ProxyTy>& other) + { + ptr_ = const_cast(dynamic_cast(other.Get())); + typename _ProxyTy::AddRef(ptr_); + } + + inline pointer_type Get() noexcept + { + return ptr_; + } + + inline const_pointer_type Get() const noexcept + { + return ptr_; + } + + inline void Reset(pointer_type ptr = nullptr) + { + if (ptr) + SmartPtr(ptr).Swap(*this); + else + Tidy(); + } + + inline void Swap(SmartPtr& other) noexcept + { + std::swap(ptr_, other.ptr_); + } + + inline pointer_type operator->() + { + KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); + return ptr_; + } + + inline const_pointer_type operator->() const + { + KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); + return ptr_; + } + + inline reference_type operator*() + { + KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); + return *ptr_; + } + + inline const_reference_type operator*() const + { + KGE_ASSERT(ptr_ != nullptr && "Invalid pointer"); + return *ptr_; + } + + inline pointer_type* operator&() + { + KGE_ASSERT(ptr_ == nullptr && "Memory leak"); + return &ptr_; + } + + inline operator bool() const noexcept + { + return ptr_ != nullptr; + } + + inline bool operator!() const noexcept + { + return ptr_ == 0; + } + + inline SmartPtr& operator=(const SmartPtr& other) + { + if (other.ptr_ != ptr_) + SmartPtr(other).Swap(*this); + return (*this); + } + + inline SmartPtr& operator=(SmartPtr&& other) noexcept + { + if (other.ptr_ != ptr_) + other.Swap(*this); + return (*this); + } + + inline SmartPtr& operator=(pointer_type p) + { + if (p != ptr_) + SmartPtr(p).Swap(*this); + return (*this); + } + + inline SmartPtr& operator=(std::nullptr_t) + { + Tidy(); + return *this; + } + +private: + void Tidy() + { + typename _ProxyTy::Release(ptr_); + ptr_ = nullptr; + } + +private: + pointer_type ptr_; +}; + +template +inline bool operator==(SmartPtr<_Ty, _ProxyTy> const& lhs, SmartPtr<_UTy, _ProxyTy> const& rhs) noexcept +{ + return lhs.Get() == rhs.Get(); +} + +template +inline bool operator==(SmartPtr<_Ty, _ProxyTy> const& lhs, _Ty* rhs) noexcept +{ + return lhs.Get() == rhs; +} + +template +inline bool operator==(_Ty* lhs, SmartPtr<_Ty, _ProxyTy> const& rhs) noexcept +{ + return lhs == rhs.Get(); +} + +template +inline bool operator==(SmartPtr<_Ty, _ProxyTy> const& lhs, std::nullptr_t) noexcept +{ + return !static_cast(lhs); +} + +template +inline bool operator==(std::nullptr_t, SmartPtr<_Ty, _ProxyTy> const& rhs) noexcept +{ + return !static_cast(rhs); +} + +template +inline bool operator!=(SmartPtr<_Ty, _ProxyTy> const& lhs, SmartPtr<_UTy, _ProxyTy> const& rhs) noexcept +{ + return !(lhs == rhs); +} + +template +inline bool operator!=(SmartPtr<_Ty, _ProxyTy> const& lhs, _Ty* rhs) noexcept +{ + return lhs.Get() != rhs; +} + +template +inline bool operator!=(_Ty* lhs, SmartPtr<_Ty, _ProxyTy> const& rhs) noexcept +{ + return lhs != rhs.Get(); +} + +template +inline bool operator!=(SmartPtr<_Ty, _ProxyTy> const& lhs, std::nullptr_t) noexcept +{ + return static_cast(lhs); +} + +template +inline bool operator!=(std::nullptr_t, SmartPtr<_Ty, _ProxyTy> const& rhs) noexcept +{ + return static_cast(rhs); +} + +template +inline bool operator<(SmartPtr<_Ty, _ProxyTy> const& lhs, SmartPtr<_UTy, _ProxyTy> const& rhs) noexcept +{ + return lhs.Get() < rhs.Get(); +} + +// template class cannot specialize std::swap, +// so implement a Swap Function in kiwano namespace +template +inline void swap(SmartPtr<_Ty, _ProxyTy>& lhs, SmartPtr<_Ty, _ProxyTy>& rhs) noexcept +{ + lhs.Swap(rhs); +} } // namespace kiwano diff --git a/src/kiwano/core/String.cpp b/src/kiwano/core/String.cpp new file mode 100644 index 00000000..896d32d1 --- /dev/null +++ b/src/kiwano/core/String.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include + +namespace kiwano +{ +namespace string +{ + +#if defined(KGE_PLATFORM_WINDOWS) + +// +// This 中文 comment will enable utf-8 encoding in Visual Studio +// Otherwise 'CP_UTF8' cannot work +// + +String Format(const char* format, ...) +{ + String result; + if (format) + { + va_list args = nullptr; + va_start(args, format); + + const auto len = static_cast(::_vscprintf(format, args) + 1); + if (len) + { + result.resize(len); + ::_vsnprintf_s(&result[0], len, len, format, args); + } + va_end(args); + } + return result; +} + +String ToNarrow(const WideString& str) +{ + if (str.empty()) + return String(); + + int chars_num = ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, NULL, 0, NULL, NULL); + if (chars_num) + { + String result; + result.resize(chars_num); + + ::WideCharToMultiByte(CP_UTF8, 0, str.c_str(), -1, &result[0], chars_num, NULL, NULL); + return result; + } + return String(); +} + +WideString ToWide(const String& str) +{ + if (str.empty()) + return WideString(); + + int chars_num = ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0); + if (chars_num) + { + WideString result; + result.resize(chars_num); + + ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &result[0], chars_num); + return result; + } + return WideString(); +} + +#endif // KGE_PLATFORM_WINDOWS + +} // namespace string +} // namespace kiwano diff --git a/src/kiwano/core/String.h b/src/kiwano/core/String.h new file mode 100644 index 00000000..ef8c91f0 --- /dev/null +++ b/src/kiwano/core/String.h @@ -0,0 +1,52 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include + +namespace kiwano +{ + +/// \~chinese +/// @brief 字符串容器 +using String = std::string; + +/// \~chinese +/// @brief 宽字符串容器 +using WideString = std::wstring; + +namespace string +{ + +/// \~chinese +/// @brief 格式化字符串 +String Format(const char* format, ...); + +/// \~chinese +/// @brief 宽字符串转窄字符串 +String ToNarrow(const WideString& str); + +/// \~chinese +/// @brief 窄字符串转宽字符串 +WideString ToWide(const String& str); + +} + +} // namespace kiwano diff --git a/src/kiwano/core/Time.cpp b/src/kiwano/core/Time.cpp index 82d6908a..832e5d0b 100644 --- a/src/kiwano/core/Time.cpp +++ b/src/kiwano/core/Time.cpp @@ -157,21 +157,21 @@ String Duration::ToString() const if (hour) { - result.append(String::parse(hour)).append("h"); - result.append(String::parse(min)).append("m"); + result.append(std::to_string(hour)).append("h"); + result.append(std::to_string(min)).append("m"); } else if (min) { - result.append(String::parse(min)).append("m"); + result.append(std::to_string(min)).append("m"); } if (ms != 0) { - result.append(String::parse(static_cast(sec) + static_cast(ms) / 1000.f)).append("s"); + result.append(std::to_string(static_cast(sec) + static_cast(ms) / 1000.f)).append("s"); } else if (sec != 0) { - result.append(String::parse(sec)).append("s"); + result.append(std::to_string(sec)).append("s"); } return result; } diff --git a/src/kiwano/core/Time.h b/src/kiwano/core/Time.h index e18d415b..996f14c4 100644 --- a/src/kiwano/core/Time.h +++ b/src/kiwano/core/Time.h @@ -106,7 +106,7 @@ struct KGE_API Duration /// 例如: "300ms", "-1.5h", "2h45m" /// 允许的时间单位有 "ms", "s", "m", "h" /// @return 解析出的时间段 - /// @throw std::runtime_error 传入一个不合法的格式时抛出 + /// @throw kiwano::RuntimeError 传入一个不合法的格式时抛出 static Duration Parse(const String& str); static const Duration Ms; ///< 毫秒 diff --git a/src/kiwano/core/Timer.h b/src/kiwano/core/Timer.h index 52d92780..0847d1f2 100644 --- a/src/kiwano/core/Timer.h +++ b/src/kiwano/core/Timer.h @@ -21,6 +21,7 @@ #pragma once #include #include +#include namespace kiwano { @@ -33,7 +34,7 @@ KGE_DECLARE_SMART_PTR(Timer); /// @details 定时器用于每隔一段时间执行一次回调函数,且可以指定执行总次数 class KGE_API Timer : public virtual ObjectBase - , protected IntrusiveListItem + , protected IntrusiveListValue { friend class TimerManager; friend IntrusiveList; diff --git a/src/kiwano/core/TimerManager.cpp b/src/kiwano/core/TimerManager.cpp index 098474ba..3e241620 100644 --- a/src/kiwano/core/TimerManager.cpp +++ b/src/kiwano/core/TimerManager.cpp @@ -25,18 +25,18 @@ namespace kiwano { void TimerManager::UpdateTimers(Duration dt) { - if (timers_.empty()) + if (timers_.IsEmpty()) return; TimerPtr next; - for (auto timer = timers_.first_item(); timer; timer = next) + for (auto timer = timers_.GetFirst(); timer; timer = next) { - next = timer->next_item(); + next = timer->GetNext(); timer->Update(dt); if (timer->IsRemoveable()) - timers_.remove(timer); + timers_.Remove(timer); } } @@ -58,15 +58,15 @@ Timer* TimerManager::AddTimer(TimerPtr timer) if (timer) { timer->Reset(); - timers_.push_back(timer); + timers_.PushBack(timer); } - return timer.get(); + return timer.Get(); } void TimerManager::StopTimers(String const& name) { - if (timers_.empty()) + if (timers_.IsEmpty()) return; for (auto& timer : timers_) @@ -80,7 +80,7 @@ void TimerManager::StopTimers(String const& name) void TimerManager::StartTimers(String const& name) { - if (timers_.empty()) + if (timers_.IsEmpty()) return; for (auto& timer : timers_) @@ -94,7 +94,7 @@ void TimerManager::StartTimers(String const& name) void TimerManager::RemoveTimers(String const& name) { - if (timers_.empty()) + if (timers_.IsEmpty()) return; for (auto& timer : timers_) @@ -108,7 +108,7 @@ void TimerManager::RemoveTimers(String const& name) void TimerManager::StopAllTimers() { - if (timers_.empty()) + if (timers_.IsEmpty()) return; for (auto& timer : timers_) @@ -119,7 +119,7 @@ void TimerManager::StopAllTimers() void TimerManager::StartAllTimers() { - if (timers_.empty()) + if (timers_.IsEmpty()) return; for (auto& timer : timers_) @@ -130,7 +130,7 @@ void TimerManager::StartAllTimers() void TimerManager::RemoveAllTimers() { - timers_.clear(); + timers_.Clear(); } const TimerManager::Timers& TimerManager::GetAllTimers() const diff --git a/src/kiwano/core/Xml.h b/src/kiwano/core/Xml.h new file mode 100644 index 00000000..d5265206 --- /dev/null +++ b/src/kiwano/core/Xml.h @@ -0,0 +1,36 @@ +// Copyright (c) 2016-2018 Kiwano - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include +#include <3rd-party/pugixml/pugixml.hpp> + +namespace kiwano +{ + +/// \~chinese +/// @brief XML文档 +using XmlDocument = pugi::xml_document; + +/// \~chinese +/// @brief XML文档 +using XmlNode = pugi::xml_node; + +} // namespace kiwano diff --git a/src/kiwano/macros.h b/src/kiwano/macros.h index b4378327..e8b1993f 100644 --- a/src/kiwano/macros.h +++ b/src/kiwano/macros.h @@ -25,19 +25,16 @@ #endif #ifdef _WIN32 -# define KGE_WIN32 -# ifdef _WIN64 -# define KGE_WIN64 -# endif +# define KGE_PLATFORM_WINDOWS #elif __ANDROID__ -# define KGE_ANDROID +# define KGE_PLATFORM_ANDROID #elif __linux__ -# define KGE_LINUX +# define KGE_PLATFORM_LINUX #elif __APPLE__ # if TARGET_OS_IPHONE -# define KGE_IPHONE +# define KGE_PLATFORM_IPHONE # elif TARGET_OS_MAC -# define KGE_MACOS +# define KGE_PLATFORM_MACOS # else # error "Unsupported Apple platform" # endif @@ -65,7 +62,7 @@ // ///////////////////////////////////////////////////////////// -#ifdef KGE_WIN32 +#ifdef KGE_PLATFORM_WINDOWS #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_NONE # undef KGE_RENDER_ENGINE @@ -163,4 +160,10 @@ KGE_SUPPRESS_WARNING(4251) #include #include -#endif // KGE_WIN32 +#else + +#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX +# error "DirectX render engine is not supported on current platform" +#endif + +#endif // KGE_PLATFORM_WINDOWS diff --git a/src/kiwano/platform/Input.h b/src/kiwano/platform/Input.h index 494d7f21..17ca0963 100644 --- a/src/kiwano/platform/Input.h +++ b/src/kiwano/platform/Input.h @@ -19,6 +19,7 @@ // THE SOFTWARE. #pragma once +#include #include #include #include diff --git a/src/kiwano/platform/Runner.cpp b/src/kiwano/platform/Runner.cpp index d5f24c3f..55a3fdfe 100644 --- a/src/kiwano/platform/Runner.cpp +++ b/src/kiwano/platform/Runner.cpp @@ -84,7 +84,7 @@ bool Runner::MainLoop() // Poll events while (EventPtr evt = main_window_->PollEvent()) { - app.DispatchEvent(evt.get()); + app.DispatchEvent(evt.Get()); } // Update & render diff --git a/src/kiwano/platform/Window.h b/src/kiwano/platform/Window.h index 526b63f3..e9dd6883 100644 --- a/src/kiwano/platform/Window.h +++ b/src/kiwano/platform/Window.h @@ -46,7 +46,7 @@ enum class CursorType }; -#if defined(KGE_WIN32) +#if defined(KGE_PLATFORM_WINDOWS) typedef HWND WindowHandle; #endif @@ -67,7 +67,7 @@ public: * @param icon 图标资源ID * @param resizable 窗口大小可拉伸 * @param fullscreen 全屏模式 - * @throw std::system_error 窗口创建失败时抛出 + * @throw kiwano::SystemError 窗口创建失败时抛出 */ static WindowPtr Create(String const& title, uint32_t width, uint32_t height, uint32_t icon = 0, bool resizable = false, bool fullscreen = false); diff --git a/src/kiwano/platform/win32/ComPtr.hpp b/src/kiwano/platform/win32/ComPtr.hpp index 1e34bcf0..328e9103 100644 --- a/src/kiwano/platform/win32/ComPtr.hpp +++ b/src/kiwano/platform/win32/ComPtr.hpp @@ -19,21 +19,22 @@ // THE SOFTWARE. #pragma once -#include -#include #include +#include +#include +#include namespace kiwano { struct ComPtrProxy { - static inline void add_ref(IUnknown* ptr) + static inline void AddRef(IUnknown* ptr) { if (ptr) ptr->AddRef(); } - static inline void release(IUnknown* ptr) + static inline void Release(IUnknown* ptr) { if (ptr) ptr->Release(); @@ -42,6 +43,6 @@ struct ComPtrProxy // ComPtr<> is a smart pointer for COM template ::value, int>::type> -using ComPtr = IntrusivePtr<_Ty, ComPtrProxy>; +using ComPtr = SmartPtr<_Ty, ComPtrProxy>; } // namespace kiwano diff --git a/src/kiwano/platform/win32/WindowImpl.cpp b/src/kiwano/platform/win32/WindowImpl.cpp index dab99056..cc8ce967 100644 --- a/src/kiwano/platform/win32/WindowImpl.cpp +++ b/src/kiwano/platform/win32/WindowImpl.cpp @@ -20,8 +20,9 @@ #include -#if defined(KGE_WIN32) +#if defined(KGE_PLATFORM_WINDOWS) +#include #include #include #include @@ -277,7 +278,7 @@ void WindowWin32Impl::Init(String const& title, uint32_t width, uint32_t height, height = win_height; } - WideString wide_title = MultiByteToWide(title); + WideString wide_title = string::ToWide(title); handle_ = ::CreateWindowExW(is_fullscreen_ ? WS_EX_TOPMOST : 0, L"KiwanoAppWnd", wide_title.c_str(), GetStyle(), left, top, width, height, nullptr, nullptr, hinst, nullptr); @@ -320,7 +321,7 @@ void WindowWin32Impl::SetTitle(String const& title) { if (handle_) { - WideString wide_title = MultiByteToWide(title); + WideString wide_title = string::ToWide(title); ::SetWindowTextW(handle_, wide_title.c_str()); } } @@ -633,7 +634,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA { KGE_SYS_LOG("Window title changed"); - this->title_ = WideToMultiByte(reinterpret_cast(lparam)); + this->title_ = string::ToNarrow(reinterpret_cast(lparam)); WindowTitleChangedEventPtr evt = new WindowTitleChangedEvent; evt->title = this->title_; diff --git a/src/kiwano/render/DirectX/D2DDeviceResources.cpp b/src/kiwano/render/DirectX/D2DDeviceResources.cpp index 3ca646b9..86b045f1 100644 --- a/src/kiwano/render/DirectX/D2DDeviceResources.cpp +++ b/src/kiwano/render/DirectX/D2DDeviceResources.cpp @@ -171,13 +171,13 @@ STDMETHODIMP D2DDeviceResources::QueryInterface(IID const& riid, void** object) void D2DDeviceResources::DiscardResources() { - factory_.reset(); - device_.reset(); - device_context_.reset(); - target_bitmap_.reset(); + factory_.Reset(); + device_.Reset(); + device_context_.Reset(); + target_bitmap_.Reset(); - imaging_factory_.reset(); - dwrite_factory_.reset(); + imaging_factory_.Reset(); + dwrite_factory_.Reset(); } HRESULT D2DDeviceResources::CreateDeviceIndependentResources() @@ -235,7 +235,7 @@ HRESULT D2DDeviceResources::CreateDeviceResources(_In_ ComPtr dxgi_ // Create the Direct2D device object and a corresponding context. ComPtr device; - HRESULT hr = factory_->CreateDevice(dxgi_device.get(), &device); + HRESULT hr = factory_->CreateDevice(dxgi_device.Get(), &device); if (SUCCEEDED(hr)) { @@ -269,7 +269,7 @@ HRESULT D2DDeviceResources::CreateWindowSizeDependentResources() { ComPtr target; hr = device_context_->CreateBitmapFromDxgiSurface( - dxgi_back_buffer.get(), + dxgi_back_buffer.Get(), D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED), dpi_, dpi_), &target); @@ -277,7 +277,7 @@ HRESULT D2DDeviceResources::CreateWindowSizeDependentResources() if (SUCCEEDED(hr)) { target_bitmap_ = target; - device_context_->SetTarget(target_bitmap_.get()); + device_context_->SetTarget(target_bitmap_.Get()); } } return hr; @@ -326,7 +326,7 @@ HRESULT D2DDeviceResources::CreateBitmapConverter(_Out_ ComPtrInitialize(source.get(), format, dither, palette.get(), alpha_threshold_percent, palette_translate); + output->Initialize(source.Get(), format, dither, palette.Get(), alpha_threshold_percent, palette_translate); } if (SUCCEEDED(hr)) @@ -345,7 +345,7 @@ HRESULT D2DDeviceResources::CreateBitmapFromConverter(_Out_ ComPtr& ComPtr output; - HRESULT hr = device_context_->CreateBitmapFromWicBitmap(converter.get(), properties, &output); + HRESULT hr = device_context_->CreateBitmapFromWicBitmap(converter.Get(), properties, &output); if (SUCCEEDED(hr)) { @@ -393,7 +393,7 @@ HRESULT D2DDeviceResources::CreateBitmapDecoderFromResource(_Out_ ComPtr decoder_output; - hr = imaging_factory_->CreateDecoderFromStream(stream.get(), nullptr, WICDecodeMetadataCacheOnLoad, + hr = imaging_factory_->CreateDecoderFromStream(stream.Get(), nullptr, WICDecodeMetadataCacheOnLoad, &decoder_output); if (SUCCEEDED(hr)) @@ -413,7 +413,7 @@ HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr& te return E_UNEXPECTED; ComPtr output; - HRESULT hr = dwrite_factory_->CreateTextFormat(family, collection.get(), weight, style, stretch, font_size, + HRESULT hr = dwrite_factory_->CreateTextFormat(family, collection.Get(), weight, style, stretch, font_size, L"", &output); if (SUCCEEDED(hr)) @@ -431,7 +431,7 @@ HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr& te ComPtr output; - HRESULT hr = dwrite_factory_->CreateTextLayout(text, length, text_format.get(), 0, 0, &output); + HRESULT hr = dwrite_factory_->CreateTextLayout(text, length, text_format.Get(), 0, 0, &output); if (SUCCEEDED(hr)) { diff --git a/src/kiwano/render/DirectX/D2DDeviceResources.h b/src/kiwano/render/DirectX/D2DDeviceResources.h index eda74715..e8768f79 100644 --- a/src/kiwano/render/DirectX/D2DDeviceResources.h +++ b/src/kiwano/render/DirectX/D2DDeviceResources.h @@ -66,37 +66,37 @@ public: inline ID2D1Factory1* GetFactory() { KGE_ASSERT(factory_); - return factory_.get(); + return factory_.Get(); } inline IWICImagingFactory* GetWICImagingFactory() { KGE_ASSERT(imaging_factory_); - return imaging_factory_.get(); + return imaging_factory_.Get(); } inline IDWriteFactory* GetDWriteFactory() { KGE_ASSERT(dwrite_factory_); - return dwrite_factory_.get(); + return dwrite_factory_.Get(); } inline ID2D1Device* GetDevice() { KGE_ASSERT(device_); - return device_.get(); + return device_.Get(); } inline ID2D1DeviceContext* GetDeviceContext() { KGE_ASSERT(device_context_); - return device_context_.get(); + return device_context_.Get(); } inline ID2D1Bitmap1* GetTargetBitmap() { KGE_ASSERT(target_bitmap_); - return target_bitmap_.get(); + return target_bitmap_.Get(); } protected: diff --git a/src/kiwano/render/DirectX/D3D10DeviceResources.cpp b/src/kiwano/render/DirectX/D3D10DeviceResources.cpp index 6e9f76d4..98a86749 100644 --- a/src/kiwano/render/DirectX/D3D10DeviceResources.cpp +++ b/src/kiwano/render/DirectX/D3D10DeviceResources.cpp @@ -168,19 +168,19 @@ void D3D10DeviceResources::ClearRenderTarget(Color& clear_color) { KGE_ASSERT(device_ != nullptr && rt_view_ != nullptr && ds_view_ != nullptr); - auto rt_view = rt_view_.get(); - device_->OMSetRenderTargets(1, &rt_view, ds_view_.get()); + auto rt_view = rt_view_.Get(); + device_->OMSetRenderTargets(1, &rt_view, ds_view_.Get()); device_->ClearRenderTargetView(rt_view, reinterpret_cast(&clear_color)); } void D3D10DeviceResources::DiscardResources() { - device_.reset(); - rt_view_.reset(); - ds_view_.reset(); - dxgi_device_.reset(); - dxgi_swap_chain_.reset(); - dxgi_factory_.reset(); + device_.Reset(); + rt_view_.Reset(); + ds_view_.Reset(); + dxgi_device_.Reset(); + dxgi_swap_chain_.Reset(); + dxgi_factory_.Reset(); hwnd_ = nullptr; } @@ -252,7 +252,7 @@ HRESULT D3D10DeviceResources::CreateDeviceResources() swap_chain_desc.Windowed = TRUE; swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - hr = dxgi_factory_->CreateSwapChain(device_.get(), &swap_chain_desc, &dxgi_swap_chain_); + hr = dxgi_factory_->CreateSwapChain(device_.Get(), &swap_chain_desc, &dxgi_swap_chain_); } return hr; @@ -298,7 +298,7 @@ HRESULT D3D10DeviceResources::CreateWindowSizeDependentResources() renderDesc.Texture2D.MipSlice = 0; rt_view_ = nullptr; - hr = device_->CreateRenderTargetView(dxgi_back_buffer.get(), &renderDesc, &rt_view_); + hr = device_->CreateRenderTargetView(dxgi_back_buffer.Get(), &renderDesc, &rt_view_); } } @@ -328,14 +328,14 @@ HRESULT D3D10DeviceResources::CreateWindowSizeDependentResources() desc.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D; desc.Texture2D.MipSlice = 0; - ds_view_.reset(); - hr = device_->CreateDepthStencilView(depth_stencil.get(), &desc, &ds_view_); + ds_view_.Reset(); + hr = device_->CreateDepthStencilView(depth_stencil.Get(), &desc, &ds_view_); } if (SUCCEEDED(hr)) { - ID3D10RenderTargetView* main_view = rt_view_.get(); - device_->OMSetRenderTargets(1, &main_view, ds_view_.get()); + ID3D10RenderTargetView* main_view = rt_view_.Get(); + device_->OMSetRenderTargets(1, &main_view, ds_view_.Get()); } } diff --git a/src/kiwano/render/DirectX/D3D10DeviceResources.h b/src/kiwano/render/DirectX/D3D10DeviceResources.h index 90037349..e13958d6 100644 --- a/src/kiwano/render/DirectX/D3D10DeviceResources.h +++ b/src/kiwano/render/DirectX/D3D10DeviceResources.h @@ -35,32 +35,32 @@ public: inline ID3D10Device* GetDevice() { KGE_ASSERT(device_); - return device_.get(); + return device_.Get(); } inline ID3D10RenderTargetView* GetRenderTargetView() { KGE_ASSERT(rt_view_); - return rt_view_.get(); + return rt_view_.Get(); } inline ID3D10DepthStencilView* GetDepthStencilView() { KGE_ASSERT(ds_view_); - return ds_view_.get(); + return ds_view_.Get(); } inline IDXGIFactory* GetDXGIFactory() { KGE_ASSERT(dxgi_factory_); - return dxgi_factory_.get(); + return dxgi_factory_.Get(); } inline IDXGIDevice* GetDXGIDevice() { KGE_ASSERT(dxgi_device_); - return dxgi_device_.get(); + return dxgi_device_.Get(); } inline IDXGISwapChain* GetDXGISwapChain() { KGE_ASSERT(dxgi_swap_chain_); - return dxgi_swap_chain_.get(); + return dxgi_swap_chain_.Get(); } protected: diff --git a/src/kiwano/render/DirectX/D3D11DeviceResources.cpp b/src/kiwano/render/DirectX/D3D11DeviceResources.cpp index 357dcb3a..1e353cb9 100644 --- a/src/kiwano/render/DirectX/D3D11DeviceResources.cpp +++ b/src/kiwano/render/DirectX/D3D11DeviceResources.cpp @@ -160,20 +160,20 @@ void D3D11DeviceResources::ClearRenderTarget(Color& clear_color) { KGE_ASSERT(device_context_ != nullptr && rt_view_ != nullptr && ds_view_ != nullptr); - auto rt_view = rt_view_.get(); - device_context_->OMSetRenderTargets(1, &rt_view, ds_view_.get()); + auto rt_view = rt_view_.Get(); + device_context_->OMSetRenderTargets(1, &rt_view, ds_view_.Get()); device_context_->ClearRenderTargetView(rt_view, reinterpret_cast(&clear_color)); } void D3D11DeviceResources::DiscardResources() { - device_.reset(); - device_context_.reset(); - rt_view_.reset(); - ds_view_.reset(); - dxgi_device_.reset(); - dxgi_swap_chain_.reset(); - dxgi_factory_.reset(); + device_.Reset(); + device_context_.Reset(); + rt_view_.Reset(); + ds_view_.Reset(); + dxgi_device_.Reset(); + dxgi_swap_chain_.Reset(); + dxgi_factory_.Reset(); hwnd_ = nullptr; } @@ -293,7 +293,7 @@ HRESULT D3D11DeviceResources::CreateDeviceResources() swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; } - hr = dxgi_factory_->CreateSwapChain(device_.get(), &swap_chain_desc, &dxgi_swap_chain_); + hr = dxgi_factory_->CreateSwapChain(device_.Get(), &swap_chain_desc, &dxgi_swap_chain_); } return hr; } @@ -333,7 +333,7 @@ HRESULT D3D11DeviceResources::CreateWindowSizeDependentResources() if (SUCCEEDED(hr)) { rt_view_ = nullptr; - hr = device_->CreateRenderTargetView(dxgi_back_buffer.get(), nullptr, &rt_view_); + hr = device_->CreateRenderTargetView(dxgi_back_buffer.Get(), nullptr, &rt_view_); } } @@ -353,14 +353,14 @@ HRESULT D3D11DeviceResources::CreateWindowSizeDependentResources() { CD3D11_DEPTH_STENCIL_VIEW_DESC desc(D3D11_DSV_DIMENSION_TEXTURE2D); - ds_view_.reset(); - hr = device_->CreateDepthStencilView(depth_stencil.get(), &desc, &ds_view_); + ds_view_.Reset(); + hr = device_->CreateDepthStencilView(depth_stencil.Get(), &desc, &ds_view_); } if (SUCCEEDED(hr)) { - ID3D11RenderTargetView* main_view = rt_view_.get(); - device_context_->OMSetRenderTargets(1, &main_view, ds_view_.get()); + ID3D11RenderTargetView* main_view = rt_view_.Get(); + device_context_->OMSetRenderTargets(1, &main_view, ds_view_.Get()); } } diff --git a/src/kiwano/render/DirectX/D3D11DeviceResources.h b/src/kiwano/render/DirectX/D3D11DeviceResources.h index d99742ed..29a1b36a 100644 --- a/src/kiwano/render/DirectX/D3D11DeviceResources.h +++ b/src/kiwano/render/DirectX/D3D11DeviceResources.h @@ -35,37 +35,37 @@ public: inline ID3D11Device* GetDevice() { KGE_ASSERT(device_); - return device_.get(); + return device_.Get(); } inline ID3D11DeviceContext* GetDeviceContext() { KGE_ASSERT(device_context_); - return device_context_.get(); + return device_context_.Get(); } inline ID3D11RenderTargetView* GetRenderTargetView() { KGE_ASSERT(rt_view_); - return rt_view_.get(); + return rt_view_.Get(); } inline ID3D11DepthStencilView* GetDepthStencilView() { KGE_ASSERT(ds_view_); - return ds_view_.get(); + return ds_view_.Get(); } inline IDXGIFactory* GetDXGIFactory() { KGE_ASSERT(dxgi_factory_); - return dxgi_factory_.get(); + return dxgi_factory_.Get(); } inline IDXGIDevice* GetDXGIDevice() { KGE_ASSERT(dxgi_device_); - return dxgi_device_.get(); + return dxgi_device_.Get(); } inline IDXGISwapChain* GetDXGISwapChain() { KGE_ASSERT(dxgi_swap_chain_); - return dxgi_swap_chain_.get(); + return dxgi_swap_chain_.Get(); } protected: diff --git a/src/kiwano/render/DirectX/FontCollectionLoader.cpp b/src/kiwano/render/DirectX/FontCollectionLoader.cpp index 3ea41b6e..e1755bf1 100644 --- a/src/kiwano/render/DirectX/FontCollectionLoader.cpp +++ b/src/kiwano/render/DirectX/FontCollectionLoader.cpp @@ -305,7 +305,7 @@ HRESULT STDMETHODCALLTYPE FontFileEnumerator::MoveNext(_Out_ BOOL* hasCurrentFil if (nextIndex_ < filePaths_.size()) { - WideString file_name = MultiByteToWide(filePaths_[nextIndex_]); + WideString file_name = string::ToWide(filePaths_[nextIndex_]); hr = pFactory_->CreateFontFileReference(file_name.c_str(), NULL, ¤tFile_); diff --git a/src/kiwano/render/DirectX/RenderContextImpl.cpp b/src/kiwano/render/DirectX/RenderContextImpl.cpp index 75a1692a..dca29c5d 100644 --- a/src/kiwano/render/DirectX/RenderContextImpl.cpp +++ b/src/kiwano/render/DirectX/RenderContextImpl.cpp @@ -38,10 +38,10 @@ HRESULT RenderContextImpl::CreateDeviceResources(ComPtr factory, C return E_INVALIDARG; render_target_ = ctx; - text_renderer_.reset(); - current_brush_.reset(); + text_renderer_.Reset(); + current_brush_.Reset(); - HRESULT hr = ITextRenderer::Create(&text_renderer_, render_target_.get()); + HRESULT hr = ITextRenderer::Create(&text_renderer_, render_target_.Get()); if (SUCCEEDED(hr)) { @@ -62,9 +62,9 @@ HRESULT RenderContextImpl::CreateDeviceResources(ComPtr factory, C void RenderContextImpl::DiscardDeviceResources() { - text_renderer_.reset(); - render_target_.reset(); - current_brush_.reset(); + text_renderer_.Reset(); + render_target_.Reset(); + current_brush_.Reset(); } bool RenderContextImpl::IsValid() const @@ -86,7 +86,7 @@ void RenderContextImpl::BeginDraw() void RenderContextImpl::EndDraw() { - ThrowIfFailed(render_target_->EndDraw(), "ID2D1RenderTarget EndDraw failed"); + KGE_THROW_IF_FAILED(render_target_->EndDraw(), "ID2D1RenderTarget EndDraw failed"); RenderContext::EndDraw(); @@ -103,7 +103,7 @@ void RenderContextImpl::DrawTexture(Texture const& texture, const Rect* src_rect ? D2D1_BITMAP_INTERPOLATION_MODE_LINEAR : D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR; - render_target_->DrawBitmap(texture.GetBitmap().get(), dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr, + render_target_->DrawBitmap(texture.GetBitmap().Get(), dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr, brush_opacity_, mode, src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr); IncreasePrimitivesCount(); @@ -133,10 +133,10 @@ void RenderContextImpl::DrawTextLayout(TextLayout const& layout, Point const& of } HRESULT hr = S_OK; - ID2D1StrokeStyle* stroke_style = style.outline_stroke ? style.outline_stroke->GetStrokeStyle().get() : nullptr; + ID2D1StrokeStyle* stroke_style = style.outline_stroke ? style.outline_stroke->GetStrokeStyle().Get() : nullptr; - hr = text_renderer_->DrawTextLayout(layout.GetTextLayout().get(), offset.x, offset.y, fill_brush.get(), - outline_brush.get(), style.outline_width, stroke_style); + hr = text_renderer_->DrawTextLayout(layout.GetTextLayout().Get(), offset.x, offset.y, fill_brush.Get(), + outline_brush.Get(), style.outline_width, stroke_style); if (SUCCEEDED(hr)) { @@ -156,8 +156,8 @@ void RenderContextImpl::DrawShape(Shape const& shape, StrokeStylePtr stroke, flo if (shape.IsValid()) { - ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().get() : nullptr; - render_target_->DrawGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get(), stroke_width, + ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().Get() : nullptr; + render_target_->DrawGeometry(shape.GetGeometry().Get(), current_brush_->GetBrush().Get(), stroke_width, stroke_style); IncreasePrimitivesCount(); @@ -169,9 +169,9 @@ void RenderContextImpl::DrawLine(Point const& point1, Point const& point2, Strok KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().get() : nullptr; + ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().Get() : nullptr; render_target_->DrawLine(DX::ConvertToPoint2F(point1), DX::ConvertToPoint2F(point2), - current_brush_->GetBrush().get(), stroke_width, stroke_style); + current_brush_->GetBrush().Get(), stroke_width, stroke_style); IncreasePrimitivesCount(); } @@ -181,8 +181,8 @@ void RenderContextImpl::DrawRectangle(Rect const& rect, StrokeStylePtr stroke, f KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().get() : nullptr; - render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get(), stroke_width, + ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().Get() : nullptr; + render_target_->DrawRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().Get(), stroke_width, stroke_style); IncreasePrimitivesCount(); @@ -194,9 +194,9 @@ void RenderContextImpl::DrawRoundedRectangle(Rect const& rect, Vec2 const& radiu KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().get() : nullptr; + ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().Get() : nullptr; render_target_->DrawRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y), - current_brush_->GetBrush().get(), stroke_width, stroke_style); + current_brush_->GetBrush().Get(), stroke_width, stroke_style); IncreasePrimitivesCount(); } @@ -206,9 +206,9 @@ void RenderContextImpl::DrawEllipse(Point const& center, Vec2 const& radius, Str KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().get() : nullptr; + ID2D1StrokeStyle* stroke_style = stroke ? stroke->GetStrokeStyle().Get() : nullptr; render_target_->DrawEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y), - current_brush_->GetBrush().get(), stroke_width, stroke_style); + current_brush_->GetBrush().Get(), stroke_width, stroke_style); IncreasePrimitivesCount(); } @@ -220,7 +220,7 @@ void RenderContextImpl::FillShape(Shape const& shape) if (shape.IsValid()) { - render_target_->FillGeometry(shape.GetGeometry().get(), current_brush_->GetBrush().get()); + render_target_->FillGeometry(shape.GetGeometry().Get(), current_brush_->GetBrush().Get()); IncreasePrimitivesCount(); } @@ -231,7 +231,7 @@ void RenderContextImpl::FillRectangle(Rect const& rect) KGE_ASSERT(render_target_ && "Render target has not been initialized!"); KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); - render_target_->FillRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().get()); + render_target_->FillRectangle(DX::ConvertToRectF(rect), current_brush_->GetBrush().Get()); IncreasePrimitivesCount(); } @@ -242,7 +242,7 @@ void RenderContextImpl::FillRoundedRectangle(Rect const& rect, Vec2 const& radiu KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); render_target_->FillRoundedRectangle(D2D1::RoundedRect(DX::ConvertToRectF(rect), radius.x, radius.y), - current_brush_->GetBrush().get()); + current_brush_->GetBrush().Get()); IncreasePrimitivesCount(); } @@ -253,7 +253,7 @@ void RenderContextImpl::FillEllipse(Point const& center, Vec2 const& radius) KGE_ASSERT(current_brush_ && "The brush used for rendering has not been set!"); render_target_->FillEllipse(D2D1::Ellipse(DX::ConvertToPoint2F(center), radius.x, radius.y), - current_brush_->GetBrush().get()); + current_brush_->GetBrush().Get()); IncreasePrimitivesCount(); } @@ -271,7 +271,7 @@ void RenderContextImpl::CreateTexture(Texture& texture, math::Vec2T si texture.SetBitmap(saved_bitmap); } - ThrowIfFailed(hr, "Create texture failed"); + KGE_THROW_IF_FAILED(hr, "Create texture failed"); } void RenderContextImpl::PushClipRect(Rect const& clip_rect) @@ -302,7 +302,7 @@ void RenderContextImpl::PushLayer(Layer& layer) } else { - ThrowIfFailed(hr, "Create ID2D1Layer failed"); + KGE_THROW_IF_FAILED(hr, "Create ID2D1Layer failed"); } } @@ -313,11 +313,11 @@ void RenderContextImpl::PushLayer(Layer& layer) mask = layer.GetMaskShape()->GetGeometry(); render_target_->PushLayer( - D2D1::LayerParameters(DX::ConvertToRectF(layer.GetClipRect()), mask.get(), + D2D1::LayerParameters(DX::ConvertToRectF(layer.GetClipRect()), mask.Get(), antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED, DX::ConvertToMatrix3x2F(layer.GetMaskTransform()), layer.GetOpacity(), nullptr, D2D1_LAYER_OPTIONS_NONE), - layer.GetLayer().get()); + layer.GetLayer().Get()); } } @@ -430,7 +430,7 @@ void RenderContextImpl::SaveDrawingState() if (drawing_state_) { - render_target_->SaveDrawingState(drawing_state_.get()); + render_target_->SaveDrawingState(drawing_state_.Get()); } } @@ -440,7 +440,7 @@ void RenderContextImpl::RestoreDrawingState() if (drawing_state_) { - render_target_->RestoreDrawingState(drawing_state_.get()); + render_target_->RestoreDrawingState(drawing_state_.Get()); } } diff --git a/src/kiwano/render/DirectX/RendererImpl.cpp b/src/kiwano/render/DirectX/RendererImpl.cpp index 0782cc51..ee979335 100644 --- a/src/kiwano/render/DirectX/RendererImpl.cpp +++ b/src/kiwano/render/DirectX/RendererImpl.cpp @@ -50,7 +50,7 @@ void RendererImpl::MakeContextForWindow(WindowPtr window) { KGE_SYS_LOG("Creating device resources"); - ThrowIfFailed(::CoInitialize(nullptr), "CoInitialize failed"); + KGE_THROW_IF_FAILED(::CoInitialize(nullptr), "CoInitialize failed"); HWND target_window = window->GetHandle(); output_size_ = window->GetSize(); @@ -83,7 +83,7 @@ void RendererImpl::MakeContextForWindow(WindowPtr window) if (SUCCEEDED(hr)) { - hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.get()); + hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.Get()); } } @@ -94,40 +94,40 @@ void RendererImpl::MakeContextForWindow(WindowPtr window) if (SUCCEEDED(hr)) { - hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.get()); + hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.Get()); } if (SUCCEEDED(hr)) { hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_, - res_font_file_loader_.get()); + res_font_file_loader_.Get()); if (SUCCEEDED(hr)) { hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader( - res_font_collection_loader_.get()); + res_font_collection_loader_.Get()); } } } } } - ThrowIfFailed(hr, "Create render resources failed"); + KGE_THROW_IF_FAILED(hr, "Create render resources failed"); } void RendererImpl::Destroy() { KGE_SYS_LOG("Destroying device resources"); - d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.get()); - res_font_file_loader_.reset(); + d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.Get()); + res_font_file_loader_.Reset(); - d2d_res_->GetDWriteFactory()->UnregisterFontCollectionLoader(res_font_collection_loader_.get()); - res_font_collection_loader_.reset(); + d2d_res_->GetDWriteFactory()->UnregisterFontCollectionLoader(res_font_collection_loader_.Get()); + res_font_collection_loader_.Reset(); - render_ctx_.reset(); - d2d_res_.reset(); - d3d_res_.reset(); + render_ctx_.Reset(); + d2d_res_.Reset(); + d3d_res_.Reset(); ::CoUninitialize(); } @@ -165,7 +165,7 @@ void RendererImpl::Present() hr = HandleDeviceLost(); } - ThrowIfFailed(hr, "Unexpected DXGI exception"); + KGE_THROW_IF_FAILED(hr, "Unexpected DXGI exception"); } HRESULT RendererImpl::HandleDeviceLost() @@ -202,7 +202,7 @@ void RendererImpl::CreateTexture(Texture& texture, String const& file_path) if (SUCCEEDED(hr)) { - WideString full_path = MultiByteToWide(FileSystem::GetInstance().GetFullPathForFile(file_path)); + WideString full_path = string::ToWide(FileSystem::GetInstance().GetFullPathForFile(file_path)); ComPtr decoder; hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path.c_str()); @@ -235,7 +235,7 @@ void RendererImpl::CreateTexture(Texture& texture, String const& file_path) if (FAILED(hr)) { - ThrowIfFailed(hr, "Load texture failed"); + KGE_THROW_IF_FAILED(hr, "Load texture failed"); } } @@ -307,7 +307,7 @@ void RendererImpl::CreateGifImage(GifImage& gif, String const& file_path) if (SUCCEEDED(hr)) { - WideString full_path = MultiByteToWide(FileSystem::GetInstance().GetFullPathForFile(file_path)); + WideString full_path = string::ToWide(FileSystem::GetInstance().GetFullPathForFile(file_path)); ComPtr decoder; hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path.c_str()); @@ -543,7 +543,7 @@ void RendererImpl::CreateFontCollection(Font& font, String const& file_path) if (SUCCEEDED(hr)) { ComPtr font_collection; - hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(font_collection_loader_.get(), key, key_size, + hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(font_collection_loader_.Get(), key, key_size, &font_collection); if (SUCCEEDED(hr)) @@ -553,7 +553,7 @@ void RendererImpl::CreateFontCollection(Font& font, String const& file_path) } } - ThrowIfFailed(hr, "Create font collection failed"); + KGE_THROW_IF_FAILED(hr, "Create font collection failed"); } void RendererImpl::CreateFontCollection(Font& font, Resource const& res) @@ -574,7 +574,7 @@ void RendererImpl::CreateFontCollection(Font& font, Resource const& res) if (SUCCEEDED(hr)) { ComPtr font_collection; - hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(res_font_collection_loader_.get(), key, + hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(res_font_collection_loader_.Get(), key, key_size, &font_collection); if (SUCCEEDED(hr)) @@ -584,7 +584,7 @@ void RendererImpl::CreateFontCollection(Font& font, Resource const& res) } } - ThrowIfFailed(hr, "Create font collection failed"); + KGE_THROW_IF_FAILED(hr, "Create font collection failed"); } void RendererImpl::CreateTextLayout(TextLayout& layout) @@ -599,53 +599,108 @@ void RendererImpl::CreateTextLayout(TextLayout& layout) { layout.SetTextFormat(nullptr); layout.SetTextLayout(nullptr); + layout.SetDirtyFlag(TextLayout::DirtyFlag::Updated); return; } + const TextStyle& style = layout.GetStyle(); + if (!layout.GetTextFormat() || (layout.GetDirtyFlag() & TextLayout::DirtyFlag::DirtyFormat)) { + WideString font_family = style.font_family.empty() ? L"" : string::ToWide(style.font_family); + DWRITE_FONT_WEIGHT font_weight = DWRITE_FONT_WEIGHT(style.font_weight); + DWRITE_FONT_STYLE font_style = style.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL; + IDWriteFontCollection* collection = style.font ? style.font->GetCollection().Get() : nullptr; + ComPtr output; if (SUCCEEDED(hr)) { - const TextStyle& style = layout.GetStyle(); - - hr = d2d_res_->CreateTextFormat(output, MultiByteToWide(style.font_family).c_str(), - style.font ? style.font->GetCollection() : nullptr, - DWRITE_FONT_WEIGHT(style.font_weight), - style.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, + hr = d2d_res_->CreateTextFormat(output, font_family.c_str(), collection, font_weight, font_style, DWRITE_FONT_STRETCH_NORMAL, style.font_size); } if (SUCCEEDED(hr)) { layout.SetTextFormat(output); + layout.SetDirtyFlag(layout.GetDirtyFlag() | TextLayout::DirtyFlag::DirtyLayout); } } if (layout.GetDirtyFlag() & TextLayout::DirtyFlag::DirtyLayout) { ComPtr output; + if (SUCCEEDED(hr)) { - - WideString text = MultiByteToWide(layout.GetText()); + WideString text = string::ToWide(layout.GetText()); hr = d2d_res_->CreateTextLayout(output, text.c_str(), text.length(), layout.GetTextFormat()); } + if (SUCCEEDED(hr)) + { + hr = output->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(style.alignment)); + } + + if (SUCCEEDED(hr)) + { + float wrap_width = style.wrap_width; + bool enable_wrapping = (wrap_width > 0); + + if (SUCCEEDED(hr)) + { + if (enable_wrapping) + { + hr = output->SetWordWrapping(DWRITE_WORD_WRAPPING_WRAP); + } + else + { + hr = output->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP); + } + } + + if (SUCCEEDED(hr)) + { + if (enable_wrapping) + { + hr = output->SetMaxWidth(wrap_width); + } + else + { + // Fix the layout width when the text does not wrap + DWRITE_TEXT_METRICS metrics; + hr = output->GetMetrics(&metrics); + + if (SUCCEEDED(hr)) + { + hr = output->SetMaxWidth(metrics.width); + } + } + } + } + + if (SUCCEEDED(hr)) + { + float spacing = style.line_spacing; + if (spacing == 0.f) + { + hr = output->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0); + } + else + { + hr = output->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_UNIFORM, spacing, spacing * 0.8f); + } + } + if (SUCCEEDED(hr)) { layout.SetTextLayout(output); - - layout.SetAlignment(layout.GetStyle().alignment); - layout.SetWrapWidth(layout.GetStyle().wrap_width); - layout.SetLineSpacing(layout.GetStyle().line_spacing); - - layout.SetDirtyFlag(TextLayout::DirtyFlag::Clean); } } - ThrowIfFailed(hr, "Create text layout failed"); + layout.SetDirtyFlag(TextLayout::DirtyFlag::Updated); + + KGE_THROW_IF_FAILED(hr, "Create text layout failed"); } void RendererImpl::CreateLineShape(Shape& shape, Point const& begin_pos, Point const& end_pos) @@ -681,7 +736,7 @@ void RendererImpl::CreateLineShape(Shape& shape, Point const& begin_pos, Point c shape.SetGeometry(path_geo); } - ThrowIfFailed(hr, "Create ID2D1PathGeometry failed"); + KGE_THROW_IF_FAILED(hr, "Create ID2D1PathGeometry failed"); } void RendererImpl::CreateRectShape(Shape& shape, Rect const& rect) @@ -703,7 +758,7 @@ void RendererImpl::CreateRectShape(Shape& shape, Rect const& rect) shape.SetGeometry(output); } - ThrowIfFailed(hr, "Create ID2D1RectangleGeometry failed"); + KGE_THROW_IF_FAILED(hr, "Create ID2D1RectangleGeometry failed"); } void RendererImpl::CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 const& radius) @@ -726,7 +781,7 @@ void RendererImpl::CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 c shape.SetGeometry(output); } - ThrowIfFailed(hr, "Create ID2D1RoundedRectangleGeometry failed"); + KGE_THROW_IF_FAILED(hr, "Create ID2D1RoundedRectangleGeometry failed"); } void RendererImpl::CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius) @@ -749,7 +804,7 @@ void RendererImpl::CreateEllipseShape(Shape& shape, Point const& center, Vec2 co shape.SetGeometry(output); } - ThrowIfFailed(hr, "Create ID2D1EllipseGeometry failed"); + KGE_THROW_IF_FAILED(hr, "Create ID2D1EllipseGeometry failed"); } void RendererImpl::CreateShapeSink(ShapeSink& sink) @@ -771,7 +826,7 @@ void RendererImpl::CreateShapeSink(ShapeSink& sink) sink.SetPathGeometry(output); } - ThrowIfFailed(hr, "Create ID2D1PathGeometry failed"); + KGE_THROW_IF_FAILED(hr, "Create ID2D1PathGeometry failed"); } void RendererImpl::CreateBrush(Brush& brush, Color const& color) @@ -805,7 +860,7 @@ void RendererImpl::CreateBrush(Brush& brush, Color const& color) } } - ThrowIfFailed(hr, "Create ID2D1SolidBrush failed"); + KGE_THROW_IF_FAILED(hr, "Create ID2D1SolidBrush failed"); } void RendererImpl::CreateBrush(Brush& brush, LinearGradientStyle const& style) @@ -828,7 +883,7 @@ void RendererImpl::CreateBrush(Brush& brush, LinearGradientStyle const& style) ComPtr output; hr = d2d_res_->GetDeviceContext()->CreateLinearGradientBrush( D2D1::LinearGradientBrushProperties(DX::ConvertToPoint2F(style.begin), DX::ConvertToPoint2F(style.end)), - collection.get(), &output); + collection.Get(), &output); if (SUCCEEDED(hr)) { @@ -837,7 +892,7 @@ void RendererImpl::CreateBrush(Brush& brush, LinearGradientStyle const& style) } } - ThrowIfFailed(hr, "Create ID2D1LinearGradientBrush failed"); + KGE_THROW_IF_FAILED(hr, "Create ID2D1LinearGradientBrush failed"); } void RendererImpl::CreateBrush(Brush& brush, RadialGradientStyle const& style) @@ -861,7 +916,7 @@ void RendererImpl::CreateBrush(Brush& brush, RadialGradientStyle const& style) hr = d2d_res_->GetDeviceContext()->CreateRadialGradientBrush( D2D1::RadialGradientBrushProperties(DX::ConvertToPoint2F(style.center), DX::ConvertToPoint2F(style.offset), style.radius.x, style.radius.y), - collection.get(), &output); + collection.Get(), &output); if (SUCCEEDED(hr)) { @@ -870,11 +925,11 @@ void RendererImpl::CreateBrush(Brush& brush, RadialGradientStyle const& style) } } - ThrowIfFailed(hr, "Create ID2D1RadialGradientBrush failed"); + KGE_THROW_IF_FAILED(hr, "Create ID2D1RadialGradientBrush failed"); } void RendererImpl::CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join, - const float* dash_array, size_t dash_size, float dash_offset) + const float* dash_array, size_t dash_size, float dash_offset) { HRESULT hr = S_OK; if (!d2d_res_) @@ -897,7 +952,7 @@ void RendererImpl::CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, Li } } - ThrowIfFailed(hr, "Create ID2D1StrokeStyle failed"); + KGE_THROW_IF_FAILED(hr, "Create ID2D1StrokeStyle failed"); } TextureRenderContextPtr RendererImpl::CreateTextureRenderContext(const Size* desired_size) @@ -966,7 +1021,7 @@ void RendererImpl::Resize(uint32_t width, uint32_t height) render_ctx_->Resize(output_size_); } - ThrowIfFailed(hr, "Resize render target failed"); + KGE_THROW_IF_FAILED(hr, "Resize render target failed"); } } // namespace kiwano diff --git a/src/kiwano/render/DirectX/RendererImpl.h b/src/kiwano/render/DirectX/RendererImpl.h index eae5d49b..2e2d6562 100644 --- a/src/kiwano/render/DirectX/RendererImpl.h +++ b/src/kiwano/render/DirectX/RendererImpl.h @@ -132,13 +132,13 @@ inline RenderContext& RendererImpl::GetContext() inline ID2DDeviceResources* RendererImpl::GetD2DDeviceResources() { KGE_ASSERT(d2d_res_); - return d2d_res_.get(); + return d2d_res_.Get(); } inline ID3DDeviceResources* RendererImpl::GetD3DDeviceResources() { KGE_ASSERT(d3d_res_); - return d3d_res_.get(); + return d3d_res_.Get(); } } // namespace kiwano diff --git a/src/kiwano/render/DirectX/TextRenderer.cpp b/src/kiwano/render/DirectX/TextRenderer.cpp index 45e9b8d4..db051082 100644 --- a/src/kiwano/render/DirectX/TextRenderer.cpp +++ b/src/kiwano/render/DirectX/TextRenderer.cpp @@ -121,8 +121,8 @@ STDMETHODIMP TextRenderer::CreateDeviceResources(_In_ ID2D1RenderTarget* pRT) { HRESULT hr = E_FAIL; - pFactory_.reset(); - pRT_.reset(); + pFactory_.Reset(); + pRT_.Reset(); if (pRT) { @@ -180,7 +180,7 @@ STDMETHODIMP TextRenderer::DrawGlyphRun(__maybenull void* clientDrawingContext, { hr = glyphRun->fontFace->GetGlyphRunOutline( glyphRun->fontEmSize, glyphRun->glyphIndices, glyphRun->glyphAdvances, glyphRun->glyphOffsets, - glyphRun->glyphCount, glyphRun->isSideways, glyphRun->bidiLevel % 2, pSink.get()); + glyphRun->glyphCount, glyphRun->isSideways, glyphRun->bidiLevel % 2, pSink.Get()); } if (SUCCEEDED(hr)) @@ -195,14 +195,14 @@ STDMETHODIMP TextRenderer::DrawGlyphRun(__maybenull void* clientDrawingContext, if (SUCCEEDED(hr)) { - hr = pFactory_->CreateTransformedGeometry(pPathGeometry.get(), &matrix, &pTransformedGeometry); + hr = pFactory_->CreateTransformedGeometry(pPathGeometry.Get(), &matrix, &pTransformedGeometry); } if (SUCCEEDED(hr)) { - pRT_->DrawGeometry(pTransformedGeometry.get(), pOutlineBrush_.get(), + pRT_->DrawGeometry(pTransformedGeometry.Get(), pOutlineBrush_.Get(), fOutlineWidth_ * 2, // twice width for widening - pCurrStrokeStyle_.get()); + pCurrStrokeStyle_.Get()); ++cPrimitivesCount_; } @@ -212,7 +212,7 @@ STDMETHODIMP TextRenderer::DrawGlyphRun(__maybenull void* clientDrawingContext, if (SUCCEEDED(hr) && pFillBrush_) { - pRT_->DrawGlyphRun(D2D1::Point2F(baselineOriginX, baselineOriginY), glyphRun, pFillBrush_.get()); + pRT_->DrawGlyphRun(D2D1::Point2F(baselineOriginX, baselineOriginY), glyphRun, pFillBrush_.Get()); ++cPrimitivesCount_; } @@ -238,20 +238,20 @@ STDMETHODIMP TextRenderer::DrawUnderline(__maybenull void* clientDrawingContext, ComPtr pTransformedGeometry; if (SUCCEEDED(hr)) { - hr = pFactory_->CreateTransformedGeometry(pRectangleGeometry.get(), &matrix, &pTransformedGeometry); + hr = pFactory_->CreateTransformedGeometry(pRectangleGeometry.Get(), &matrix, &pTransformedGeometry); } if (SUCCEEDED(hr) && pOutlineBrush_) { - pRT_->DrawGeometry(pTransformedGeometry.get(), pOutlineBrush_.get(), fOutlineWidth_ * 2, - pCurrStrokeStyle_.get()); + pRT_->DrawGeometry(pTransformedGeometry.Get(), pOutlineBrush_.Get(), fOutlineWidth_ * 2, + pCurrStrokeStyle_.Get()); ++cPrimitivesCount_; } if (SUCCEEDED(hr) && pFillBrush_) { - pRT_->FillGeometry(pTransformedGeometry.get(), pFillBrush_.get()); + pRT_->FillGeometry(pTransformedGeometry.Get(), pFillBrush_.Get()); ++cPrimitivesCount_; } @@ -278,20 +278,20 @@ STDMETHODIMP TextRenderer::DrawStrikethrough(__maybenull void* clientDrawingCont ComPtr pTransformedGeometry; if (SUCCEEDED(hr)) { - hr = pFactory_->CreateTransformedGeometry(pRectangleGeometry.get(), &matrix, &pTransformedGeometry); + hr = pFactory_->CreateTransformedGeometry(pRectangleGeometry.Get(), &matrix, &pTransformedGeometry); } if (SUCCEEDED(hr) && pOutlineBrush_) { - pRT_->DrawGeometry(pTransformedGeometry.get(), pOutlineBrush_.get(), fOutlineWidth_ * 2, - pCurrStrokeStyle_.get()); + pRT_->DrawGeometry(pTransformedGeometry.Get(), pOutlineBrush_.Get(), fOutlineWidth_ * 2, + pCurrStrokeStyle_.Get()); ++cPrimitivesCount_; } if (SUCCEEDED(hr) && pFillBrush_) { - pRT_->FillGeometry(pTransformedGeometry.get(), pFillBrush_.get()); + pRT_->FillGeometry(pTransformedGeometry.Get(), pFillBrush_.Get()); ++cPrimitivesCount_; } diff --git a/src/kiwano/render/Renderer.h b/src/kiwano/render/Renderer.h index fcf8c3c2..87db369e 100644 --- a/src/kiwano/render/Renderer.h +++ b/src/kiwano/render/Renderer.h @@ -67,28 +67,28 @@ public: /// @brief 创建纹理内部资源 /// @param[out] texture 纹理 /// @param[in] file_path 图片路径 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateTexture(Texture& texture, String const& file_path) = 0; /// \~chinese /// @brief 创建纹理内部资源 /// @param[out] texture 纹理 /// @param[in] resource 图片资源 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateTexture(Texture& texture, Resource const& resource) = 0; /// \~chinese /// @brief 创建GIF图像内部资源 /// @param[out] gif GIF图像 /// @param[in] file_path 图片路径 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateGifImage(GifImage& gif, String const& file_path) = 0; /// \~chinese /// @brief 创建GIF图像内部资源 /// @param[out] gif GIF图像 /// @param[in] resource 图片资源 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateGifImage(GifImage& gif, Resource const& resource) = 0; /// \~chinese @@ -96,27 +96,27 @@ public: /// @param[out] frame GIF图像帧 /// @param[in] gif GIF图像 /// @param[in] frame_index 帧下标 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, size_t frame_index) = 0; /// \~chinese /// @brief 创建字体集内部资源 /// @param[out] font 字体 /// @param[in] file_paths 字体文件路径 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateFontCollection(Font& font, String const& file_path) = 0; /// \~chinese /// @brief 创建字体集内部资源 /// @param[out] font 字体 /// @param[in] res_arr 字体资源 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateFontCollection(Font& font, Resource const& res) = 0; /// \~chinese /// @brief 创建文字布局内部资源 /// @param[out] layout 字体布局 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateTextLayout(TextLayout& layout) = 0; /// \~chinese @@ -124,14 +124,14 @@ public: /// @param[out] shape 形状 /// @param[in] begin_pos 线段起点 /// @param[in] end_pos 线段终点 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateLineShape(Shape& shape, Point const& begin_pos, Point const& end_pos) = 0; /// \~chinese /// @brief 创建矩形形状内部资源 /// @param[out] shape 形状 /// @param[in] rect 矩形大小 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateRectShape(Shape& shape, Rect const& rect) = 0; /// \~chinese @@ -139,7 +139,7 @@ public: /// @param[out] shape 形状 /// @param[in] rect 矩形大小 /// @param[in] radius 圆角半径 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateRoundedRectShape(Shape& shape, Rect const& rect, Vec2 const& radius) = 0; /// \~chinese @@ -147,34 +147,34 @@ public: /// @param[out] shape 形状 /// @param[in] center 椭圆圆心 /// @param[in] radius 椭圆半径 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateEllipseShape(Shape& shape, Point const& center, Vec2 const& radius) = 0; /// \~chinese /// @brief 创建几何图形生成器内部资源 /// @param[out] sink 形状生成器 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateShapeSink(ShapeSink& sink) = 0; /// \~chinese /// @brief 创建纯色画刷内部资源 /// @param[out] brush 画刷 /// @param[in] color 颜色 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateBrush(Brush& brush, Color const& color) = 0; /// \~chinese /// @brief 创建线性渐变画刷内部资源 /// @param[out] brush 画刷 /// @param[in] style 线性渐变样式 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateBrush(Brush& brush, LinearGradientStyle const& style) = 0; /// \~chinese /// @brief 创建径向渐变画刷内部资源 /// @param[out] brush 画刷 /// @param[in] style 径向渐变样式 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateBrush(Brush& brush, RadialGradientStyle const& style) = 0; /// \~chinese @@ -185,7 +185,7 @@ public: /// @param[in] dash_array 虚线长度与间隙数组 /// @param[in] dash_size 虚线数组大小 /// @param[in] dash_offset 虚线偏移量 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual void CreateStrokeStyle(StrokeStyle& stroke_style, CapStyle cap, LineJoinStyle line_join, const float* dash_array, size_t dash_size, float dash_offset) = 0; @@ -193,7 +193,7 @@ public: /// @brief 创建纹理渲染上下文 /// @param[in] desired_size 期望的输出大小 /// @return 纹理渲染上下文 - /// @throw std::system_error 创建失败时抛出 + /// @throw kiwano::SystemError 创建失败时抛出 virtual TextureRenderContextPtr CreateTextureRenderContext(const Size* desired_size = nullptr) = 0; public: @@ -219,7 +219,7 @@ public: /// \~chinese /// @brief 将绘制内容呈现至窗口 - /// @throw std::system_error 呈现失败时抛出 + /// @throw kiwano::SystemError 呈现失败时抛出 virtual void Present() = 0; /// \~chinese diff --git a/src/kiwano/render/Shape.cpp b/src/kiwano/render/Shape.cpp index 5e55b6d2..66e2cd54 100644 --- a/src/kiwano/render/Shape.cpp +++ b/src/kiwano/render/Shape.cpp @@ -91,7 +91,7 @@ bool Shape::ComputePointAtLength(float length, Point& point, Vec2& tangent) cons void Shape::Clear() { #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX - geo_.reset(); + geo_.Reset(); #else return; // not supported #endif diff --git a/src/kiwano/render/ShapeSink.cpp b/src/kiwano/render/ShapeSink.cpp index e11cc76d..d0ce33ab 100644 --- a/src/kiwano/render/ShapeSink.cpp +++ b/src/kiwano/render/ShapeSink.cpp @@ -36,10 +36,10 @@ void ShapeSink::Open() #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX if (!IsOpened()) { - path_geo_.reset(); + path_geo_.Reset(); Renderer::GetInstance().CreateShapeSink(*this); - ThrowIfFailed(path_geo_->Open(&sink_), "Open ID2D1GeometrySink failed"); + KGE_THROW_IF_FAILED(path_geo_->Open(&sink_), "Open ID2D1GeometrySink failed"); } #else return; // not supported @@ -51,8 +51,8 @@ void ShapeSink::Close() #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX if (IsOpened()) { - ThrowIfFailed(sink_->Close(), "Close ID2D1GeometrySink failed"); - sink_.reset(); + KGE_THROW_IF_FAILED(sink_->Close(), "Close ID2D1GeometrySink failed"); + sink_.Reset(); } shape_ = new Shape; @@ -90,8 +90,8 @@ ShapeSink& ShapeSink::AddShape(ShapePtr input, const Matrix3x2* input_matrix) ComPtr geo = input->GetGeometry(); HRESULT hr = - geo->Outline(DX::ConvertToMatrix3x2F(input_matrix), D2D1_DEFAULT_FLATTENING_TOLERANCE, sink_.get()); - ThrowIfFailed(hr, "Get outline of ID2D1Geometry failed"); + geo->Outline(DX::ConvertToMatrix3x2F(input_matrix), D2D1_DEFAULT_FLATTENING_TOLERANCE, sink_.Get()); + KGE_THROW_IF_FAILED(hr, "Get outline of ID2D1Geometry failed"); } return (*this); #else @@ -196,9 +196,9 @@ ShapeSink& ShapeSink::Combine(ShapePtr shape_a, ShapePtr shape_b, CombineMode mo ComPtr geo_a_raw = shape_a->geo_; ComPtr geo_b_raw = shape_b->geo_; - HRESULT hr = geo_a_raw->CombineWithGeometry(geo_b_raw.get(), D2D1_COMBINE_MODE(mode), - DX::ConvertToMatrix3x2F(matrix), sink_.get()); - ThrowIfFailed(hr, "Combine ID2D1Geometry failed"); + HRESULT hr = geo_a_raw->CombineWithGeometry(geo_b_raw.Get(), D2D1_COMBINE_MODE(mode), + DX::ConvertToMatrix3x2F(matrix), sink_.Get()); + KGE_THROW_IF_FAILED(hr, "Combine ID2D1Geometry failed"); } #else // not supported @@ -211,7 +211,7 @@ void ShapeSink::Clear() Close(); #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX - path_geo_.reset(); + path_geo_.Reset(); #else // not supported #endif diff --git a/src/kiwano/render/StrokeStyle.cpp b/src/kiwano/render/StrokeStyle.cpp index e188f732..5141e7e7 100644 --- a/src/kiwano/render/StrokeStyle.cpp +++ b/src/kiwano/render/StrokeStyle.cpp @@ -100,7 +100,7 @@ void StrokeStyle::SetDashStyle(DashStyle dash_style) void StrokeStyle::SetDashStyle(const Vector& dash_array) { dash_array_ = dash_array; - style_.reset(); + style_.Reset(); } void StrokeStyle::SetDashStyle(const float* dash_array, size_t dash_size) @@ -109,7 +109,7 @@ void StrokeStyle::SetDashStyle(const float* dash_array, size_t dash_size) dash_array_.clear(); else dash_array_.assign(dash_array, dash_array + dash_size); - style_.reset(); + style_.Reset(); } #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX diff --git a/src/kiwano/render/StrokeStyle.h b/src/kiwano/render/StrokeStyle.h index 99b300cc..0fd67b7d 100644 --- a/src/kiwano/render/StrokeStyle.h +++ b/src/kiwano/render/StrokeStyle.h @@ -206,19 +206,19 @@ inline float StrokeStyle::GetDashOffset() const inline void StrokeStyle::SetCapStyle(CapStyle cap) { cap_ = cap; - style_.reset(); + style_.Reset(); } inline void StrokeStyle::SetLineJoinStyle(LineJoinStyle line_join) { line_join_ = line_join; - style_.reset(); + style_.Reset(); } inline void StrokeStyle::SetDashOffset(float dash_offset) { dash_offset_ = dash_offset; - style_.reset(); + style_.Reset(); } inline bool StrokeStyle::IsValid() const diff --git a/src/kiwano/render/TextLayout.cpp b/src/kiwano/render/TextLayout.cpp index 09b77838..ba7806db 100644 --- a/src/kiwano/render/TextLayout.cpp +++ b/src/kiwano/render/TextLayout.cpp @@ -136,81 +136,29 @@ Size TextLayout::GetLayoutSize() const void TextLayout::SetWrapWidth(float wrap_width) { - style_.wrap_width = wrap_width; - -#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX - if (text_layout_) + if (style_.wrap_width != wrap_width) { - HRESULT hr = S_OK; - bool enable_wrapping = (wrap_width > 0); - - if (SUCCEEDED(hr)) - { - hr = text_layout_->SetWordWrapping(enable_wrapping ? DWRITE_WORD_WRAPPING_WRAP - : DWRITE_WORD_WRAPPING_NO_WRAP); - } - - if (SUCCEEDED(hr)) - { - if (enable_wrapping) - { - hr = text_layout_->SetMaxWidth(wrap_width); - } - else - { - // Fix the layout width when the text does not wrap - DWRITE_TEXT_METRICS metrics; - hr = text_layout_->GetMetrics(&metrics); - - if (SUCCEEDED(hr)) - { - hr = text_layout_->SetMaxWidth(metrics.width); - } - } - } - ThrowIfFailed(hr, "Apply word wrapping to text layout failed"); + style_.wrap_width = wrap_width; + dirty_flag_ |= DirtyFlag::DirtyLayout; } -#else - return; // not supported -#endif } void TextLayout::SetLineSpacing(float line_spacing) { - style_.line_spacing = line_spacing; - -#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX - if (text_layout_) + if (style_.line_spacing != line_spacing) { - HRESULT hr = S_OK; - if (line_spacing == 0.f) - { - hr = text_layout_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0); - } - else - { - hr = text_layout_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_UNIFORM, line_spacing, line_spacing * 0.8f); - } - ThrowIfFailed(hr, "Apply line spacing to text layout failed"); + style_.line_spacing = line_spacing; + dirty_flag_ |= DirtyFlag::DirtyLayout; } -#else - return; // not supported -#endif } void TextLayout::SetAlignment(TextAlign align) { - style_.alignment = align; - -#if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX - if (text_layout_) + if (style_.alignment != align) { - HRESULT hr = text_layout_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(align)); - ThrowIfFailed(hr, "Apply alignment style to text layout failed"); + style_.alignment = align; + dirty_flag_ |= DirtyFlag::DirtyLayout; } -#else - return; // not supported -#endif } void TextLayout::SetUnderline(bool enable, uint32_t start, uint32_t length) @@ -225,7 +173,7 @@ void TextLayout::SetUnderline(bool enable, uint32_t start, uint32_t length) { hr = text_layout_->SetUnderline(enable, { start, length }); } - ThrowIfFailed(hr, "Apply underline style to text layout failed"); + KGE_THROW_IF_FAILED(hr, "Apply underline style to text layout failed"); #else return; // not supported #endif @@ -243,7 +191,7 @@ void TextLayout::SetStrikethrough(bool enable, uint32_t start, uint32_t length) { hr = text_layout_->SetStrikethrough(enable, { start, length }); } - ThrowIfFailed(hr, "Apply strikethrough style to text layout failed"); + KGE_THROW_IF_FAILED(hr, "Apply strikethrough style to text layout failed"); #else return; // not supported #endif diff --git a/src/kiwano/render/Texture.cpp b/src/kiwano/render/Texture.cpp index 44de3671..3d07a245 100644 --- a/src/kiwano/render/Texture.cpp +++ b/src/kiwano/render/Texture.cpp @@ -107,9 +107,9 @@ void Texture::CopyFrom(TexturePtr copy_from) #if KGE_RENDER_ENGINE == KGE_RENDER_ENGINE_DIRECTX if (IsValid() && copy_from) { - HRESULT hr = bitmap_->CopyFromBitmap(nullptr, copy_from->GetBitmap().get(), nullptr); + HRESULT hr = bitmap_->CopyFromBitmap(nullptr, copy_from->GetBitmap().Get(), nullptr); - ThrowIfFailed(hr, "Copy texture data failed"); + KGE_THROW_IF_FAILED(hr, "Copy texture data failed"); } #else return; // not supported @@ -122,11 +122,11 @@ void Texture::CopyFrom(TexturePtr copy_from, Rect const& src_rect, Point const& if (IsValid() && copy_from) { HRESULT hr = bitmap_->CopyFromBitmap( - &D2D1::Point2U(uint32_t(dest_point.x), uint32_t(dest_point.y)), copy_from->GetBitmap().get(), + &D2D1::Point2U(uint32_t(dest_point.x), uint32_t(dest_point.y)), copy_from->GetBitmap().Get(), &D2D1::RectU(uint32_t(src_rect.GetLeft()), uint32_t(src_rect.GetTop()), uint32_t(src_rect.GetRight()), uint32_t(src_rect.GetBottom()))); - ThrowIfFailed(hr, "Copy texture data failed"); + KGE_THROW_IF_FAILED(hr, "Copy texture data failed"); } #else return; // not supported diff --git a/src/kiwano/render/TextureCache.cpp b/src/kiwano/render/TextureCache.cpp index e590a118..4d464681 100644 --- a/src/kiwano/render/TextureCache.cpp +++ b/src/kiwano/render/TextureCache.cpp @@ -57,7 +57,8 @@ TextureCache::~TextureCache() {} TexturePtr TextureCache::AddOrGetTexture(String const& file_path) { - return CreateOrGetCache(texture_cache_, file_path, file_path.hash()); + size_t hash = std::hash()(file_path); + return CreateOrGetCache(texture_cache_, file_path, hash); } TexturePtr TextureCache::AddOrGetTexture(Resource const& res) @@ -67,7 +68,8 @@ TexturePtr TextureCache::AddOrGetTexture(Resource const& res) GifImagePtr TextureCache::AddOrGetGifImage(String const& file_path) { - return CreateOrGetCache(gif_texture_cache_, file_path, file_path.hash()); + size_t hash = std::hash()(file_path); + return CreateOrGetCache(gif_texture_cache_, file_path, hash); } GifImagePtr TextureCache::AddOrGetGifImage(Resource const& res) @@ -77,7 +79,8 @@ GifImagePtr TextureCache::AddOrGetGifImage(Resource const& res) void TextureCache::RemoveTexture(String const& file_path) { - RemoveCache(texture_cache_, file_path.hash()); + size_t hash = std::hash()(file_path); + RemoveCache(texture_cache_, hash); } void TextureCache::RemoveTexture(Resource const& res) @@ -87,7 +90,8 @@ void TextureCache::RemoveTexture(Resource const& res) void TextureCache::RemoveGifImage(String const& file_path) { - RemoveCache(gif_texture_cache_, file_path.hash()); + size_t hash = std::hash()(file_path); + RemoveCache(gif_texture_cache_, hash); } void TextureCache::RemoveGifImage(Resource const& res) diff --git a/src/kiwano/utils/LocalStorage.cpp b/src/kiwano/utils/LocalStorage.cpp index 172a635c..12177fd5 100644 --- a/src/kiwano/utils/LocalStorage.cpp +++ b/src/kiwano/utils/LocalStorage.cpp @@ -77,7 +77,7 @@ int LocalStorage::GetInt(String const& key, int default_value) const float LocalStorage::GetFloat(String const& key, float default_value) const { char temp[32] = { 0 }; - String default_str = String::parse(default_value); + String default_str = std::to_string(default_value); ::GetPrivateProfileStringA(field_name_.c_str(), key.c_str(), default_str.c_str(), temp, 31, file_path_.c_str()); return std::stof(temp); } @@ -85,7 +85,7 @@ float LocalStorage::GetFloat(String const& key, float default_value) const double LocalStorage::GetDouble(String const& key, double default_value) const { char temp[32] = { 0 }; - String default_str = String::parse(default_value); + String default_str = std::to_string(default_value); ::GetPrivateProfileStringA(field_name_.c_str(), key.c_str(), default_str.c_str(), temp, 31, file_path_.c_str()); return std::stod(temp); } diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp index 681c20da..71ba748d 100644 --- a/src/kiwano/utils/ResourceCache.cpp +++ b/src/kiwano/utils/ResourceCache.cpp @@ -30,7 +30,7 @@ namespace resource_cache_01 { bool LoadJsonData(ResourceCache* loader, Json const& json_data); -bool LoadXmlData(ResourceCache* loader, const pugi::xml_node& elem); +bool LoadXmlData(ResourceCache* loader, const XmlNode& elem); } // namespace resource_cache_01 @@ -42,7 +42,7 @@ Map> load_json_funcs = { { "0.1", resource_cache_01::LoadJsonData }, }; -Map> load_xml_funcs = { +Map> load_xml_funcs = { { "latest", resource_cache_01::LoadXmlData }, { "0.1", resource_cache_01::LoadXmlData }, }; @@ -127,9 +127,9 @@ bool ResourceCache::LoadFromXmlFile(String const& file_path) String full_path = FileSystem::GetInstance().GetFullPathForFile(file_path); - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(full_path.c_str(), pugi::parse_default, pugi::encoding_auto); + XmlDocument doc; + auto result = doc.load_file(full_path.c_str()); if (result) { return LoadFromXml(doc); @@ -141,9 +141,9 @@ bool ResourceCache::LoadFromXmlFile(String const& file_path) } } -bool ResourceCache::LoadFromXml(const pugi::xml_document& doc) +bool ResourceCache::LoadFromXml(const XmlDocument& doc) { - if (pugi::xml_node root = doc.child("resources")) + if (XmlNode root = doc.child("resources")) { String version; if (auto version_node = root.child("version")) @@ -313,7 +313,7 @@ bool LoadJsonData(ResourceCache* loader, Json const& json_data) GlobalData global_data; if (json_data.count("path")) { - global_data.path = json_data["path"]; + global_data.path = json_data["path"].get(); } if (json_data.count("images")) @@ -385,7 +385,7 @@ bool LoadJsonData(ResourceCache* loader, Json const& json_data) return true; } -bool LoadXmlData(ResourceCache* loader, const pugi::xml_node& elem) +bool LoadXmlData(ResourceCache* loader, const XmlNode& elem) { GlobalData global_data; if (auto path = elem.child("path")) diff --git a/src/kiwano/utils/ResourceCache.h b/src/kiwano/utils/ResourceCache.h index c4be9e9b..12fe458b 100644 --- a/src/kiwano/utils/ResourceCache.h +++ b/src/kiwano/utils/ResourceCache.h @@ -22,9 +22,10 @@ #include #include #include +#include +#include #include #include -#include <3rd-party/pugixml/pugixml.hpp> namespace kiwano { @@ -54,7 +55,7 @@ public: /// \~chinese /// @brief 从 XML 文档对象加载资源信息 /// @param doc XML文档对象 - bool LoadFromXml(pugi::xml_document const& doc); + bool LoadFromXml(XmlDocument const& doc); /// \~chinese /// @brief 获取资源 @@ -69,7 +70,7 @@ public: template SmartPtr<_Ty> Get(String const& id) const { - return dynamic_cast<_Ty*>(Get(id).get()); + return dynamic_cast<_Ty*>(Get(id).Get()); } /// \~chinese