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_;
};
}