diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj index e29eacc9..b3b2c395 100644 --- a/projects/kiwano/kiwano.vcxproj +++ b/projects/kiwano/kiwano.vcxproj @@ -14,6 +14,7 @@ + diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters index 2d84d245..94abf255 100644 --- a/projects/kiwano/kiwano.vcxproj.filters +++ b/projects/kiwano/kiwano.vcxproj.filters @@ -294,6 +294,9 @@ utils + + core + diff --git a/src/kiwano/core/any.hpp b/src/kiwano/core/any.hpp new file mode 100644 index 00000000..3223fcd8 --- /dev/null +++ b/src/kiwano/core/any.hpp @@ -0,0 +1,374 @@ +// Copyright (c) 2018-2019 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 +{ + +inline namespace core +{ + +class any +{ +public: + any() : storage_{} + { + } + + template < + typename _Ty, + typename _Decayed = typename std::decay<_Ty>::type, + typename = typename std::enable_if::value>::type + > + any(_Ty&& val) : storage_{} + { + emplace<_Decayed>(std::forward<_Ty&&>(val)); + } + + template < + typename _Ty, + typename _Decayed = typename std::decay<_Ty>::type, + typename... _Args + > + any(_Args&&... args) : storage_{} + { + emplace<_Decayed>(std::forward<_Args>(args)...); + } + + any(const any& rhs) : storage_{} + { + 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()); + } + } + } + + 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 + void emplace(_Args&&... args) + { + reset(); + store<_Decayed>(decayed_is_small<_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(); + } + + 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 + 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 + 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 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_SPACE_SIZE = 16U; + + 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(void* const ptr) noexcept + { + return ::new _Ty(*static_cast<_Ty*>(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*, const 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, const void* const ptr) noexcept + { + return ::new (static_cast<_Ty*>(target)) _Ty(std::move(*static_cast(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_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 storage_; +}; + +} + +} diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp index b87e13ea..2c75a649 100644 --- a/src/kiwano/utils/ResourceCache.cpp +++ b/src/kiwano/utils/ResourceCache.cpp @@ -21,12 +21,14 @@ #include #include +#include #include #include #include #include #include + namespace kiwano { namespace __resource_cache_01 @@ -59,13 +61,20 @@ namespace kiwano bool ResourceCache::LoadFromJsonFile(String const& file_path) { + if (!FileSystem::GetInstance()->IsFileExists(file_path)) + { + KGE_WARNING_LOG(L"ResourceCache::LoadFromJsonFile failed: File not found."); + return false; + } + Json json_data; std::wifstream ifs; ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { - ifs.open(file_path.c_str()); + String full_path = FileSystem::GetInstance()->GetFullPathForFile(file_path); + ifs.open(full_path.c_str()); ifs >> json_data; ifs.close(); } @@ -112,14 +121,20 @@ namespace kiwano bool ResourceCache::LoadFromXmlFile(String const& file_path) { - tinyxml2::XMLDocument doc; + if (!FileSystem::GetInstance()->IsFileExists(file_path)) + { + KGE_WARNING_LOG(L"ResourceCache::LoadFromXmlFile failed: File not found."); + return false; + } + tinyxml2::XMLDocument doc; std::wifstream ifs; ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit); try { - ifs.open(file_path.c_str()); + String full_path = FileSystem::GetInstance()->GetFullPathForFile(file_path); + ifs.open(full_path.c_str()); StringStream ss; ss << ifs.rdbuf(); @@ -192,7 +207,7 @@ namespace kiwano { if (frame) { - cache_.insert(std::make_pair(id, frame)); + object_cache_.insert(std::make_pair(id, frame)); return true; } return false; @@ -268,7 +283,7 @@ namespace kiwano { if (frames) { - cache_.insert(std::make_pair(id, frames)); + object_cache_.insert(std::make_pair(id, frames)); return frames->GetFrames().size(); } return 0; @@ -278,7 +293,7 @@ namespace kiwano { if (obj) { - cache_.insert(std::make_pair(id, obj)); + object_cache_.insert(std::make_pair(id, obj)); return true; } return false; @@ -340,14 +355,14 @@ namespace kiwano return FontCollection(); } - void ResourceCache::Delete(String const & id) + void ResourceCache::Remove(String const & id) { - cache_.erase(id); + object_cache_.erase(id); } void ResourceCache::Clear() { - cache_.clear(); + object_cache_.clear(); } } diff --git a/src/kiwano/utils/ResourceCache.h b/src/kiwano/utils/ResourceCache.h index c6967f25..a67003c0 100644 --- a/src/kiwano/utils/ResourceCache.h +++ b/src/kiwano/utils/ResourceCache.h @@ -19,7 +19,6 @@ // THE SOFTWARE. #pragma once -#include #include #include #include @@ -87,7 +86,7 @@ namespace kiwano FontCollection GetFontCollection(String const& id) const; // 删除指定资源 - void Delete(String const& id); + void Remove(String const& id); // 清空所有资源 void Clear(); @@ -95,8 +94,8 @@ namespace kiwano template _Ty* Get(String const& id) const { - auto iter = cache_.find(id); - if (iter == cache_.end()) + auto iter = object_cache_.find(id); + if (iter == object_cache_.end()) return nullptr; return dynamic_cast<_Ty*>((*iter).second.get()); } @@ -107,9 +106,8 @@ namespace kiwano virtual ~ResourceCache(); protected: - UnorderedMap cache_; - - UnorderedMap gif_cache_; - UnorderedMap font_collection_cache_; + UnorderedMap object_cache_; + UnorderedMap gif_cache_; + UnorderedMap font_collection_cache_; }; }