Add FileSystem & LocalStorage
This commit is contained in:
parent
cbcfc231c6
commit
6d266d7e2d
|
|
@ -77,7 +77,7 @@
|
|||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/3rd-party;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;</AdditionalIncludeDirectories>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
|
@ -95,7 +95,7 @@
|
|||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/3rd-party;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;</AdditionalIncludeDirectories>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/3rd-party;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;</AdditionalIncludeDirectories>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
|
@ -97,7 +97,7 @@
|
|||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/3rd-party;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;</AdditionalIncludeDirectories>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<ClInclude Include="..\..\src\kiwano-network\kiwano-network.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-network\src\HttpClient.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-network\src\HttpRequest.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-network\src\HttpResponse.h" />
|
||||
<ClInclude Include="..\..\src\kiwano-network\src\HttpResponse.hpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\kiwano-network\src\HttpClient.cpp" />
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/3rd-party;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;</AdditionalIncludeDirectories>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
|
@ -93,7 +93,7 @@
|
|||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/3rd-party;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;</AdditionalIncludeDirectories>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
<ClInclude Include="..\..\src\kiwano-network\src\HttpRequest.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano-network\src\HttpResponse.h">
|
||||
<ClInclude Include="..\..\src\kiwano-network\src\HttpResponse.hpp">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -86,9 +86,8 @@
|
|||
<ClInclude Include="..\..\src\kiwano\renderer\win32\TextRenderer.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\ui\Button.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\ui\Menu.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\utils\DataUtil.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\utils\FileUtil.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\utils\Path.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\utils\LocalStorage.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\utils\FileSystem.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\utils\ResourceCache.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
@ -146,9 +145,8 @@
|
|||
<ClCompile Include="..\..\src\kiwano\renderer\win32\TextRenderer.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\ui\Button.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\ui\Menu.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\utils\DataUtil.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\utils\FileUtil.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\utils\Path.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\utils\LocalStorage.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\utils\FileSystem.cpp" />
|
||||
<ClCompile Include="..\..\src\kiwano\utils\ResourceCache.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
|
|
@ -215,7 +213,7 @@
|
|||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/3rd-party;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
|
@ -233,7 +231,7 @@
|
|||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/3rd-party;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
|
|
|||
|
|
@ -102,9 +102,6 @@
|
|||
<ClInclude Include="..\..\src\kiwano\platform\modules.h">
|
||||
<Filter>platform</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\utils\Path.h">
|
||||
<Filter>utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\config.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\macros.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\math\Vec2.hpp">
|
||||
|
|
@ -117,9 +114,6 @@
|
|||
<Filter>base</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\kiwano.h" />
|
||||
<ClInclude Include="..\..\src\kiwano\utils\DataUtil.h">
|
||||
<Filter>utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\base\Timer.h">
|
||||
<Filter>base</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -129,9 +123,6 @@
|
|||
<ClInclude Include="..\..\src\kiwano\base\AsyncTask.h">
|
||||
<Filter>base</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\utils\FileUtil.h">
|
||||
<Filter>utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\2d\GifSprite.h">
|
||||
<Filter>2d</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -297,6 +288,12 @@
|
|||
<ClInclude Include="..\..\src\kiwano\base\win32\helper.h">
|
||||
<Filter>base\win32</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\utils\LocalStorage.h">
|
||||
<Filter>utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kiwano\utils\FileSystem.h">
|
||||
<Filter>utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\kiwano\ui\Button.cpp">
|
||||
|
|
@ -338,15 +335,9 @@
|
|||
<ClCompile Include="..\..\src\kiwano\platform\modules.cpp">
|
||||
<Filter>platform</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\utils\Path.cpp">
|
||||
<Filter>utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\base\Input.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\utils\DataUtil.cpp">
|
||||
<Filter>utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\base\Timer.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -356,9 +347,6 @@
|
|||
<ClCompile Include="..\..\src\kiwano\base\AsyncTask.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\utils\FileUtil.cpp">
|
||||
<Filter>utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\2d\GifSprite.cpp">
|
||||
<Filter>2d</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -473,5 +461,11 @@
|
|||
<ClCompile Include="..\..\src\kiwano\base\Component.cpp">
|
||||
<Filter>base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\utils\LocalStorage.cpp">
|
||||
<Filter>utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kiwano\utils\FileSystem.cpp">
|
||||
<Filter>utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include <kiwano/base/Logger.h>
|
||||
#include <kiwano/utils/FileUtil.h>
|
||||
#include <kiwano/utils/FileSystem.h>
|
||||
#include "Sound.h"
|
||||
#include "AudioEngine.h"
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ namespace kiwano
|
|||
|
||||
bool Sound::Load(String const& file_path)
|
||||
{
|
||||
if (!FileUtil::ExistsFile(file_path))
|
||||
if (!FileSystem::GetInstance()->IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Media file '%s' not found", file_path.c_str());
|
||||
return false;
|
||||
|
|
@ -65,7 +65,9 @@ namespace kiwano
|
|||
Close();
|
||||
}
|
||||
|
||||
HRESULT hr = transcoder_.LoadMediaFile(file_path);
|
||||
String full_path = FileSystem::GetInstance()->GetFullPathForFile(file_path);
|
||||
|
||||
HRESULT hr = transcoder_.LoadMediaFile(full_path);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,4 +24,4 @@
|
|||
#include "src/ImGuiModule.h"
|
||||
|
||||
// ImGui
|
||||
#include <imgui/imgui.h>
|
||||
#include <3rd-party/imgui/imgui.h>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// dear imgui: Renderer for Kiwano (DirectX10)
|
||||
|
||||
#pragma once
|
||||
#include <imgui/imgui.h>
|
||||
#include <3rd-party/imgui/imgui.h>
|
||||
|
||||
struct ID3D10Device;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// dear imgui: Renderer for Kiwano (DirectX11)
|
||||
|
||||
#pragma once
|
||||
#include <imgui/imgui.h>
|
||||
#include <3rd-party/imgui/imgui.h>
|
||||
|
||||
struct ID3D11Device;
|
||||
struct ID3D11DeviceContext;
|
||||
|
|
|
|||
|
|
@ -21,5 +21,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "src/HttpRequest.h"
|
||||
#include "src/HttpResponse.h"
|
||||
#include "src/HttpResponse.hpp"
|
||||
#include "src/HttpClient.h"
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@
|
|||
#include <codecvt>
|
||||
|
||||
#include "HttpRequest.h"
|
||||
#include "HttpResponse.h"
|
||||
#include "HttpResponse.hpp"
|
||||
#include "HttpClient.h"
|
||||
|
||||
#include <kiwano/base/Logger.h>
|
||||
#include <kiwano/platform/Application.h>
|
||||
#include <curl/curl.h> // CURL
|
||||
#include <3rd-party/curl/curl.h> // CURL
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <kiwano/core/Function.hpp>
|
||||
#include <kiwano/core/function.hpp>
|
||||
#include <kiwano/core/basic_json.hpp>
|
||||
#include <kiwano/base/ObjectBase.h>
|
||||
#include <kiwano/base/SmartPtr.hpp>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#include "../Logger.h"
|
||||
#include <StackWalker/StackWalker.h>
|
||||
#include <3rd-party/StackWalker/StackWalker.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
|
|||
|
|
@ -135,9 +135,8 @@
|
|||
// utils
|
||||
//
|
||||
|
||||
#include "utils/Path.h"
|
||||
#include "utils/DataUtil.h"
|
||||
#include "utils/FileUtil.h"
|
||||
#include "utils/FileSystem.h"
|
||||
#include "utils/LocalStorage.h"
|
||||
#include "utils/ResourceCache.h"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include "Renderer.h"
|
||||
#include "../base/win32/helper.h"
|
||||
#include "../base/Window.h"
|
||||
#include "../utils/FileUtil.h"
|
||||
#include "../utils/FileSystem.h"
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -247,7 +247,7 @@ namespace kiwano
|
|||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!FileUtil::ExistsFile(file_path))
|
||||
if (!FileSystem::GetInstance()->IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Texture file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
|
|
@ -255,8 +255,10 @@ namespace kiwano
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
String full_path = FileSystem::GetInstance()->GetFullPathForFile(file_path);
|
||||
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, file_path);
|
||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
|
@ -363,7 +365,7 @@ namespace kiwano
|
|||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!FileUtil::ExistsFile(file_path))
|
||||
if (!FileSystem::GetInstance()->IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Gif texture file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
|
|
@ -371,8 +373,10 @@ namespace kiwano
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
String full_path = FileSystem::GetInstance()->GetFullPathForFile(file_path);
|
||||
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, file_path);
|
||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, full_path);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
|
@ -586,15 +590,19 @@ namespace kiwano
|
|||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
Vector<String> full_paths(file_paths);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
for (const auto& file_path : file_paths)
|
||||
for (auto& file_path : full_paths)
|
||||
{
|
||||
if (!FileUtil::ExistsFile(file_path))
|
||||
if (!FileSystem::GetInstance()->IsFileExists(file_path))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Font file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
file_path = FileSystem::GetInstance()->GetFullPathForFile(file_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -603,7 +611,7 @@ namespace kiwano
|
|||
LPVOID collection_key = nullptr;
|
||||
std::uint32_t collection_key_size = 0;
|
||||
|
||||
hr = font_collection_loader_->AddFilePaths(file_paths, &collection_key, &collection_key_size);
|
||||
hr = font_collection_loader_->AddFilePaths(full_paths, &collection_key, &collection_key_size);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,208 @@
|
|||
// 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.
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "../platform/modules.h"
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
namespace
|
||||
{
|
||||
inline String ConvertPathFormat(String const& path)
|
||||
{
|
||||
// C:\a\b\c.txt => C:/a/b/c.txt
|
||||
|
||||
size_t len = path.length();
|
||||
String result = path;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
if (result[i] == L'\\')
|
||||
{
|
||||
result[i] = L'/';
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline bool IsFileExists(String const& path)
|
||||
{
|
||||
DWORD dwAttrib = ::GetFileAttributesW(path.c_str());
|
||||
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
||||
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
}
|
||||
|
||||
FileSystem::FileSystem()
|
||||
{
|
||||
}
|
||||
|
||||
FileSystem::~FileSystem()
|
||||
{
|
||||
}
|
||||
|
||||
void FileSystem::AddSearchPath(String const& path)
|
||||
{
|
||||
String search_path = ConvertPathFormat(path);
|
||||
if (!search_path.empty() && search_path[search_path.length() - 1] != L'/')
|
||||
{
|
||||
search_path += L"/";
|
||||
}
|
||||
|
||||
search_paths_.push_back(search_path);
|
||||
}
|
||||
|
||||
void FileSystem::SetSearchPaths(Vector<String> const& paths)
|
||||
{
|
||||
search_paths_ = paths;
|
||||
|
||||
for (auto& path : search_paths_)
|
||||
{
|
||||
path = ConvertPathFormat(path);
|
||||
if (!path.empty() && path[path.length() - 1] != L'/')
|
||||
{
|
||||
path += L"/";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String FileSystem::GetFullPathForFile(String const& file) const
|
||||
{
|
||||
if (file.empty())
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
|
||||
if (IsAbsolutePath(file))
|
||||
{
|
||||
return file;
|
||||
}
|
||||
|
||||
// Search file path cache
|
||||
auto cache_iter = file_lookup_cache_.find(file);
|
||||
if (cache_iter != file_lookup_cache_.end())
|
||||
{
|
||||
return cache_iter->second;
|
||||
}
|
||||
|
||||
String dict_path;
|
||||
|
||||
// Search file path dictionary
|
||||
auto iter = file_lookup_dict_.find(file);
|
||||
if (iter != file_lookup_dict_.end())
|
||||
{
|
||||
dict_path = iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
dict_path = ConvertPathFormat(file);
|
||||
}
|
||||
|
||||
if (kiwano::IsFileExists(dict_path))
|
||||
{
|
||||
file_lookup_cache_.emplace(file, dict_path);
|
||||
return dict_path;
|
||||
}
|
||||
|
||||
for (const auto& search_path : search_paths_)
|
||||
{
|
||||
String full_path = search_path + dict_path;
|
||||
if (kiwano::IsFileExists(full_path))
|
||||
{
|
||||
file_lookup_cache_.emplace(file, full_path); // Save to cache
|
||||
return full_path;
|
||||
}
|
||||
}
|
||||
|
||||
// File not found
|
||||
return L"";
|
||||
}
|
||||
|
||||
void FileSystem::AddFileLookupRule(String const& key, String const& file_path)
|
||||
{
|
||||
file_lookup_dict_.emplace(key, ConvertPathFormat(file_path));
|
||||
}
|
||||
|
||||
void FileSystem::SetFileLookupDictionary(UnorderedMap<String, String> const& dict)
|
||||
{
|
||||
file_lookup_cache_.clear();
|
||||
|
||||
file_lookup_dict_ = dict;
|
||||
}
|
||||
|
||||
bool FileSystem::IsFileExists(String const& file_path) const
|
||||
{
|
||||
if (IsAbsolutePath(file_path))
|
||||
{
|
||||
return kiwano::IsFileExists(file_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
String full_path = GetFullPathForFile(file_path);
|
||||
return !full_path.empty();
|
||||
}
|
||||
}
|
||||
|
||||
bool FileSystem::IsAbsolutePath(String const& path) const
|
||||
{
|
||||
// like "C:\some.file"
|
||||
return path.length() > 2 && ((std::isalpha(path[0]) && path[1] == L':') || (path[0] == L'/' && path[1] == L'/'));
|
||||
}
|
||||
|
||||
bool FileSystem::RemoveFile(String const& file_path) const
|
||||
{
|
||||
if (::DeleteFileW(file_path.c_str()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileSystem::ExtractResourceToFile(Resource const& res, String const& dest_file_name) const
|
||||
{
|
||||
HANDLE file_handle = ::CreateFileW(
|
||||
dest_file_name.c_str(),
|
||||
GENERIC_WRITE,
|
||||
NULL,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
Resource::Data data = res.GetData();
|
||||
if (data)
|
||||
{
|
||||
DWORD written_bytes = 0;
|
||||
::WriteFile(file_handle, data.buffer, data.size, &written_bytes, NULL);
|
||||
::CloseHandle(file_handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
::CloseHandle(file_handle);
|
||||
::DeleteFile(dest_file_name.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -19,28 +19,55 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "../macros.h"
|
||||
#include "../base/Resource.h"
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
// 文件
|
||||
class KGE_API FileUtil
|
||||
class KGE_API FileSystem
|
||||
: public Singleton<FileSystem>
|
||||
{
|
||||
public:
|
||||
// 删除文件
|
||||
static bool Delete(String const& file_path);
|
||||
KGE_DECLARE_SINGLETON(FileSystem);
|
||||
|
||||
// 释放二进制资源到临时文件目录
|
||||
static bool Extract(
|
||||
Resource const& res, /* 资源 */
|
||||
String const& dest_file_name /* 目标文件名 */
|
||||
);
|
||||
public:
|
||||
// 添加文件搜索路径
|
||||
void AddSearchPath(String const& path);
|
||||
|
||||
// 设置文件搜索路径
|
||||
void SetSearchPaths(Vector<String> const& paths);
|
||||
|
||||
// 获取文件的完整路径
|
||||
String GetFullPathForFile(String const& file) const;
|
||||
|
||||
// 添加文件路径查找字典规则
|
||||
void AddFileLookupRule(String const& key, String const& file_path);
|
||||
|
||||
// 设置文件路径查找字典
|
||||
void SetFileLookupDictionary(UnorderedMap<String, String> const& dict);
|
||||
|
||||
// 文件是否存在
|
||||
static bool ExistsFile(String const& file_path);
|
||||
bool IsFileExists(String const& file_path) const;
|
||||
|
||||
// 文件夹是否存在
|
||||
static bool ExistsDirectory(String const& dir_path);
|
||||
// 判断路径是否是绝对路径
|
||||
bool IsAbsolutePath(String const& path) const;
|
||||
|
||||
// 删除文件
|
||||
bool RemoveFile(String const& file_path) const;
|
||||
|
||||
// 释放二进制资源到临时文件目录
|
||||
bool ExtractResourceToFile(
|
||||
Resource const& res, /* 资源 */
|
||||
String const& dest_file_name /* 目标文件名 */
|
||||
) const;
|
||||
|
||||
private:
|
||||
FileSystem();
|
||||
|
||||
~FileSystem();
|
||||
|
||||
private:
|
||||
Vector<String> search_paths_;
|
||||
UnorderedMap<String, String> file_lookup_dict_;
|
||||
mutable UnorderedMap<String, String> file_lookup_cache_;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
// 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.
|
||||
|
||||
#include "FileUtil.h"
|
||||
#include "../platform/modules.h"
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
||||
bool FileUtil::Delete(String const& file_path)
|
||||
{
|
||||
if (::DeleteFile(file_path.c_str()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileUtil::Extract(Resource const& res, String const& dest_file_name)
|
||||
{
|
||||
HANDLE file_handle = ::CreateFile(
|
||||
dest_file_name.c_str(),
|
||||
GENERIC_WRITE,
|
||||
NULL,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_TEMPORARY,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
Resource::Data data = res.GetData();
|
||||
if (data)
|
||||
{
|
||||
DWORD written_bytes = 0;
|
||||
::WriteFile(file_handle, data.buffer, data.size, &written_bytes, NULL);
|
||||
::CloseHandle(file_handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
::CloseHandle(file_handle);
|
||||
::DeleteFile(dest_file_name.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FileUtil::ExistsFile(String const& file_path)
|
||||
{
|
||||
DWORD dwAttrib = ::GetFileAttributesW(file_path.c_str());
|
||||
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
||||
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
|
||||
bool FileUtil::ExistsDirectory(String const& dir_path)
|
||||
{
|
||||
DWORD dwAttrib = ::GetFileAttributesW(dir_path.c_str());
|
||||
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
||||
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
}
|
||||
|
|
@ -18,27 +18,27 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "DataUtil.h"
|
||||
#include "LocalStorage.h"
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
DataUtil::DataUtil(String const & file_path, String const & field)
|
||||
LocalStorage::LocalStorage(String const & file_path, String const & field)
|
||||
{
|
||||
SetFilePath(file_path);
|
||||
SetFieldName(field);
|
||||
}
|
||||
|
||||
void DataUtil::SetFilePath(String const & file_path)
|
||||
void LocalStorage::SetFilePath(String const & file_path)
|
||||
{
|
||||
file_path_ = file_path;
|
||||
}
|
||||
|
||||
void DataUtil::SetFieldName(String const & field_name)
|
||||
void LocalStorage::SetFieldName(String const & field_name)
|
||||
{
|
||||
field_name_ = field_name;
|
||||
}
|
||||
|
||||
bool DataUtil::Exists(String const& key) const
|
||||
bool LocalStorage::Exists(String const& key) const
|
||||
{
|
||||
wchar_t temp[256] = { 0 };
|
||||
::GetPrivateProfileStringW(
|
||||
|
|
@ -52,7 +52,7 @@ namespace kiwano
|
|||
return temp[0] == L'\0';
|
||||
}
|
||||
|
||||
bool DataUtil::SaveInt(String const& key, int val) const
|
||||
bool LocalStorage::SaveInt(String const& key, int val) const
|
||||
{
|
||||
BOOL ret = ::WritePrivateProfileStringW(
|
||||
field_name_.c_str(),
|
||||
|
|
@ -63,7 +63,7 @@ namespace kiwano
|
|||
return ret == TRUE;
|
||||
}
|
||||
|
||||
bool DataUtil::SaveFloat(String const& key, float val) const
|
||||
bool LocalStorage::SaveFloat(String const& key, float val) const
|
||||
{
|
||||
BOOL ret = ::WritePrivateProfileStringW(
|
||||
field_name_.c_str(),
|
||||
|
|
@ -74,7 +74,7 @@ namespace kiwano
|
|||
return ret == TRUE;
|
||||
}
|
||||
|
||||
bool DataUtil::SaveDouble(String const& key, double val) const
|
||||
bool LocalStorage::SaveDouble(String const& key, double val) const
|
||||
{
|
||||
BOOL ret = ::WritePrivateProfileStringW(
|
||||
field_name_.c_str(),
|
||||
|
|
@ -85,7 +85,7 @@ namespace kiwano
|
|||
return ret == TRUE;
|
||||
}
|
||||
|
||||
bool DataUtil::SaveBool(String const& key, bool val) const
|
||||
bool LocalStorage::SaveBool(String const& key, bool val) const
|
||||
{
|
||||
BOOL ret = ::WritePrivateProfileStringW(
|
||||
field_name_.c_str(),
|
||||
|
|
@ -96,7 +96,7 @@ namespace kiwano
|
|||
return ret == TRUE;
|
||||
}
|
||||
|
||||
bool DataUtil::SaveString(String const& key, String const& val) const
|
||||
bool LocalStorage::SaveString(String const& key, String const& val) const
|
||||
{
|
||||
BOOL ret = ::WritePrivateProfileStringW(
|
||||
field_name_.c_str(),
|
||||
|
|
@ -107,7 +107,7 @@ namespace kiwano
|
|||
return ret == TRUE;
|
||||
}
|
||||
|
||||
int DataUtil::GetInt(String const & key, int default_value) const
|
||||
int LocalStorage::GetInt(String const & key, int default_value) const
|
||||
{
|
||||
return ::GetPrivateProfileIntW(
|
||||
field_name_.c_str(),
|
||||
|
|
@ -117,7 +117,7 @@ namespace kiwano
|
|||
);
|
||||
}
|
||||
|
||||
float DataUtil::GetFloat(String const & key, float default_value) const
|
||||
float LocalStorage::GetFloat(String const & key, float default_value) const
|
||||
{
|
||||
wchar_t temp[32] = { 0 };
|
||||
String default_str = String::parse(default_value);
|
||||
|
|
@ -125,7 +125,7 @@ namespace kiwano
|
|||
return std::stof(temp);
|
||||
}
|
||||
|
||||
double DataUtil::GetDouble(String const & key, double default_value) const
|
||||
double LocalStorage::GetDouble(String const & key, double default_value) const
|
||||
{
|
||||
wchar_t temp[32] = { 0 };
|
||||
String default_str = String::parse(default_value);
|
||||
|
|
@ -133,7 +133,7 @@ namespace kiwano
|
|||
return std::stod(temp);
|
||||
}
|
||||
|
||||
bool DataUtil::GetBool(String const & key, bool default_value) const
|
||||
bool LocalStorage::GetBool(String const & key, bool default_value) const
|
||||
{
|
||||
int nValue = ::GetPrivateProfileIntW(
|
||||
field_name_.c_str(),
|
||||
|
|
@ -143,7 +143,7 @@ namespace kiwano
|
|||
return nValue == TRUE;
|
||||
}
|
||||
|
||||
String DataUtil::GetString(String const & key, String const & default_value) const
|
||||
String LocalStorage::GetString(String const & key, String const & default_value) const
|
||||
{
|
||||
wchar_t temp[256] = { 0 };
|
||||
::GetPrivateProfileStringW(
|
||||
|
|
@ -156,4 +156,4 @@ namespace kiwano
|
|||
);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,19 +25,19 @@
|
|||
namespace kiwano
|
||||
{
|
||||
//
|
||||
// 数据存取工具 (.ini 格式)
|
||||
// 一个 DataUtil 对象表示一个数据储存实体, 用于存取简单格式 (bool | int | float | double | String) 的数据
|
||||
// 本地数据存取工具
|
||||
// LocalStorage 用于在本地存取数据, 支持的数据类型包括 (bool | int | float | double | String)
|
||||
// 数据都采用 key-value (键-值) 的方式存取
|
||||
// 例如, 保存一份游戏最高分, 以便下次进行游戏时读取:
|
||||
// DataUtil data; // 创建数据对象
|
||||
// data.SaveInt(L"best score", 20); // 保存最高分 20
|
||||
// int best = data.GetInt(L"best score"); // 读取之前储存的最高分
|
||||
// LocalStorage data; // 创建数据对象
|
||||
// data.SaveInt(L"best-score", 20); // 保存最高分 20
|
||||
// int best = data.GetInt(L"best-score"); // 读取之前储存的最高分
|
||||
//
|
||||
|
||||
class KGE_API DataUtil
|
||||
class KGE_API LocalStorage
|
||||
{
|
||||
public:
|
||||
DataUtil(
|
||||
LocalStorage(
|
||||
String const& file_path = L"./data.ini", // 文件路径
|
||||
String const& field = L"defalut" // 字段名
|
||||
);
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
// 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.
|
||||
|
||||
#include "Path.h"
|
||||
#include "../platform/modules.h"
|
||||
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable:4091) // ignore warning 4091 (on winSDK 8.1)
|
||||
#include <shlobj.h>
|
||||
#pragma warning (pop)
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
namespace
|
||||
{
|
||||
// 创建指定文件夹
|
||||
bool CreateFolder(String const& dir_path)
|
||||
{
|
||||
if (dir_path.empty() || dir_path.size() >= MAX_PATH)
|
||||
return false;
|
||||
|
||||
wchar_t tmp_dir_path[MAX_PATH] = { 0 };
|
||||
std::size_t length = dir_path.length();
|
||||
|
||||
for (std::size_t i = 0; i < length; ++i)
|
||||
{
|
||||
tmp_dir_path[i] = dir_path.at(i);
|
||||
if (tmp_dir_path[i] == L'\\' || tmp_dir_path[i] == L'/' || i == (length - 1))
|
||||
{
|
||||
if (::_waccess(tmp_dir_path, 0) != 0)
|
||||
{
|
||||
if (::_wmkdir(tmp_dir_path) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
String const& Path::GetTemporaryPath()
|
||||
{
|
||||
static String temp_path;
|
||||
if (temp_path.empty())
|
||||
{
|
||||
// 设置临时文件保存路径
|
||||
wchar_t path[_MAX_PATH];
|
||||
|
||||
if (0 != ::GetTempPath(_MAX_PATH, path))
|
||||
{
|
||||
temp_path.append(path).append(L"\\KiwanoGameTemp\\");
|
||||
|
||||
if (!modules::Shlwapi::Get().PathFileExistsW(temp_path.c_str()) && !CreateFolder(temp_path))
|
||||
{
|
||||
temp_path = L"";
|
||||
}
|
||||
}
|
||||
}
|
||||
return temp_path;
|
||||
}
|
||||
|
||||
String const& Path::GetLocalAppDataPath()
|
||||
{
|
||||
static String local_app_data_path;
|
||||
if (local_app_data_path.empty())
|
||||
{
|
||||
// 获取 AppData/Local 文件夹的路径
|
||||
wchar_t path[MAX_PATH] = { 0 };
|
||||
::SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path);
|
||||
local_app_data_path = path;
|
||||
}
|
||||
|
||||
return local_app_data_path;
|
||||
}
|
||||
|
||||
String const& Path::GetExeFilePath()
|
||||
{
|
||||
static String exe_file_path;
|
||||
if (exe_file_path.empty())
|
||||
{
|
||||
TCHAR path[_MAX_PATH] = { 0 };
|
||||
if (::GetModuleFileName(nullptr, path, _MAX_PATH) != 0)
|
||||
{
|
||||
exe_file_path = path;
|
||||
}
|
||||
}
|
||||
return exe_file_path;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// 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 "../macros.h"
|
||||
#include "../core/core.h"
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
// 路径
|
||||
class KGE_API Path
|
||||
{
|
||||
public:
|
||||
// 获取临时文件目录
|
||||
static String const& GetTemporaryPath();
|
||||
|
||||
// 获取 LocalAppData 目录
|
||||
static String const& GetLocalAppDataPath();
|
||||
|
||||
// 获取当前程序的运行路径
|
||||
static String const& GetExeFilePath();
|
||||
};
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
#include "../base/Resource.h"
|
||||
#include "../2d/include-forwards.h"
|
||||
#include "../renderer/GifImage.h"
|
||||
#include <tinyxml2/tinyxml2.h>
|
||||
#include <3rd-party/tinyxml2/tinyxml2.h>
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue