diff --git a/.gitignore b/.gitignore
index 17c3d9fa..e430d78f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,4 +26,6 @@ packages/
!*.lib
# Resources bin
-*.aps
\ No newline at end of file
+*.aps
+
+docs/
\ No newline at end of file
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 00000000..146898d9
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,90 @@
+# Doxyfile 1.8.16
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+PROJECT_NAME = "Kiwano Engine"
+PROJECT_NUMBER = v1.0.0
+PROJECT_BRIEF =
+PROJECT_LOGO = logo/logo_square_tiny.png
+
+DOXYFILE_ENCODING = UTF-8
+CREATE_SUBDIRS = YES
+
+OUTPUT_LANGUAGE = Chinese
+OUTPUT_DIRECTORY = docs/
+
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = NO
+
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+
+SHOW_INCLUDE_FILES = YES
+SHOW_USED_FILES = NO
+SHOW_FILES = NO
+SHOW_NAMESPACES = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+INPUT = src/
+INPUT_ENCODING = gb2312
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++
+
+RECURSIVE = YES
+EXCLUDE = src/3rd-party \
+ src/kiwano/platform/win32 \
+ src/kiwano/renderer/win32
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = YES
+PREDEFINED = KGE_API= \
+ KGE_DOXYGEN_DO_NOT_INCLUDE=
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_EXTRA_STYLESHEET =
+
+GENERATE_TREEVIEW = YES
+ENUM_VALUES_PER_LINE = 4
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LATEX output
+#---------------------------------------------------------------------------
+
+GENERATE_LATEX = NO
diff --git a/logo/logo_square_tiny.png b/logo/logo_square_tiny.png
new file mode 100644
index 00000000..63829ef3
Binary files /dev/null and b/logo/logo_square_tiny.png differ
diff --git a/projects/3rd-party/Box2D/libBox2D.vcxproj b/projects/3rd-party/Box2D/libBox2D.vcxproj
index d4adf92f..7e2bab7c 100644
--- a/projects/3rd-party/Box2D/libBox2D.vcxproj
+++ b/projects/3rd-party/Box2D/libBox2D.vcxproj
@@ -185,4 +185,4 @@
-
\ No newline at end of file
+
diff --git a/projects/3rd-party/StackWalker/libStackWalker.vcxproj b/projects/3rd-party/StackWalker/libStackWalker.vcxproj
deleted file mode 100644
index 8907d076..00000000
--- a/projects/3rd-party/StackWalker/libStackWalker.vcxproj
+++ /dev/null
@@ -1,97 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
-
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2}
- libStackWalker
-
-
-
- StaticLibrary
- true
- Unicode
- $(DefaultPlatformToolset)
-
-
- StaticLibrary
- false
- false
- Unicode
- $(DefaultPlatformToolset)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
- $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
- true
-
-
- $(SolutionDir)\output\$(PlatformToolset)\$(Platform)\$(Configuration)\
- $(SolutionDir)\build\$(PlatformToolset)\$(Platform)\$(Configuration)\$(ProjectName)\
- true
-
-
-
- Level3
- Disabled
- true
- None
- true
- ../../../src/3rd-party;
- false
-
-
- Windows
- true
-
-
-
-
- Level3
- MaxSpeed
- true
- true
- false
- true
- None
- true
- ../../../src/3rd-party;
- false
-
-
- Windows
- false
- true
- true
-
-
-
-
-
-
\ No newline at end of file
diff --git a/projects/3rd-party/StackWalker/libStackWalker.vcxproj.filters b/projects/3rd-party/StackWalker/libStackWalker.vcxproj.filters
deleted file mode 100644
index 08a3c777..00000000
--- a/projects/3rd-party/StackWalker/libStackWalker.vcxproj.filters
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/projects/3rd-party/curl/libcurl.vcxproj b/projects/3rd-party/curl/libcurl.vcxproj
index 9a4c7664..4fa3e9d3 100644
--- a/projects/3rd-party/curl/libcurl.vcxproj
+++ b/projects/3rd-party/curl/libcurl.vcxproj
@@ -102,4 +102,4 @@
-
\ No newline at end of file
+
diff --git a/projects/3rd-party/imgui/libimgui.vcxproj b/projects/3rd-party/imgui/libimgui.vcxproj
index 0912e006..10ff944f 100644
--- a/projects/3rd-party/imgui/libimgui.vcxproj
+++ b/projects/3rd-party/imgui/libimgui.vcxproj
@@ -102,4 +102,4 @@
-
\ No newline at end of file
+
diff --git a/projects/3rd-party/tinyxml2/libtinyxml2.vcxproj b/projects/3rd-party/tinyxml2/libtinyxml2.vcxproj
index d6ba3b24..8d2e1039 100644
--- a/projects/3rd-party/tinyxml2/libtinyxml2.vcxproj
+++ b/projects/3rd-party/tinyxml2/libtinyxml2.vcxproj
@@ -94,4 +94,4 @@
-
\ No newline at end of file
+
diff --git a/projects/Kiwano.sln b/projects/Kiwano.sln
index 3cf1ce1f..2899bd53 100644
--- a/projects/Kiwano.sln
+++ b/projects/Kiwano.sln
@@ -14,8 +14,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kiwano-physics", "kiwano-ph
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3rd-party", "3rd-party", "{2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libStackWalker", "3rd-party\StackWalker\libStackWalker.vcxproj", "{3A3948DC-9865-46B3-B7B9-7E5572704ED2}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtinyxml2", "3rd-party\tinyxml2\libtinyxml2.vcxproj", "{AB47E875-85E5-4105-A71E-88930EAAB910}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libimgui", "3rd-party\imgui\libimgui.vcxproj", "{7FA1E56D-62AC-47D1-97D1-40B302724198}"
@@ -47,10 +45,10 @@ Global
{A7062ED8-8910-48A5-A3BC-C1612672571F}.Debug|Win32.Build.0 = Debug|Win32
{A7062ED8-8910-48A5-A3BC-C1612672571F}.Release|Win32.ActiveCfg = Release|Win32
{A7062ED8-8910-48A5-A3BC-C1612672571F}.Release|Win32.Build.0 = Release|Win32
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Debug|Win32.ActiveCfg = Debug|Win32
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Debug|Win32.Build.0 = Debug|Win32
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Release|Win32.ActiveCfg = Release|Win32
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2}.Release|Win32.Build.0 = Release|Win32
+ {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.Build.0 = Debug|Win32
+ {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.ActiveCfg = Release|Win32
+ {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.Build.0 = Release|Win32
{AB47E875-85E5-4105-A71E-88930EAAB910}.Debug|Win32.ActiveCfg = Debug|Win32
{AB47E875-85E5-4105-A71E-88930EAAB910}.Debug|Win32.Build.0 = Debug|Win32
{AB47E875-85E5-4105-A71E-88930EAAB910}.Release|Win32.ActiveCfg = Release|Win32
@@ -67,16 +65,11 @@ Global
{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Debug|Win32.Build.0 = Debug|Win32
{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Release|Win32.ActiveCfg = Release|Win32
{0CBA9295-F14D-4966-A7C4-1DD68158176C}.Release|Win32.Build.0 = Release|Win32
- {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.ActiveCfg = Debug|Win32
- {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Debug|Win32.Build.0 = Debug|Win32
- {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.ActiveCfg = Release|Win32
- {DF599AFB-744F-41E5-AF0C-2146F90575C8}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {3A3948DC-9865-46B3-B7B9-7E5572704ED2} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
{AB47E875-85E5-4105-A71E-88930EAAB910} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
{7FA1E56D-62AC-47D1-97D1-40B302724198} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
{A9ABACC7-75A1-46BA-8E48-4105346D9719} = {2D8919F2-8922-4B3F-8F68-D4127C6BCBB7}
diff --git a/projects/kiwano-audio/kiwano-audio.vcxproj b/projects/kiwano-audio/kiwano-audio.vcxproj
index 4bb63a42..7836bc77 100644
--- a/projects/kiwano-audio/kiwano-audio.vcxproj
+++ b/projects/kiwano-audio/kiwano-audio.vcxproj
@@ -1,7 +1,7 @@
-
+
@@ -19,7 +19,7 @@
-
+
@@ -39,7 +39,7 @@
StaticLibrary
false
- false
+ true
Unicode
$(DefaultPlatformToolset)
@@ -108,4 +108,4 @@
-
\ No newline at end of file
+
diff --git a/projects/kiwano-audio/kiwano-audio.vcxproj.filters b/projects/kiwano-audio/kiwano-audio.vcxproj.filters
index 2e5726c2..a842f4fe 100644
--- a/projects/kiwano-audio/kiwano-audio.vcxproj.filters
+++ b/projects/kiwano-audio/kiwano-audio.vcxproj.filters
@@ -3,16 +3,16 @@
-
+
-
+
\ No newline at end of file
diff --git a/projects/kiwano-imgui/kiwano-imgui.vcxproj b/projects/kiwano-imgui/kiwano-imgui.vcxproj
index faecc0d6..55833de5 100644
--- a/projects/kiwano-imgui/kiwano-imgui.vcxproj
+++ b/projects/kiwano-imgui/kiwano-imgui.vcxproj
@@ -38,7 +38,7 @@
StaticLibrary
false
- false
+ true
Unicode
$(DefaultPlatformToolset)
@@ -110,4 +110,4 @@
-
\ No newline at end of file
+
diff --git a/projects/kiwano-network/kiwano-network.vcxproj b/projects/kiwano-network/kiwano-network.vcxproj
index 4192e881..6883d0be 100644
--- a/projects/kiwano-network/kiwano-network.vcxproj
+++ b/projects/kiwano-network/kiwano-network.vcxproj
@@ -34,7 +34,7 @@
StaticLibrary
false
- false
+ true
Unicode
$(DefaultPlatformToolset)
@@ -106,4 +106,4 @@
-
\ No newline at end of file
+
diff --git a/projects/kiwano-physics/kiwano-physics.vcxproj b/projects/kiwano-physics/kiwano-physics.vcxproj
index cc69700c..33cce9e7 100644
--- a/projects/kiwano-physics/kiwano-physics.vcxproj
+++ b/projects/kiwano-physics/kiwano-physics.vcxproj
@@ -13,6 +13,7 @@
+
@@ -24,6 +25,7 @@
+
@@ -44,7 +46,7 @@
StaticLibrary
false
- false
+ true
Unicode
$(DefaultPlatformToolset)
diff --git a/projects/kiwano-physics/kiwano-physics.vcxproj.filters b/projects/kiwano-physics/kiwano-physics.vcxproj.filters
index a927a9b3..e4f5fe7f 100644
--- a/projects/kiwano-physics/kiwano-physics.vcxproj.filters
+++ b/projects/kiwano-physics/kiwano-physics.vcxproj.filters
@@ -10,6 +10,7 @@
+
@@ -19,5 +20,6 @@
+
\ No newline at end of file
diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj
index ffe0546b..eab6029a 100644
--- a/projects/kiwano/kiwano.vcxproj
+++ b/projects/kiwano/kiwano.vcxproj
@@ -11,24 +11,16 @@
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -37,8 +29,7 @@
-
-
+
@@ -48,7 +39,7 @@
-
+
@@ -66,15 +57,18 @@
-
+
+
+
-
+
+
@@ -86,6 +80,7 @@
+
@@ -111,17 +106,21 @@
-
+
-
+
+
+
+
+
@@ -130,13 +129,14 @@
-
+
+
-
+
@@ -166,9 +166,6 @@
-
- {3a3948dc-9865-46b3-b7b9-7e5572704ed2}
-
{ab47e875-85e5-4105-a71e-88930eaab910}
@@ -187,7 +184,7 @@
StaticLibrary
false
- false
+ true
Unicode
$(DefaultPlatformToolset)
diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters
index 87053e5a..dce7c87c 100644
--- a/projects/kiwano/kiwano.vcxproj.filters
+++ b/projects/kiwano/kiwano.vcxproj.filters
@@ -25,14 +25,14 @@
{9314f30d-5742-48b6-94e5-e3b4284106f6}
-
- {86e2d0f2-a9d0-4456-b6a5-d480228bbf82}
-
{30333461-e9bc-4709-84bd-ce6e0e1a3079}
-
- {192a47a9-9df6-4f40-a7d3-888eb00c53ac}
+
+ {e84dcf9a-e650-473e-8c9c-193804ab9e76}
+
+
+ {c629aedd-ffb9-4bc1-82c3-f50e77c82e77}
@@ -45,21 +45,12 @@
2d
-
- 2d
-
2d
2d
-
- 2d
-
-
- 2d
-
2d
@@ -72,9 +63,6 @@
core
-
- core
-
core
@@ -93,9 +81,6 @@
platform
-
- platform
-
@@ -150,33 +135,6 @@
2d
-
- common
-
-
- common
-
-
- common
-
-
- common
-
-
- common
-
-
- common
-
-
- common
-
-
- common
-
-
- common
-
2d
@@ -240,9 +198,6 @@
renderer
-
- renderer
-
2d
@@ -267,27 +222,15 @@
math
-
- core\win32
-
-
- core\win32
-
utils
-
- common
-
utils
core
-
- core
-
platform
@@ -303,6 +246,48 @@
platform
+
+ 2d
+
+
+ core
+
+
+ core
+
+
+ renderer
+
+
+ renderer\win32
+
+
+ renderer
+
+
+ platform\win32
+
+
+ platform\win32
+
+
+ platform\win32
+
+
+ core\event
+
+
+ core\event
+
+
+ core\event
+
+
+ core\event
+
+
+ core\event
+
@@ -320,9 +305,6 @@
2d
-
- 2d
-
2d
@@ -341,9 +323,6 @@
platform
-
- platform
-
core
@@ -443,9 +422,6 @@
renderer
-
- renderer
-
2d
@@ -470,9 +446,6 @@
core
-
- core
-
platform
@@ -485,5 +458,32 @@
platform
+
+ 2d
+
+
+ core
+
+
+ renderer
+
+
+ platform\win32
+
+
+ platform\win32
+
+
+ core\event
+
+
+ core\event
+
+
+ core\event
+
+
+ core\event
+
\ No newline at end of file
diff --git a/scripts/appveyor/clear_project_configuration.ps1 b/scripts/appveyor/clear_project_configuration.ps1
index 05b9fba9..185ad6bf 100644
--- a/scripts/appveyor/clear_project_configuration.ps1
+++ b/scripts/appveyor/clear_project_configuration.ps1
@@ -3,14 +3,19 @@ function Set-FileConfiguration {
[string]$filePath
)
- $replace = "(EditAndContinue|ProgramDatabase)"
- $replaceTo = "None"
+ $debugInfoReplace = "(EditAndContinue|ProgramDatabase)"
+ $debugInfoReplaceTo = "None"
+
+ $optimizationReplace = "true"
+ $optimizationReplaceTo = "false"
# Create a copy of .vcxproj file
Copy-Item -Path $filePath -Destination ($filePath + '.template')
# Overlay some configurations
- Get-Content ($filePath + '.template') -Encoding UTF8 | ForEach-Object { $_ -replace $replace, $replaceTo } | Out-File $filePath -Encoding UTF8
+ Get-Content ($filePath + '.template') -Encoding UTF8 | ForEach-Object {
+ ( $_ -replace $debugInfoReplace, $debugInfoReplaceTo ) -replace $optimizationReplace, $optimizationReplaceTo
+ } | Out-File $filePath -Encoding UTF8
# Delete the copy file
Remove-Item -Path ($filePath + '.template')
@@ -24,3 +29,12 @@ Get-ChildItem -Path 'projects\' -Directory | ForEach-Object {
Set-FileConfiguration ($dirPath + '\' + $_)
}
}
+
+Get-ChildItem -Path 'projects\3rd-party' -Directory | ForEach-Object {
+ $dirPath = "projects\3rd-party\$($_)"
+
+ # Search all vcxproj files
+ Get-ChildItem -Path $dirPath *.vcxproj -File | ForEach-Object {
+ Set-FileConfiguration ($dirPath + '\' + $_)
+ }
+}
diff --git a/src/3rd-party/OuterC/LICENSE b/src/3rd-party/OuterC/LICENSE
new file mode 100644
index 00000000..9e74ea5c
--- /dev/null
+++ b/src/3rd-party/OuterC/LICENSE
@@ -0,0 +1,21 @@
+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/kiwano/common/any.hpp b/src/3rd-party/OuterC/oc/any.h
similarity index 86%
rename from src/kiwano/common/any.hpp
rename to src/3rd-party/OuterC/oc/any.h
index 0b3dfd6d..fa4594b5 100644
--- a/src/kiwano/common/any.hpp
+++ b/src/3rd-party/OuterC/oc/any.h
@@ -1,32 +1,11 @@
-// 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.
+// Copyright (c) 2019-2020 OuterC - Nomango
#pragma once
#include
#include
#include
-namespace kiwano
-{
-
-namespace common
+namespace oc
{
class bad_any_cast : public std::exception
@@ -133,7 +112,7 @@ public:
template
const _Ty* cast_pointer() const noexcept
{
- static_assert(!std::is_void<_Ty>::value, "kiwano::any cannot contain void");
+ 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)))
@@ -519,14 +498,14 @@ _Ty any_cast(any&& a)
return static_cast<_Ty>(std::move(*ptr));
}
-} // namespace common
-
-} // namespace kiwano
+} // namespace oc
namespace std
{
- inline void swap(kiwano::common::any& lhs, kiwano::common::any& rhs) noexcept
- {
- lhs.swap(rhs);
- }
+
+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
new file mode 100644
index 00000000..af9cce32
--- /dev/null
+++ b/src/3rd-party/OuterC/oc/function.h
@@ -0,0 +1,169 @@
+// 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
new file mode 100644
index 00000000..9abefaa1
--- /dev/null
+++ b/src/3rd-party/OuterC/oc/function/details.h
@@ -0,0 +1,168 @@
+// 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 (static_cast<_Ty*>(ptr_)->*func_)(::std::forward<_Args>(args)...);
+ }
+
+ static inline callable<_Ret, _Args...>* make(void* ptr, _FuncType func)
+ {
+ return new (::std::nothrow) proxy_mem_callable<_Ty, _Ret, _Args...>(ptr, func);
+ }
+
+protected:
+ proxy_mem_callable(void* ptr, _FuncType func)
+ : ptr_(ptr)
+ , func_(func)
+ {
+ }
+
+protected:
+ void* 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 (static_cast<_Ty*>(ptr_)->*func_)(::std::forward<_Args>(args)...);
+ }
+
+ static inline callable<_Ret, _Args...>* make(void* ptr, _FuncType func)
+ {
+ return new (::std::nothrow) proxy_const_mem_callable<_Ty, _Ret, _Args...>(ptr, func);
+ }
+
+protected:
+ proxy_const_mem_callable(void* ptr, _FuncType func)
+ : ptr_(ptr)
+ , func_(func)
+ {
+ }
+
+protected:
+ void* 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
new file mode 100644
index 00000000..7138a22c
--- /dev/null
+++ b/src/3rd-party/OuterC/oc/intrusive_list.h
@@ -0,0 +1,254 @@
+// 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_type = _PTy;
+ using const_pointer_type = const _PTy;
+
+ intrusive_list_item() : prev_(nullptr), next_(nullptr) {}
+ intrusive_list_item(pointer_type rhs) : prev_(nullptr), next_(nullptr) { if (rhs) { prev_ = rhs->prev_; next_ = rhs->next_; } }
+
+ const_pointer_type prev_item() const { return prev_; }
+ pointer_type prev_item() { return prev_; }
+ const_pointer_type next_item() const { return next_; }
+ pointer_type next_item() { return next_; }
+
+private:
+ pointer_type prev_;
+ pointer_type next_;
+
+ friend class intrusive_list<_Ty, _PTy>;
+};
+
+
+template
+class intrusive_list
+{
+public:
+ using pointer_type = _PTy;
+ using const_pointer_type = const _PTy;
+
+ intrusive_list() : first_(), last_() {}
+ ~intrusive_list() { clear(); }
+
+ const_pointer_type first_item() const { return first_; }
+ pointer_type first_item() { return first_; }
+ const_pointer_type last_item() const { return last_; }
+ pointer_type last_item() { return last_; }
+
+ inline bool empty() const
+ {
+ return first_ == nullptr;
+ }
+
+ void push_back(pointer_type 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_type 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_type child, pointer_type 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_type child, pointer_type 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_type 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_type p = first_;
+ while (p)
+ {
+ pointer_type 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_type p = first_;
+ pointer_type 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 pointer_type = _PTy;
+ using const_pointer_type = const _PTy;
+
+ inline iterator_impl(pointer_type ptr = nullptr, bool is_end = false) : base_(ptr), is_end_(is_end) {}
+
+ inline pointer_type operator*() const { OC_ASSERT(base_ && !is_end_); return base_; }
+ inline iterator_impl& operator++() { OC_ASSERT(base_ && !is_end_); pointer_type 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_type(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_type 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_type front() { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); }
+ inline const_pointer_type front() const { if (empty()) throw std::out_of_range("front() called on empty intrusive_list"); return first_item(); }
+ inline pointer_type back() { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); }
+ inline const_pointer_type back() const { if (empty()) throw std::out_of_range("back() called on empty intrusive_list"); return last_item(); }
+
+private:
+ pointer_type first_;
+ pointer_type last_;
+};
+
+} // namespace oc
diff --git a/src/3rd-party/OuterC/oc/intrusive_ptr.h b/src/3rd-party/OuterC/oc/intrusive_ptr.h
new file mode 100644
index 00000000..e13aef0c
--- /dev/null
+++ b/src/3rd-party/OuterC/oc/intrusive_ptr.h
@@ -0,0 +1,201 @@
+// 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
new file mode 100644
index 00000000..e61c0d95
--- /dev/null
+++ b/src/3rd-party/OuterC/oc/json.h
@@ -0,0 +1,50 @@
+// Copyright (c) 2019-2020 OuterC - Nomango
+
+#pragma once
+#include